Skip to content

Commit 52d15d5

Browse files
committed
feat(logger): add WithFields/FieldsFromContext methods for context
1 parent b89ccae commit 52d15d5

File tree

4 files changed

+81
-3
lines changed

4 files changed

+81
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## v3.116.4
2+
* Added helper methods `WithFields` and `FieldsFromContext` for working with structured logging fields via context.
3+
These methods allow adding custom fields to the context, which are later extracted by the logger.
4+
15
## v3.116.3
26
* Default grpc message size adjusted to the server's defaults
37

log/context.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import (
44
"context"
55
)
66

7+
type FieldsType map[string]string
8+
79
type (
8-
ctxLevelKey struct{}
9-
ctxNamesKey struct{}
10+
ctxLevelKey struct{}
11+
ctxNamesKey struct{}
12+
ctxFieldsKey struct{}
1013
)
1114

1215
func WithLevel(ctx context.Context, lvl Level) context.Context {
@@ -36,6 +39,29 @@ func NamesFromContext(ctx context.Context) []string {
3639
return v[:len(v):len(v)] // prevent re
3740
}
3841

42+
func WithFields(ctx context.Context, fields FieldsType) context.Context {
43+
existing := FieldsFromContext(ctx)
44+
merged := make(FieldsType, len(existing)+len(fields))
45+
46+
for k, v := range existing {
47+
merged[k] = v
48+
}
49+
50+
for k, v := range fields {
51+
merged[k] = v
52+
}
53+
54+
return context.WithValue(ctx, ctxFieldsKey{}, merged)
55+
}
56+
57+
func FieldsFromContext(ctx context.Context) FieldsType {
58+
if fields, _ := ctx.Value(ctxFieldsKey{}).(FieldsType); fields != nil {
59+
return fields
60+
}
61+
62+
return FieldsType{}
63+
}
64+
3965
func with(ctx context.Context, lvl Level, names ...string) context.Context {
4066
return WithLevel(WithNames(ctx, names...), lvl)
4167
}

log/context_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,37 @@ func TestWithNamesRaceRegression(t *testing.T) {
9090
}
9191
})
9292
}
93+
94+
func TestFieldsFromContext(t *testing.T) {
95+
for _, tt := range []struct {
96+
ctx context.Context //nolint:containedctx
97+
fields FieldsType
98+
}{
99+
{
100+
ctx: context.Background(),
101+
fields: FieldsType{},
102+
},
103+
{
104+
ctx: WithFields(context.Background(), FieldsType{"a": "1", "b": "1"}),
105+
fields: FieldsType{"a": "1", "b": "1"},
106+
},
107+
{
108+
ctx: WithFields(
109+
WithFields(context.Background(), FieldsType{"a": "1", "b": "1"}),
110+
FieldsType{"a": "2", "b": "2"},
111+
),
112+
fields: FieldsType{"a": "2", "b": "2"},
113+
},
114+
{
115+
ctx: WithFields(
116+
WithFields(context.Background(), FieldsType{"a": "1", "b": "1"}),
117+
FieldsType{"a": "3"},
118+
),
119+
fields: FieldsType{"a": "3", "b": "1"},
120+
},
121+
} {
122+
t.Run("", func(t *testing.T) {
123+
require.Equal(t, tt.fields, FieldsFromContext(tt.ctx))
124+
})
125+
}
126+
}

log/logger.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,23 @@ func (l *defaultLogger) Log(ctx context.Context, msg string, fields ...Field) {
9090
return
9191
}
9292

93+
additionalFields := FieldsFromContext(ctx)
94+
var merged []Field
95+
if len(additionalFields) > 0 {
96+
merged = make([]Field, 0, len(additionalFields)+len(fields))
97+
98+
for k, v := range additionalFields {
99+
merged = append(merged, String(k, v))
100+
}
101+
102+
merged = append(merged, fields...)
103+
} else {
104+
merged = fields
105+
}
106+
93107
_, _ = io.WriteString(l.w, l.format(
94108
NamesFromContext(ctx),
95-
l.appendFields(msg, fields...),
109+
l.appendFields(msg, merged...),
96110
lvl,
97111
)+"\n")
98112
}

0 commit comments

Comments
 (0)