github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/go-grpc-middleware/logging/zap/options.go (about) 1 package grpc_zap 2 3 import ( 4 "time" 5 6 grpc_logging "github.com/hxx258456/ccgo/go-grpc-middleware/logging" 7 "github.com/hxx258456/ccgo/grpc/codes" 8 "go.uber.org/zap" 9 "go.uber.org/zap/zapcore" 10 ) 11 12 var ( 13 defaultOptions = &options{ 14 levelFunc: DefaultCodeToLevel, 15 shouldLog: grpc_logging.DefaultDeciderMethod, 16 codeFunc: grpc_logging.DefaultErrorToCode, 17 durationFunc: DefaultDurationToField, 18 } 19 ) 20 21 type options struct { 22 levelFunc CodeToLevel 23 shouldLog grpc_logging.Decider 24 codeFunc grpc_logging.ErrorToCode 25 durationFunc DurationToField 26 } 27 28 func evaluateServerOpt(opts []Option) *options { 29 optCopy := &options{} 30 *optCopy = *defaultOptions 31 optCopy.levelFunc = DefaultCodeToLevel 32 for _, o := range opts { 33 o(optCopy) 34 } 35 return optCopy 36 } 37 38 func evaluateClientOpt(opts []Option) *options { 39 optCopy := &options{} 40 *optCopy = *defaultOptions 41 optCopy.levelFunc = DefaultClientCodeToLevel 42 for _, o := range opts { 43 o(optCopy) 44 } 45 return optCopy 46 } 47 48 type Option func(*options) 49 50 // CodeToLevel function defines the mapping between gRPC return codes and interceptor log level. 51 type CodeToLevel func(code codes.Code) zapcore.Level 52 53 // DurationToField function defines how to produce duration fields for logging 54 type DurationToField func(duration time.Duration) zapcore.Field 55 56 // WithDecider customizes the function for deciding if the gRPC interceptor logs should log. 57 func WithDecider(f grpc_logging.Decider) Option { 58 return func(o *options) { 59 o.shouldLog = f 60 } 61 } 62 63 // WithLevels customizes the function for mapping gRPC return codes and interceptor log level statements. 64 func WithLevels(f CodeToLevel) Option { 65 return func(o *options) { 66 o.levelFunc = f 67 } 68 } 69 70 // WithCodes customizes the function for mapping errors to error codes. 71 func WithCodes(f grpc_logging.ErrorToCode) Option { 72 return func(o *options) { 73 o.codeFunc = f 74 } 75 } 76 77 // WithDurationField customizes the function for mapping request durations to Zap fields. 78 func WithDurationField(f DurationToField) Option { 79 return func(o *options) { 80 o.durationFunc = f 81 } 82 } 83 84 // DefaultCodeToLevel is the default implementation of gRPC return codes and interceptor log level for server side. 85 func DefaultCodeToLevel(code codes.Code) zapcore.Level { 86 switch code { 87 case codes.OK: 88 return zap.InfoLevel 89 case codes.Canceled: 90 return zap.InfoLevel 91 case codes.Unknown: 92 return zap.ErrorLevel 93 case codes.InvalidArgument: 94 return zap.InfoLevel 95 case codes.DeadlineExceeded: 96 return zap.WarnLevel 97 case codes.NotFound: 98 return zap.InfoLevel 99 case codes.AlreadyExists: 100 return zap.InfoLevel 101 case codes.PermissionDenied: 102 return zap.WarnLevel 103 case codes.Unauthenticated: 104 return zap.InfoLevel // unauthenticated requests can happen 105 case codes.ResourceExhausted: 106 return zap.WarnLevel 107 case codes.FailedPrecondition: 108 return zap.WarnLevel 109 case codes.Aborted: 110 return zap.WarnLevel 111 case codes.OutOfRange: 112 return zap.WarnLevel 113 case codes.Unimplemented: 114 return zap.ErrorLevel 115 case codes.Internal: 116 return zap.ErrorLevel 117 case codes.Unavailable: 118 return zap.WarnLevel 119 case codes.DataLoss: 120 return zap.ErrorLevel 121 default: 122 return zap.ErrorLevel 123 } 124 } 125 126 // DefaultClientCodeToLevel is the default implementation of gRPC return codes to log levels for client side. 127 func DefaultClientCodeToLevel(code codes.Code) zapcore.Level { 128 switch code { 129 case codes.OK: 130 return zap.DebugLevel 131 case codes.Canceled: 132 return zap.DebugLevel 133 case codes.Unknown: 134 return zap.InfoLevel 135 case codes.InvalidArgument: 136 return zap.DebugLevel 137 case codes.DeadlineExceeded: 138 return zap.InfoLevel 139 case codes.NotFound: 140 return zap.DebugLevel 141 case codes.AlreadyExists: 142 return zap.DebugLevel 143 case codes.PermissionDenied: 144 return zap.InfoLevel 145 case codes.Unauthenticated: 146 return zap.InfoLevel // unauthenticated requests can happen 147 case codes.ResourceExhausted: 148 return zap.DebugLevel 149 case codes.FailedPrecondition: 150 return zap.DebugLevel 151 case codes.Aborted: 152 return zap.DebugLevel 153 case codes.OutOfRange: 154 return zap.DebugLevel 155 case codes.Unimplemented: 156 return zap.WarnLevel 157 case codes.Internal: 158 return zap.WarnLevel 159 case codes.Unavailable: 160 return zap.WarnLevel 161 case codes.DataLoss: 162 return zap.WarnLevel 163 default: 164 return zap.InfoLevel 165 } 166 } 167 168 // DefaultDurationToField is the default implementation of converting request duration to a Zap field. 169 var DefaultDurationToField = DurationToTimeMillisField 170 171 // DurationToTimeMillisField converts the duration to milliseconds and uses the key `grpc.time_ms`. 172 func DurationToTimeMillisField(duration time.Duration) zapcore.Field { 173 return zap.Float32("grpc.time_ms", durationToMilliseconds(duration)) 174 } 175 176 // DurationToDurationField uses a Duration field to log the request duration 177 // and leaves it up to Zap's encoder settings to determine how that is output. 178 func DurationToDurationField(duration time.Duration) zapcore.Field { 179 return zap.Duration("grpc.duration", duration) 180 } 181 182 func durationToMilliseconds(duration time.Duration) float32 { 183 return float32(duration.Nanoseconds()/1000) / 1000 184 }