github.com/whoyao/protocol@v0.0.0-20230519045905-2d8ace718ca5/logger/proto.go (about) 1 package logger 2 3 import ( 4 "encoding/base64" 5 "strconv" 6 7 "go.uber.org/zap/zapcore" 8 "google.golang.org/protobuf/proto" 9 "google.golang.org/protobuf/reflect/protoreflect" 10 ) 11 12 func Proto(val proto.Message) zapcore.ObjectMarshaler { 13 return protoMarshaller{val.ProtoReflect()} 14 } 15 16 var _ zapcore.ObjectMarshaler = protoMarshaller{} 17 var _ zapcore.ObjectMarshaler = protoMapMarshaller{} 18 var _ zapcore.ArrayMarshaler = protoListMarshaller{} 19 20 type protoMarshaller struct { 21 m protoreflect.Message 22 } 23 24 func (p protoMarshaller) MarshalLogObject(e zapcore.ObjectEncoder) error { 25 fields := p.m.Descriptor().Fields() 26 for i := 0; i < fields.Len(); i++ { 27 f := fields.Get(i) 28 k := f.JSONName() 29 v := p.m.Get(f) 30 31 if f.IsMap() { 32 if m := v.Map(); m.IsValid() { 33 e.AddObject(k, protoMapMarshaller{f, m}) 34 } 35 } else if f.IsList() { 36 if m := v.List(); m.IsValid() { 37 e.AddArray(k, protoListMarshaller{f, m}) 38 } 39 } else { 40 marshalProtoField(k, f, v, e) 41 } 42 } 43 return nil 44 } 45 46 type protoMapMarshaller struct { 47 f protoreflect.FieldDescriptor 48 m protoreflect.Map 49 } 50 51 func (p protoMapMarshaller) MarshalLogObject(e zapcore.ObjectEncoder) error { 52 p.m.Range(func(ki protoreflect.MapKey, vi protoreflect.Value) bool { 53 var k string 54 switch p.f.MapKey().Kind() { 55 case protoreflect.BoolKind: 56 k = strconv.FormatBool(ki.Bool()) 57 case protoreflect.Int32Kind, protoreflect.Int64Kind, protoreflect.Sint32Kind, protoreflect.Sint64Kind, protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind: 58 k = strconv.FormatInt(ki.Int(), 10) 59 case protoreflect.Uint32Kind, protoreflect.Uint64Kind, protoreflect.Fixed32Kind, protoreflect.Fixed64Kind: 60 k = strconv.FormatUint(ki.Uint(), 10) 61 case protoreflect.StringKind: 62 k = ki.String() 63 } 64 marshalProtoField(k, p.f.MapValue(), vi, e) 65 return true 66 }) 67 return nil 68 } 69 70 type protoListMarshaller struct { 71 f protoreflect.FieldDescriptor 72 m protoreflect.List 73 } 74 75 func (p protoListMarshaller) MarshalLogArray(e zapcore.ArrayEncoder) error { 76 for i := 0; i < p.m.Len(); i++ { 77 v := p.m.Get(i) 78 switch p.f.Kind() { 79 case protoreflect.BoolKind: 80 e.AppendBool(v.Bool()) 81 case protoreflect.EnumKind: 82 e.AppendInt32(int32(v.Enum())) 83 case protoreflect.Int32Kind, protoreflect.Int64Kind, protoreflect.Sint32Kind, protoreflect.Sint64Kind, protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind: 84 e.AppendInt64(v.Int()) 85 case protoreflect.Uint32Kind, protoreflect.Uint64Kind, protoreflect.Fixed32Kind, protoreflect.Fixed64Kind: 86 e.AppendUint64(v.Uint()) 87 case protoreflect.FloatKind, protoreflect.DoubleKind: 88 e.AppendFloat64(v.Float()) 89 case protoreflect.StringKind: 90 e.AppendString(v.String()) 91 case protoreflect.BytesKind: 92 e.AppendString(base64.RawStdEncoding.EncodeToString(v.Bytes())) 93 case protoreflect.MessageKind: 94 e.AppendObject(protoMarshaller{v.Message()}) 95 } 96 } 97 return nil 98 } 99 100 func marshalProtoField(k string, f protoreflect.FieldDescriptor, v protoreflect.Value, e zapcore.ObjectEncoder) { 101 switch f.Kind() { 102 case protoreflect.BoolKind: 103 if b := v.Bool(); b { 104 e.AddBool(k, b) 105 } 106 case protoreflect.EnumKind: 107 if n := v.Enum(); n != 0 { 108 e.AddInt32(k, int32(n)) 109 } 110 case protoreflect.Int32Kind, protoreflect.Int64Kind, protoreflect.Sint32Kind, protoreflect.Sint64Kind, protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind: 111 if n := v.Int(); n != 0 { 112 e.AddInt64(k, n) 113 } 114 case protoreflect.Uint32Kind, protoreflect.Uint64Kind, protoreflect.Fixed32Kind, protoreflect.Fixed64Kind: 115 if n := v.Uint(); n != 0 { 116 e.AddUint64(k, n) 117 } 118 case protoreflect.FloatKind, protoreflect.DoubleKind: 119 if n := v.Float(); n != 0 { 120 e.AddFloat64(k, n) 121 } 122 case protoreflect.StringKind: 123 if s := v.String(); s != "" { 124 e.AddString(k, s) 125 } 126 case protoreflect.BytesKind: 127 if b := v.Bytes(); len(b) != 0 { 128 e.AddString(k, base64.RawStdEncoding.EncodeToString(b)) 129 } 130 case protoreflect.MessageKind: 131 if m := v.Message(); m.IsValid() { 132 e.AddObject(k, protoMarshaller{m}) 133 } 134 } 135 }