Skip to content

Commit 0ac48ad

Browse files
committed
Fix embedded fields in reflection encoder
1 parent 76642ac commit 0ac48ad

File tree

2 files changed

+65
-39
lines changed

2 files changed

+65
-39
lines changed

slogval/reflect.go

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,19 @@ import (
1212
"go.coder.com/slog"
1313
)
1414

15+
// Reflector is implemented by a value passed to Field
16+
// that would like to only use the reflection based
17+
// converter for itself and ignore interfaces like error
18+
// or fmt.Stringer.
19+
// TODO add back ValueFunc
20+
type Reflector interface {
21+
LogWithReflect()
22+
}
23+
1524
// Reflect uses reflection to convert the slice of fields into a ordered
1625
// map that uses only the primitive value types defined in this package.
26+
// It uses interfaces like error and fmt.Stringer where appropriate.
27+
// Have a type implement Reflector if you would like to force
1728
func Reflect(fs []slog.Field) Map {
1829
var m Map
1930
for _, f := range fs {
@@ -39,6 +50,9 @@ func reflectValue(rv reflect.Value) Value {
3950

4051
typ := rv.Type()
4152
switch {
53+
case implements(typ, (*Reflector)(nil)):
54+
// Skip checking for any other interfaces as the value wants
55+
//
4256
case implements(typ, (*Value)(nil)):
4357
v := rv.MethodByName("isSlogCoreValue").Call(nil)
4458
return v[0].Interface().(Value)
@@ -109,35 +123,41 @@ func reflectValue(rv reflect.Value) Value {
109123
m.sort()
110124
return m
111125
case reflect.Struct:
112-
typ := rv.Type()
113-
114-
f := make(Map, 0, typ.NumField())
126+
m := make(Map, 0, typ.NumField())
127+
m = reflectStruct(m, rv, typ)
128+
return m
129+
default:
130+
return String(fmt.Sprintf("%v", rv))
131+
}
132+
}
115133

116-
for i := 0; i < typ.NumField(); i++ {
117-
ft := typ.Field(i)
118-
fv := rv.Field(i)
134+
func reflectStruct(m Map, rv reflect.Value, typ reflect.Type) Map {
135+
for i := 0; i < typ.NumField(); i++ {
136+
ft := typ.Field(i)
137+
fv := rv.Field(i)
119138

120-
if ft.Tag.Get("log") == "-" {
121-
continue
122-
}
123-
if implements(typ, (*proto.Message)(nil)) && strings.HasPrefix(ft.Name, "XXX_") {
124-
// Have to ignore XXX_ fields for protobuf messages.
125-
continue
126-
}
139+
if ft.Tag.Get("log") == "-" {
140+
continue
141+
}
142+
if implements(typ, (*proto.Message)(nil)) && strings.HasPrefix(ft.Name, "XXX_") {
143+
// Have to ignore XXX_ fields for protobuf messages.
144+
continue
145+
}
127146

128-
v := reflectValue(fv)
129-
name := ft.Tag.Get("log")
130-
if name == "" {
131-
name = snakecase(ft.Name)
132-
}
133-
f = f.appendVal(name, v)
147+
if ft.Anonymous {
148+
m = reflectStruct(m, fv, ft.Type)
149+
continue
150+
}
134151

152+
v := reflectValue(fv)
153+
name := ft.Tag.Get("log")
154+
if name == "" {
155+
name = snakecase(ft.Name)
135156
}
157+
m = m.appendVal(name, v)
136158

137-
return f
138-
default:
139-
return String(fmt.Sprintf("%v", rv))
140159
}
160+
return m
141161
}
142162

143163
func snakecase(s string) string {

slogval/reflect_test.go

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,20 @@ go.coder.com/slog/slogval.TestReflect
5454
},
5555
},
5656
{
57-
name: "logTag",
58-
in: struct {
59-
a string `log:"-"`
60-
b string `log:"hi"`
61-
c string `log:"f"`
62-
}{
63-
"a",
64-
"b",
65-
"c",
66-
},
67-
out: Map{
68-
{"hi", String("b")},
69-
{"f", String("c")},
70-
},
71-
},
72-
{
73-
name: "LogValue",
57+
name: "logValue",
7458
in: myStruct{},
7559
out: String("hi"),
7660
},
61+
{
62+
name: "embeddedStruct",
63+
in: outerStruct{},
64+
out: Map{
65+
{"field_3", Int(0)},
66+
{"field_5", Int(0)},
67+
{"field_1", String("")},
68+
{"field_2", Int(0)},
69+
},
70+
},
7771
}
7872

7973
for _, tc := range testCases {
@@ -102,3 +96,15 @@ type myStruct struct{}
10296
func (m myStruct) LogValue() interface{} {
10397
return "hi"
10498
}
99+
100+
type outerStruct struct {
101+
innerStruct
102+
103+
field1 string
104+
field2 int
105+
}
106+
107+
type innerStruct struct {
108+
field3 int
109+
field5 int
110+
}

0 commit comments

Comments
 (0)