gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/go-grpc-middleware/logging/zap/options.go (about)

     1  package grpc_zap
     2  
     3  import (
     4  	"time"
     5  
     6  	grpc_logging "gitee.com/ks-custle/core-gm/go-grpc-middleware/logging"
     7  	"gitee.com/ks-custle/core-gm/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  }