aboutsummaryrefslogtreecommitdiffstats
path: root/logging/encoding.go
diff options
context:
space:
mode:
authorMarc Pervaz Boocha <mboocha@sudomsg.com>2026-02-28 00:16:22 +0530
committerMarc Pervaz Boocha <mboocha@sudomsg.com>2026-02-28 00:16:22 +0530
commit1c75db8c1d1dc6a0a9097016dbdbbb4348f5c835 (patch)
treee3aa95caea8ea13b2e50b69babad2ab9eebfa0f2 /logging/encoding.go
parentAdd Syslog and refactored the Sink api (diff)
downloadkit-main.tar
kit-main.tar.gz
kit-main.tar.bz2
kit-main.tar.lz
kit-main.tar.xz
kit-main.tar.zst
kit-main.zip
Add Host Loggermain
Diffstat (limited to 'logging/encoding.go')
-rw-r--r--logging/encoding.go125
1 files changed, 125 insertions, 0 deletions
diff --git a/logging/encoding.go b/logging/encoding.go
new file mode 100644
index 0000000..c4de0c8
--- /dev/null
+++ b/logging/encoding.go
@@ -0,0 +1,125 @@
+package logging
+
+import (
+ "encoding/json"
+ "fmt"
+ "iter"
+ "log/slog"
+ "runtime"
+ "slices"
+ "strings"
+)
+
+func RecordAll(r slog.Record, replaceAttr func(groups []string, a slog.Attr) slog.Attr) iter.Seq2[[]string, slog.Attr] {
+ return func(yield func([]string, slog.Attr) bool) {
+ var walk func([]string, slog.Attr) bool
+ walk = func(groups []string, a slog.Attr) bool {
+ if replaceAttr != nil {
+ a = replaceAttr(groups, a)
+ }
+
+ if a.Key == "" {
+ return true
+ }
+
+ a.Value = a.Value.Resolve()
+
+ if a.Value.Kind() == slog.KindGroup {
+ newGroups := append(slices.Clone(groups), a.Key)
+ for _, child := range a.Value.Group() {
+ if !walk(newGroups, child) {
+ return false
+ }
+ }
+ return true
+ }
+
+ return yield(groups, a)
+ }
+
+ if !r.Time.IsZero() {
+ if !walk([]string{}, slog.Time(slog.TimeKey, r.Time)) {
+ return
+ }
+ }
+
+ if !walk([]string{}, slog.Any(slog.LevelKey, r.Level)) {
+ return
+ }
+ if !walk([]string{}, slog.String(slog.MessageKey, r.Message)) {
+ return
+ }
+
+ if r.PC != 0 {
+ if !walk([]string{}, slog.Uint64(slog.SourceKey, uint64(r.PC))) {
+ return
+ }
+ }
+
+ r.Attrs(func(attr slog.Attr) bool {
+ return walk([]string{}, attr)
+ })
+ }
+}
+
+type Encoder func(iter.Seq2[[]string, slog.Attr]) (string, error)
+
+func LogFmtEncoder(attrs iter.Seq2[[]string, slog.Attr]) (string, error) {
+ str := []string{}
+ for groups, attr := range attrs {
+ if len(groups) == 0 && attr.Key == slog.SourceKey {
+ pc := uintptr(attr.Value.Uint64())
+ fs := runtime.CallersFrames([]uintptr{pc})
+ f, _ := fs.Next()
+ attr.Value = slog.StringValue(fmt.Sprintf("%s:%d", f.File, f.Line))
+ }
+
+ str = append(str, fmt.Sprintf("%s=%q", strings.Join(append(groups, attr.Key), "."), attr.Value))
+ }
+
+ return strings.Join(str, " "), nil
+}
+
+func ToMap(seq iter.Seq2[[]string, slog.Attr]) map[string]any {
+ out := make(map[string]any)
+ for groups, attr := range seq {
+ current := out
+ for _, group := range groups {
+ if next, ok := current[group].(map[string]any); ok {
+ current = next
+ } else {
+ newMap := make(map[string]any)
+ current[group] = newMap
+ current = newMap
+ }
+ }
+ current[attr.Key] = attr.Value.Any()
+ }
+ return out
+}
+
+func JSONEncoder(attrs iter.Seq2[[]string, slog.Attr]) (string, error) {
+ m := ToMap(attrs)
+ if v, ok := m[slog.SourceKey]; ok {
+ pc := v.(uint64)
+ fs := runtime.CallersFrames([]uintptr{uintptr(pc)})
+ f, _ := fs.Next()
+ m[slog.SourceKey] = fmt.Sprintf("%s:%d", f.File, f.Line)
+ }
+
+ b, err := json.Marshal(m)
+ if err != nil {
+ return "", err
+ }
+
+ return string(b), nil
+}
+
+func MessageEncoder(attrs iter.Seq2[[]string, slog.Attr]) (string, error) {
+ for groups, attr := range attrs {
+ if len(groups) == 0 && attr.Key == slog.MessageKey {
+ return attr.Value.String(), nil
+ }
+ }
+ return "", nil
+}