logger/unwrap: add tagged option #156

Merged
vtolstov merged 1 commits from take_unwrap into v3 2022-11-19 15:23:22 +03:00
3 changed files with 62 additions and 30 deletions

View File

@ -74,7 +74,7 @@ type Request interface {
type Response interface { type Response interface {
// Read the response // Read the response
Codec() codec.Codec Codec() codec.Codec
// read the header // Header data
Header() metadata.Metadata Header() metadata.Metadata
// Read the undecoded response // Read the undecoded response
Read() ([]byte, error) Read() ([]byte, error)

View File

@ -55,15 +55,16 @@ type unwrap struct {
} }
type Options struct { type Options struct {
Codec codec.Codec Codec codec.Codec
Indent string Indent string
UnwrapMethods bool Methods bool
Tagged bool
} }
func NewOptions(opts ...Option) Options { func NewOptions(opts ...Option) Options {
options := Options{ options := Options{
Indent: " ", Indent: " ",
UnwrapMethods: false, Methods: false,
} }
for _, o := range opts { for _, o := range opts {
o(&options) o(&options)
@ -73,24 +74,30 @@ func NewOptions(opts ...Option) Options {
type Option func(*Options) type Option func(*Options)
func UnwrapIndent(f string) Option { func Indent(f string) Option {
return func(o *Options) { return func(o *Options) {
o.Indent = f o.Indent = f
} }
} }
func UnwrapMethods(b bool) Option { func Methods(b bool) Option {
return func(o *Options) { return func(o *Options) {
o.UnwrapMethods = b o.Methods = b
} }
} }
func UnwrapCodec(c codec.Codec) Option { func Codec(c codec.Codec) Option {
return func(o *Options) { return func(o *Options) {
o.Codec = c o.Codec = c
} }
} }
func Tagged(b bool) Option {
return func(o *Options) {
o.Tagged = b
}
}
func Unwrap(val interface{}, opts ...Option) *unwrap { func Unwrap(val interface{}, opts ...Option) *unwrap {
options := NewOptions(opts...) options := NewOptions(opts...)
return &unwrap{val: val, opts: &options, pointers: make(map[uintptr]int)} return &unwrap{val: val, opts: &options, pointers: make(map[uintptr]int)}
@ -256,7 +263,7 @@ func (f *unwrap) format(v reflect.Value) {
// Call Stringer/error interfaces if they exist and the handle methods // Call Stringer/error interfaces if they exist and the handle methods
// flag is enabled. // flag is enabled.
if !f.opts.UnwrapMethods { if !f.opts.Methods {
if (kind != reflect.Invalid) && (kind != reflect.Interface) { if (kind != reflect.Invalid) && (kind != reflect.Interface) {
if handled := handleMethods(f.opts, f.s, v); handled { if handled := handleMethods(f.opts, f.s, v); handled {
return return
@ -341,7 +348,12 @@ func (f *unwrap) format(v reflect.Value) {
prevSkip := false prevSkip := false
for i := 0; i < numFields; i++ { for i := 0; i < numFields; i++ {
sv, ok := vt.Field(i).Tag.Lookup("logger") sv, ok := vt.Field(i).Tag.Lookup("logger")
if ok && sv == "omit" { if ok {
if sv == "omit" {
prevSkip = true
continue
}
} else if f.opts.Tagged {
prevSkip = true prevSkip = true
continue continue
} }

View File

@ -1,24 +1,13 @@
package unwrap package unwrap
import ( import (
"fmt"
"strings"
"testing" "testing"
"go.unistack.org/micro/v3/codec" "go.unistack.org/micro/v3/codec"
) )
func TestUnwrapOmit(t *testing.T) {
type val struct {
MP map[string]string `json:"mp" logger:"omit"`
STR string `json:"str"`
AR []string `json:"ar"`
}
v1 := &val{AR: []string{"string1", "string2"}, STR: "string", MP: map[string]string{"key": "val"}}
t.Logf("output: %#v", v1)
t.Logf("output: %#v", Unwrap(v1))
}
func TestUnwrap(t *testing.T) { func TestUnwrap(t *testing.T) {
string1 := "string1" string1 := "string1"
string2 := "string2" string2 := "string2"
@ -32,7 +21,10 @@ func TestUnwrap(t *testing.T) {
v1 := &val1{ar: []*string{&string1, &string2}, str: &string1, val: &val1{str: &string2}, mp: map[string]string{"key": "val"}} v1 := &val1{ar: []*string{&string1, &string2}, str: &string1, val: &val1{str: &string2}, mp: map[string]string{"key": "val"}}
t.Logf("output: %#v", Unwrap(v1)) buf := fmt.Sprintf("%#v", Unwrap(v1))
if strings.Compare(buf, `&unwrap.val1{mp:map[string]string{"key":"val"}, val:(*unwrap.val1){mp:map[string]string<nil>, val:(*unwrap.val1)<nil>, str:(*string)"string2", ar:[]*string<nil>}, str:(*string)"string1", ar:[]*string{<*><shown>, <*>"string2"}}`) != 0 {
t.Fatalf("not proper written %s", buf)
}
type val2 struct { type val2 struct {
mp map[string]string mp map[string]string
@ -42,11 +34,11 @@ func TestUnwrap(t *testing.T) {
} }
v2 := &val2{ar: []string{string1, string2}, str: string1, val: &val2{str: string2}, mp: map[string]string{"key": "val"}} v2 := &val2{ar: []string{string1, string2}, str: string1, val: &val2{str: string2}, mp: map[string]string{"key": "val"}}
_ = v2
t.Logf("output: %#v", v2) // t.Logf("output: %#v", v2)
} }
func TestUnwrapCodec(t *testing.T) { func TestCodec(t *testing.T) {
type val struct { type val struct {
MP map[string]string `json:"mp"` MP map[string]string `json:"mp"`
STR string `json:"str"` STR string `json:"str"`
@ -55,5 +47,33 @@ func TestUnwrapCodec(t *testing.T) {
v1 := &val{AR: []string{"string1", "string2"}, STR: "string", MP: map[string]string{"key": "val"}} v1 := &val{AR: []string{"string1", "string2"}, STR: "string", MP: map[string]string{"key": "val"}}
t.Logf("output: %#v", Unwrap(v1, UnwrapCodec(codec.NewCodec()))) buf := fmt.Sprintf("%#v", Unwrap(v1, Codec(codec.NewCodec())))
if strings.Compare(buf, `{"mp":{"key":"val"},"str":"string","ar":["string1","string2"]}`) != 0 {
t.Fatalf("not proper written %s", buf)
}
}
func TestOmit(t *testing.T) {
type val struct {
Key1 string `logger:"omit"`
Key2 string `logger:"take"`
}
v1 := &val{Key1: "val1", Key2: "val2"}
buf := fmt.Sprintf("%#v", Unwrap(v1))
if strings.Compare(buf, `&unwrap.val{Key2:"val2"}`) != 0 {
t.Fatalf("not proper written %s", buf)
}
}
func TestTagged(t *testing.T) {
type val struct {
Key1 string `logger:"take"`
Key2 string
}
v1 := &val{Key1: "val1", Key2: "val2"}
buf := fmt.Sprintf("%#v", Unwrap(v1, Tagged(true)))
if strings.Compare(buf, `&unwrap.val{Key1:"val1"}`) != 0 {
t.Fatalf("not proper written %s", buf)
}
} }