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

     1  // Copyright (c) Improbable Worlds Ltd, All Rights Reserved
     2  
     3  package grpc_logrus
     4  
     5  import (
     6  	"path"
     7  	"time"
     8  
     9  	grpcmiddleware "gitee.com/ks-custle/core-gm/go-grpc-middleware"
    10  	"gitee.com/ks-custle/core-gm/go-grpc-middleware/logging/logrus/ctxlogrus"
    11  	"gitee.com/ks-custle/core-gm/grpc"
    12  	"gitee.com/ks-custle/core-gm/net/context"
    13  	"github.com/sirupsen/logrus"
    14  )
    15  
    16  var (
    17  	// SystemField is used in every log statement made through grpc_logrus. Can be overwritten before any initialization code.
    18  	SystemField = "system"
    19  
    20  	// KindField describes the log gield used to incicate whether this is a server or a client log statment.
    21  	KindField = "span.kind"
    22  )
    23  
    24  // UnaryServerInterceptor returns a new unary server interceptors that adds logrus.Entry to the context.
    25  func UnaryServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.UnaryServerInterceptor {
    26  	o := evaluateServerOpt(opts)
    27  	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    28  		startTime := time.Now()
    29  		newCtx := newLoggerForCall(ctx, entry, info.FullMethod, startTime)
    30  
    31  		resp, err := handler(newCtx, req)
    32  
    33  		if !o.shouldLog(info.FullMethod, err) {
    34  			return resp, err
    35  		}
    36  		code := o.codeFunc(err)
    37  		level := o.levelFunc(code)
    38  		durField, durVal := o.durationFunc(time.Since(startTime))
    39  		fields := logrus.Fields{
    40  			"grpc.code": code.String(),
    41  			durField:    durVal,
    42  		}
    43  		if err != nil {
    44  			fields[logrus.ErrorKey] = err
    45  		}
    46  
    47  		levelLogf(
    48  			// re-extract logger from newCtx, as it may have extra fields that changed in the holder.
    49  			// ctx_logrus.Extract is deprecated, use ctxlogrus.Extract instead.
    50  			//ctx_logrus.Extract(newCtx).WithFields(fields),
    51  			ctxlogrus.Extract(newCtx).WithFields(fields),
    52  			level,
    53  			"finished unary call with code "+code.String())
    54  
    55  		return resp, err
    56  	}
    57  }
    58  
    59  // StreamServerInterceptor returns a new streaming server interceptor that adds logrus.Entry to the context.
    60  func StreamServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamServerInterceptor {
    61  	o := evaluateServerOpt(opts)
    62  	return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
    63  		startTime := time.Now()
    64  		newCtx := newLoggerForCall(stream.Context(), entry, info.FullMethod, startTime)
    65  		wrapped := grpcmiddleware.WrapServerStream(stream)
    66  		wrapped.WrappedContext = newCtx
    67  
    68  		err := handler(srv, wrapped)
    69  
    70  		if !o.shouldLog(info.FullMethod, err) {
    71  			return err
    72  		}
    73  		code := o.codeFunc(err)
    74  		level := o.levelFunc(code)
    75  		durField, durVal := o.durationFunc(time.Since(startTime))
    76  		fields := logrus.Fields{
    77  			"grpc.code": code.String(),
    78  			durField:    durVal,
    79  		}
    80  		if err != nil {
    81  			fields[logrus.ErrorKey] = err
    82  		}
    83  
    84  		levelLogf(
    85  			// re-extract logger from newCtx, as it may have extra fields that changed in the holder.
    86  			// ctx_logrus.Extract is deprecated, use ctxlogrus.Extract instead.
    87  			//ctx_logrus.Extract(newCtx).WithFields(fields),
    88  			ctxlogrus.Extract(newCtx).WithFields(fields),
    89  			level,
    90  			"finished streaming call with code "+code.String())
    91  
    92  		return err
    93  	}
    94  }
    95  
    96  func levelLogf(entry *logrus.Entry, level logrus.Level, format string, args ...interface{}) {
    97  	switch level {
    98  	case logrus.DebugLevel:
    99  		entry.Debugf(format, args...)
   100  	case logrus.InfoLevel:
   101  		entry.Infof(format, args...)
   102  	case logrus.WarnLevel:
   103  		entry.Warningf(format, args...)
   104  	case logrus.ErrorLevel:
   105  		entry.Errorf(format, args...)
   106  	case logrus.FatalLevel:
   107  		entry.Fatalf(format, args...)
   108  	case logrus.PanicLevel:
   109  		entry.Panicf(format, args...)
   110  	}
   111  }
   112  
   113  func newLoggerForCall(ctx context.Context, entry *logrus.Entry, fullMethodString string, start time.Time) context.Context {
   114  	service := path.Dir(fullMethodString)[1:]
   115  	method := path.Base(fullMethodString)
   116  	callLog := entry.WithFields(
   117  		logrus.Fields{
   118  			SystemField:       "grpc",
   119  			KindField:         "server",
   120  			"grpc.service":    service,
   121  			"grpc.method":     method,
   122  			"grpc.start_time": start.Format(time.RFC3339),
   123  		})
   124  
   125  	if d, ok := ctx.Deadline(); ok {
   126  		callLog = callLog.WithFields(
   127  			logrus.Fields{
   128  				"grpc.request.deadline": d.Format(time.RFC3339),
   129  			})
   130  	}
   131  
   132  	// ctx_logrus.Extract is deprecated, use ctxlogrus.Extract instead.
   133  	//callLog = callLog.WithFields(ctx_logrus.Extract(ctx).Data)
   134  	callLog = callLog.WithFields(ctxlogrus.Extract(ctx).Data)
   135  	return ctxlogrus.ToContext(ctx, callLog)
   136  }