...

Source file src/github.com/grpc-ecosystem/go-grpc-middleware/logging/kit/options.go

Documentation: github.com/grpc-ecosystem/go-grpc-middleware/logging/kit

     1  package kit
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/go-kit/log"
     7  	"github.com/go-kit/log/level"
     8  	grpc_logging "github.com/grpc-ecosystem/go-grpc-middleware/logging"
     9  	"google.golang.org/grpc/codes"
    10  )
    11  
    12  var (
    13  	defaultOptions = &options{
    14  		shouldLog:       grpc_logging.DefaultDeciderMethod,
    15  		codeFunc:        grpc_logging.DefaultErrorToCode,
    16  		durationFunc:    DefaultDurationToField,
    17  		timestampFormat: time.RFC3339,
    18  	}
    19  )
    20  
    21  type options struct {
    22  	levelFunc       CodeToLevel
    23  	shouldLog       grpc_logging.Decider
    24  	codeFunc        grpc_logging.ErrorToCode
    25  	durationFunc    DurationToField
    26  	timestampFormat string
    27  }
    28  
    29  type Option func(*options)
    30  
    31  // CodeToLevel function defines the mapping between gRPC return codes and interceptor log level.
    32  type CodeToLevel func(code codes.Code, logger log.Logger) log.Logger
    33  
    34  // DurationToField function defines how to produce duration fields for logging
    35  type DurationToField func(duration time.Duration) []interface{}
    36  
    37  func evaluateServerOpt(opts []Option) *options {
    38  	optCopy := &options{}
    39  	*optCopy = *defaultOptions
    40  	optCopy.levelFunc = DefaultCodeToLevel
    41  	for _, o := range opts {
    42  		o(optCopy)
    43  	}
    44  	return optCopy
    45  }
    46  
    47  func evaluateClientOpt(opts []Option) *options {
    48  	optCopy := &options{}
    49  	*optCopy = *defaultOptions
    50  	optCopy.levelFunc = DefaultClientCodeToLevel
    51  	for _, o := range opts {
    52  		o(optCopy)
    53  	}
    54  	return optCopy
    55  }
    56  
    57  // WithDecider customizes the function for deciding if the gRPC interceptor logs should log.
    58  func WithDecider(f grpc_logging.Decider) Option {
    59  	return func(o *options) {
    60  		o.shouldLog = f
    61  	}
    62  }
    63  
    64  // WithLevels customizes the function for mapping gRPC return codes and interceptor log level statements.
    65  func WithLevels(f CodeToLevel) Option {
    66  	return func(o *options) {
    67  		o.levelFunc = f
    68  	}
    69  }
    70  
    71  // WithCodes customizes the function for mapping errors to error codes.
    72  func WithCodes(f grpc_logging.ErrorToCode) Option {
    73  	return func(o *options) {
    74  		o.codeFunc = f
    75  	}
    76  }
    77  
    78  // WithDurationField customizes the function for mapping request durations to log fields.
    79  func WithDurationField(f DurationToField) Option {
    80  	return func(o *options) {
    81  		o.durationFunc = f
    82  	}
    83  }
    84  
    85  // WithTimestampFormat customizes the timestamps emitted in the log fields.
    86  func WithTimestampFormat(format string) Option {
    87  	return func(o *options) {
    88  		o.timestampFormat = format
    89  	}
    90  }
    91  
    92  // DefaultCodeToLevel is the default implementation of gRPC return codes and interceptor log level for server side.
    93  func DefaultCodeToLevel(code codes.Code, logger log.Logger) log.Logger {
    94  	switch code {
    95  	case codes.OK, codes.Canceled, codes.InvalidArgument, codes.NotFound, codes.AlreadyExists, codes.Unauthenticated:
    96  		return level.Info(logger)
    97  	case codes.DeadlineExceeded, codes.PermissionDenied, codes.ResourceExhausted, codes.FailedPrecondition, codes.Aborted, codes.OutOfRange, codes.Unavailable:
    98  		return level.Warn(logger)
    99  	case codes.Unknown, codes.Unimplemented, codes.Internal, codes.DataLoss:
   100  		return level.Error(logger)
   101  	default:
   102  		return level.Error(logger)
   103  	}
   104  }
   105  
   106  // DefaultClientCodeToLevel is the default implementation of gRPC return codes to log levels for client side.
   107  func DefaultClientCodeToLevel(code codes.Code, logger log.Logger) log.Logger {
   108  	switch code {
   109  	case codes.OK, codes.Canceled, codes.InvalidArgument, codes.NotFound, codes.AlreadyExists, codes.ResourceExhausted, codes.FailedPrecondition, codes.Aborted, codes.OutOfRange:
   110  		return level.Debug(logger)
   111  	case codes.Unknown, codes.DeadlineExceeded, codes.PermissionDenied, codes.Unauthenticated:
   112  		return level.Info(logger)
   113  	case codes.Unimplemented, codes.Internal, codes.Unavailable, codes.DataLoss:
   114  		return level.Warn(logger)
   115  	default:
   116  		return level.Info(logger)
   117  	}
   118  }
   119  
   120  // DefaultDurationToField is the default implementation of converting request duration to a kit field.
   121  var DefaultDurationToField = DurationToTimeMillisField
   122  
   123  // DurationToTimeMillisField converts the duration to milliseconds and uses the key `grpc.time_ms`.
   124  func DurationToTimeMillisField(duration time.Duration) []interface{} {
   125  	return []interface{}{"grpc.time_ms", durationToMilliseconds(duration)}
   126  }
   127  
   128  // DurationToDurationField uses a Duration field to log the request duration
   129  // and leaves it up to Log's encoder settings to determine how that is output.
   130  func DurationToDurationField(duration time.Duration) []interface{} {
   131  	return []interface{}{"grpc.duration", duration}
   132  }
   133  
   134  func durationToMilliseconds(duration time.Duration) float32 {
   135  	return float32(duration.Nanoseconds()/1000) / 1000
   136  }
   137  

View as plain text