Compare commits

...

5 Commits

Author SHA1 Message Date
84024f7713 Merge pull request #180 from unistack-org/logger-wrapper
logger/unwrap: support sql and proto wrapper types
2023-02-06 18:55:39 +03:00
5a554f9f0c fixup
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2023-02-06 18:53:27 +03:00
9c33cbc8e2 logger/unwrap: support sql and proto wrapper types
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2023-02-06 18:50:00 +03:00
848fe1c0d4 Merge pull request #179 from unistack-org/logger-unwrap
logger/unwrap: fix unwrap format
2023-02-03 23:36:47 +03:00
6cbf23fec5 logger/unwrap: fix unwrap format
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2023-02-03 23:33:24 +03:00
2 changed files with 78 additions and 16 deletions

View File

@@ -47,12 +47,15 @@ var (
)
type unwrap struct {
val interface{}
s fmt.State
pointers map[uintptr]int
opts *Options
depth int
ignoreNextType bool
val interface{}
s fmt.State
pointers map[uintptr]int
opts *Options
depth int
ignoreNextType bool
takeAll bool
protoWrapperType bool
sqlWrapperType bool
}
// Options struct
@@ -242,9 +245,23 @@ func (f *unwrap) format(v reflect.Value) {
}
// Handle pointers specially.
if kind == reflect.Ptr {
switch kind {
case reflect.Ptr:
if !v.IsZero() {
if strings.HasPrefix(reflect.Indirect(v).Type().String(), "wrapperspb.") {
f.protoWrapperType = true
} else if strings.HasPrefix(reflect.Indirect(v).Type().String(), "sql.Null") {
f.sqlWrapperType = true
}
}
f.formatPtr(v)
return
case reflect.Struct:
if !v.IsZero() {
if strings.HasPrefix(reflect.Indirect(v).Type().String(), "sql.Null") {
f.sqlWrapperType = true
}
}
}
// get type information unless already handled elsewhere.
@@ -353,9 +370,19 @@ func (f *unwrap) format(v reflect.Value) {
f.depth++
vt := v.Type()
prevSkip := false
for i := 0; i < numFields; i++ {
f.takeAll = false
if f.protoWrapperType && !vt.Field(i).IsExported() {
prevSkip = true
continue
} else if f.sqlWrapperType && vt.Field(i).Name == "Valid" {
prevSkip = true
continue
}
sv, ok := vt.Field(i).Tag.Lookup("logger")
if ok {
switch {
case ok:
switch sv {
case "omit":
prevSkip = true
@@ -363,23 +390,30 @@ func (f *unwrap) format(v reflect.Value) {
case "take":
break
}
} else if f.opts.Tagged {
case f.takeAll:
break
case !ok && f.opts.Tagged:
prevSkip = true
continue
}
if i > 0 && !prevSkip {
_, _ = f.s.Write(commaBytes)
_, _ = f.s.Write(spaceBytes)
}
if prevSkip {
prevSkip = false
}
if numWritten > 0 {
_, _ = f.s.Write(commaBytes)
_, _ = f.s.Write(spaceBytes)
}
vtf := vt.Field(i)
if f.s.Flag('+') || f.s.Flag('#') {
_, _ = f.s.Write([]byte(vtf.Name))
_, _ = f.s.Write(colonBytes)
}
f.format(f.unpackValue(v.Field(i)))
unpackValue := f.unpackValue(v.Field(i))
f.takeAll = f.checkTakeAll(unpackValue)
f.format(unpackValue)
numWritten++
}
f.depth--
@@ -575,3 +609,31 @@ func (f *unwrap) constructOrigFormat(verb rune) (format string) {
format = buf.String()
return format
}
func (f *unwrap) checkTakeAll(v reflect.Value) bool {
takeAll := true
switch v.Kind() {
case reflect.Struct:
break
case reflect.Ptr:
v = v.Elem()
if v.Kind() != reflect.Struct {
return true
}
default:
return true
}
vt := v.Type()
for i := 0; i < v.NumField(); i++ {
sv, ok := vt.Field(i).Tag.Lookup("logger")
if ok && sv == "take" {
return false
}
takeAll = f.checkTakeAll(v.Field(i))
}
return takeAll
}

View File

@@ -86,12 +86,12 @@ func TestTaggedNested(t *testing.T) {
unk string
}
type str struct {
val *val `logger:"take"`
key string `logger:"omit"`
val *val `logger:"take"`
}
var iface interface{}
v := &str{key: "omit", val: &val{key: "test", val: "omit", unk: "unk"}}
v := &str{val: &val{key: "test", unk: "unk"}}
iface = v
buf := fmt.Sprintf("%#v", Unwrap(iface, Tagged(true)))
if strings.Compare(buf, `&unwrap.str{val:(*unwrap.val){key:"test"}}`) != 0 {