logger/unwrap: fix Tagged option #163
@@ -35,6 +35,7 @@ var (
 | 
			
		||||
	nilAngleBytes      = []byte("<nil>")
 | 
			
		||||
	circularShortBytes = []byte("<shown>")
 | 
			
		||||
	invalidAngleBytes  = []byte("<invalid>")
 | 
			
		||||
	filteredBytes      = []byte("<filtered>")
 | 
			
		||||
	openBracketBytes   = []byte("[")
 | 
			
		||||
	closeBracketBytes  = []byte("]")
 | 
			
		||||
	percentBytes       = []byte("%")
 | 
			
		||||
@@ -48,12 +49,13 @@ var (
 | 
			
		||||
type unwrap struct {
 | 
			
		||||
	val            interface{}
 | 
			
		||||
	s              fmt.State
 | 
			
		||||
	depth          int
 | 
			
		||||
	pointers       map[uintptr]int
 | 
			
		||||
	opts           *Options
 | 
			
		||||
	depth          int
 | 
			
		||||
	ignoreNextType bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Options struct
 | 
			
		||||
type Options struct {
 | 
			
		||||
	Codec   codec.Codec
 | 
			
		||||
	Indent  string
 | 
			
		||||
@@ -61,6 +63,7 @@ type Options struct {
 | 
			
		||||
	Tagged  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewOptions creates new Options struct via provided args
 | 
			
		||||
func NewOptions(opts ...Option) Options {
 | 
			
		||||
	options := Options{
 | 
			
		||||
		Indent:  " ",
 | 
			
		||||
@@ -72,26 +75,31 @@ func NewOptions(opts ...Option) Options {
 | 
			
		||||
	return options
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Option func signature
 | 
			
		||||
type Option func(*Options)
 | 
			
		||||
 | 
			
		||||
// Indent option specify indent level
 | 
			
		||||
func Indent(f string) Option {
 | 
			
		||||
	return func(o *Options) {
 | 
			
		||||
		o.Indent = f
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Methods option toggles fmt.Stringer methods
 | 
			
		||||
func Methods(b bool) Option {
 | 
			
		||||
	return func(o *Options) {
 | 
			
		||||
		o.Methods = b
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Codec option automatic marshal arg via specified codec and write it to log
 | 
			
		||||
func Codec(c codec.Codec) Option {
 | 
			
		||||
	return func(o *Options) {
 | 
			
		||||
		o.Codec = c
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tagged option toggles output only logger:"take" fields
 | 
			
		||||
func Tagged(b bool) Option {
 | 
			
		||||
	return func(o *Options) {
 | 
			
		||||
		o.Tagged = b
 | 
			
		||||
@@ -204,10 +212,8 @@ func (f *unwrap) formatPtr(v reflect.Value) {
 | 
			
		||||
	switch {
 | 
			
		||||
	case nilFound:
 | 
			
		||||
		_, _ = f.s.Write(nilAngleBytes)
 | 
			
		||||
 | 
			
		||||
	case cycleFound:
 | 
			
		||||
		_, _ = f.s.Write(circularShortBytes)
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		f.ignoreNextType = true
 | 
			
		||||
		f.format(ve)
 | 
			
		||||
@@ -263,7 +269,7 @@ func (f *unwrap) format(v reflect.Value) {
 | 
			
		||||
 | 
			
		||||
	// Call Stringer/error interfaces if they exist and the handle methods
 | 
			
		||||
	// flag is enabled.
 | 
			
		||||
	if !f.opts.Methods {
 | 
			
		||||
	if f.opts.Methods {
 | 
			
		||||
		if (kind != reflect.Invalid) && (kind != reflect.Interface) {
 | 
			
		||||
			if handled := handleMethods(f.opts, f.s, v); handled {
 | 
			
		||||
				return
 | 
			
		||||
@@ -342,6 +348,7 @@ func (f *unwrap) format(v reflect.Value) {
 | 
			
		||||
		_, _ = f.s.Write(closeMapBytes)
 | 
			
		||||
	case reflect.Struct:
 | 
			
		||||
		numFields := v.NumField()
 | 
			
		||||
		numWritten := 0
 | 
			
		||||
		_, _ = f.s.Write(openBraceBytes)
 | 
			
		||||
		f.depth++
 | 
			
		||||
		vt := v.Type()
 | 
			
		||||
@@ -349,9 +356,12 @@ func (f *unwrap) format(v reflect.Value) {
 | 
			
		||||
		for i := 0; i < numFields; i++ {
 | 
			
		||||
			sv, ok := vt.Field(i).Tag.Lookup("logger")
 | 
			
		||||
			if ok {
 | 
			
		||||
				if sv == "omit" {
 | 
			
		||||
				switch sv {
 | 
			
		||||
				case "omit":
 | 
			
		||||
					prevSkip = true
 | 
			
		||||
					continue
 | 
			
		||||
				case "take":
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			} else if f.opts.Tagged {
 | 
			
		||||
				prevSkip = true
 | 
			
		||||
@@ -370,8 +380,12 @@ func (f *unwrap) format(v reflect.Value) {
 | 
			
		||||
				_, _ = f.s.Write(colonBytes)
 | 
			
		||||
			}
 | 
			
		||||
			f.format(f.unpackValue(v.Field(i)))
 | 
			
		||||
			numWritten++
 | 
			
		||||
		}
 | 
			
		||||
		f.depth--
 | 
			
		||||
		if numWritten == 0 && f.depth < 0 {
 | 
			
		||||
			_, _ = f.s.Write(filteredBytes)
 | 
			
		||||
		}
 | 
			
		||||
		_, _ = f.s.Write(closeBraceBytes)
 | 
			
		||||
	case reflect.Uintptr:
 | 
			
		||||
		getHexPtr(f.s, uintptr(v.Uint()))
 | 
			
		||||
 
 | 
			
		||||
@@ -57,10 +57,11 @@ func TestOmit(t *testing.T) {
 | 
			
		||||
	type val struct {
 | 
			
		||||
		Key1 string `logger:"omit"`
 | 
			
		||||
		Key2 string `logger:"take"`
 | 
			
		||||
		Key3 string
 | 
			
		||||
	}
 | 
			
		||||
	v1 := &val{Key1: "val1", Key2: "val2"}
 | 
			
		||||
	v1 := &val{Key1: "val1", Key2: "val2", Key3: "val3"}
 | 
			
		||||
	buf := fmt.Sprintf("%#v", Unwrap(v1))
 | 
			
		||||
	if strings.Compare(buf, `&unwrap.val{Key2:"val2"}`) != 0 {
 | 
			
		||||
	if strings.Compare(buf, `&unwrap.val{Key2:"val2", Key3:"val3"}`) != 0 {
 | 
			
		||||
		t.Fatalf("not proper written %s", buf)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -77,3 +78,23 @@ func TestTagged(t *testing.T) {
 | 
			
		||||
		t.Fatalf("not proper written %s", buf)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestTaggedNested(t *testing.T) {
 | 
			
		||||
	type val struct {
 | 
			
		||||
		key string `logger:"take"`
 | 
			
		||||
		val string `logger:"omit"`
 | 
			
		||||
		unk string
 | 
			
		||||
	}
 | 
			
		||||
	type str struct {
 | 
			
		||||
		key string `logger:"omit"`
 | 
			
		||||
		val *val   `logger:"take"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var iface interface{}
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatalf("not proper written %s", buf)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user