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  }