|
@@ -0,0 +1,87 @@
|
|
|
+package logger
|
|
|
+
|
|
|
+import (
|
|
|
+ "context"
|
|
|
+ "log/slog"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+import (
|
|
|
+ "google.golang.org/grpc"
|
|
|
+ "google.golang.org/grpc/codes"
|
|
|
+ "google.golang.org/grpc/status"
|
|
|
+)
|
|
|
+
|
|
|
+func GRPCLoggerClientInterceptor(logger *slog.Logger) grpc.UnaryClientInterceptor {
|
|
|
+ return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
|
|
+ start := time.Now()
|
|
|
+ logger.Info("request",
|
|
|
+ slog.String("method", method),
|
|
|
+ slog.Any("payload", req),
|
|
|
+ )
|
|
|
+
|
|
|
+ err := invoker(ctx, method, req, reply, cc, opts...)
|
|
|
+
|
|
|
+ duration := time.Since(start)
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("response",
|
|
|
+ slog.String("method", method),
|
|
|
+ slog.Duration("duration", duration),
|
|
|
+ slog.String("error", err.Error()),
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ logger.Info("response",
|
|
|
+ slog.String("method", method),
|
|
|
+ slog.Duration("duration", duration),
|
|
|
+ slog.Any("reply", reply),
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ return err
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func GRPCLoggerServerInterceptor(logger *slog.Logger) grpc.UnaryServerInterceptor {
|
|
|
+ return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
|
|
+ start := time.Now()
|
|
|
+ method := info.FullMethod
|
|
|
+
|
|
|
+ // 在请求处理前记录
|
|
|
+ logger.Info("request",
|
|
|
+ slog.String("method", method),
|
|
|
+ slog.Any("payload", req),
|
|
|
+ )
|
|
|
+
|
|
|
+ // 调用实际的服务方法
|
|
|
+ resp, err = handler(ctx, req)
|
|
|
+
|
|
|
+ // 在请求处理后记录
|
|
|
+ duration := time.Since(start)
|
|
|
+ statusCode := codes.OK // 默认成功
|
|
|
+ if err != nil {
|
|
|
+ s, ok := status.FromError(err)
|
|
|
+ if ok {
|
|
|
+ statusCode = s.Code() // 从 gRPC 错误中获取状态码
|
|
|
+ } else {
|
|
|
+ statusCode = codes.Unknown // 非 gRPC 错误则视为未知
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("response",
|
|
|
+ slog.String("method", method),
|
|
|
+ slog.Duration("duration", duration),
|
|
|
+ slog.String("status_code", statusCode.String()),
|
|
|
+ slog.String("error", err.Error()),
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ logger.Info("response",
|
|
|
+ slog.String("method", method),
|
|
|
+ slog.Duration("duration", duration),
|
|
|
+ slog.Any("reply", resp),
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ return resp, err
|
|
|
+ }
|
|
|
+}
|