github.com/weaveworks/common@v0.0.0-20230728070032-dd9e68f319d5/middleware/grpc_logging.go (about) 1 package middleware 2 3 import ( 4 "errors" 5 "time" 6 7 "golang.org/x/net/context" 8 "google.golang.org/grpc" 9 10 grpcUtils "github.com/weaveworks/common/grpc" 11 "github.com/weaveworks/common/logging" 12 "github.com/weaveworks/common/user" 13 ) 14 15 const ( 16 gRPC = "gRPC" 17 errorKey = "err" 18 ) 19 20 // An error can implement ShouldLog() to control whether GRPCServerLog will log. 21 type OptionalLogging interface { 22 ShouldLog(ctx context.Context, duration time.Duration) bool 23 } 24 25 // GRPCServerLog logs grpc requests, errors, and latency. 26 type GRPCServerLog struct { 27 Log logging.Interface 28 // WithRequest will log the entire request rather than just the error 29 WithRequest bool 30 DisableRequestSuccessLog bool 31 } 32 33 // UnaryServerInterceptor returns an interceptor that logs gRPC requests 34 func (s GRPCServerLog) UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 35 begin := time.Now() 36 resp, err := handler(ctx, req) 37 if err == nil && s.DisableRequestSuccessLog { 38 return resp, nil 39 } 40 var optional OptionalLogging 41 if errors.As(err, &optional) && !optional.ShouldLog(ctx, time.Since(begin)) { 42 return resp, err 43 } 44 45 entry := user.LogWith(ctx, s.Log).WithFields(logging.Fields{"method": info.FullMethod, "duration": time.Since(begin)}) 46 if err != nil { 47 if s.WithRequest { 48 entry = entry.WithField("request", req) 49 } 50 if grpcUtils.IsCanceled(err) { 51 entry.WithField(errorKey, err).Debugln(gRPC) 52 } else { 53 entry.WithField(errorKey, err).Warnln(gRPC) 54 } 55 } else { 56 entry.Debugf("%s (success)", gRPC) 57 } 58 return resp, err 59 } 60 61 // StreamServerInterceptor returns an interceptor that logs gRPC requests 62 func (s GRPCServerLog) StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { 63 begin := time.Now() 64 err := handler(srv, ss) 65 if err == nil && s.DisableRequestSuccessLog { 66 return nil 67 } 68 69 entry := user.LogWith(ss.Context(), s.Log).WithFields(logging.Fields{"method": info.FullMethod, "duration": time.Since(begin)}) 70 if err != nil { 71 if grpcUtils.IsCanceled(err) { 72 entry.WithField(errorKey, err).Debugln(gRPC) 73 } else { 74 entry.WithField(errorKey, err).Warnln(gRPC) 75 } 76 } else { 77 entry.Debugf("%s (success)", gRPC) 78 } 79 return err 80 }