logger/unwrap: support sql and proto wrapper types #180

Merged
vtolstov merged 2 commits from logger-wrapper into v3 2023-02-06 18:55:40 +03:00

View File

@ -47,12 +47,15 @@ var (
) )
type unwrap struct { type unwrap struct {
val interface{} val interface{}
s fmt.State s fmt.State
pointers map[uintptr]int pointers map[uintptr]int
opts *Options opts *Options
depth int depth int
ignoreNextType bool ignoreNextType bool
takeAll bool
protoWrapperType bool
sqlWrapperType bool
} }
// Options struct // Options struct
@ -242,9 +245,23 @@ func (f *unwrap) format(v reflect.Value) {
} }
// Handle pointers specially. // 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) f.formatPtr(v)
return 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. // get type information unless already handled elsewhere.
@ -355,8 +372,17 @@ func (f *unwrap) format(v reflect.Value) {
prevSkip := false prevSkip := false
for i := 0; i < numFields; i++ { 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") sv, ok := vt.Field(i).Tag.Lookup("logger")
if ok { switch {
case ok:
switch sv { switch sv {
case "omit": case "omit":
prevSkip = true prevSkip = true
@ -364,7 +390,9 @@ func (f *unwrap) format(v reflect.Value) {
case "take": case "take":
break break
} }
} else if f.opts.Tagged { case f.takeAll:
break
case !ok && f.opts.Tagged:
prevSkip = true prevSkip = true
continue continue
} }
@ -383,7 +411,9 @@ func (f *unwrap) format(v reflect.Value) {
_, _ = f.s.Write([]byte(vtf.Name)) _, _ = f.s.Write([]byte(vtf.Name))
_, _ = f.s.Write(colonBytes) _, _ = 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++ numWritten++
} }
f.depth-- f.depth--
@ -579,3 +609,31 @@ func (f *unwrap) constructOrigFormat(verb rune) (format string) {
format = buf.String() format = buf.String()
return format 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
}