Refactor logging
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func InterceptorLogger() logging.Logger {
|
||||
return logging.LoggerFunc(func(ctx context.Context, lvl logging.Level, msg string, fields ...any) {
|
||||
l := zerolog.Ctx(ctx).With().Fields(fields).Logger()
|
||||
|
||||
switch lvl {
|
||||
case logging.LevelDebug:
|
||||
l.Debug().Msg(msg)
|
||||
case logging.LevelInfo:
|
||||
l.Info().Msg(msg)
|
||||
case logging.LevelWarn:
|
||||
l.Warn().Msg(msg)
|
||||
case logging.LevelError:
|
||||
l.Error().Msg(msg)
|
||||
default:
|
||||
l.Info().Msg(msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func LoggingOpts() []logging.Option {
|
||||
return []logging.Option{
|
||||
logging.WithLogOnEvents(logging.StartCall, logging.FinishCall),
|
||||
logging.WithLevels(levelFunc),
|
||||
logging.WithDurationField(func(d time.Duration) logging.Fields {
|
||||
return logging.Fields{"grpc.duration_ms", d.Milliseconds()}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func levelFunc(code codes.Code) logging.Level {
|
||||
switch code {
|
||||
case codes.OK, codes.NotFound, codes.Canceled:
|
||||
return logging.LevelInfo
|
||||
case codes.InvalidArgument, codes.AlreadyExists, codes.Unauthenticated:
|
||||
return logging.LevelWarn
|
||||
default:
|
||||
return logging.LevelError
|
||||
}
|
||||
}
|
||||
|
||||
func RequestIDInterceptor() grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||
requestID := uuid.New().String()
|
||||
|
||||
logger := log.Logger.With().
|
||||
Str("request_id", requestID).
|
||||
Str("grpc.method", info.FullMethod).
|
||||
Logger()
|
||||
|
||||
ctx = logger.WithContext(ctx)
|
||||
|
||||
resp, err := handler(ctx, req)
|
||||
if err != nil {
|
||||
st, _ := status.FromError(err)
|
||||
zerolog.Ctx(ctx).Debug().
|
||||
Str("grpc.code", st.Code().String()).
|
||||
Str("grpc.error", st.Message()).
|
||||
Msg("request failed")
|
||||
}
|
||||
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
|
||||
func PeerInfoInterceptor() grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if ok {
|
||||
evt := zerolog.Ctx(ctx).With()
|
||||
if ua := md.Get("user-agent"); len(ua) > 0 {
|
||||
evt = evt.Str("peer.user_agent", ua[0])
|
||||
}
|
||||
if auth := md.Get("authorization"); len(auth) > 0 {
|
||||
evt = evt.Bool("peer.authenticated", true)
|
||||
}
|
||||
logger := evt.Logger()
|
||||
ctx = logger.WithContext(ctx)
|
||||
}
|
||||
|
||||
return handler(ctx, req)
|
||||
}
|
||||
}
|
||||
|
||||
func StreamRequestIDInterceptor() grpc.StreamServerInterceptor {
|
||||
return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
requestID := uuid.New().String()
|
||||
|
||||
logger := log.Logger.With().
|
||||
Str("request_id", requestID).
|
||||
Str("grpc.method", info.FullMethod).
|
||||
Logger()
|
||||
|
||||
ctx := logger.WithContext(ss.Context())
|
||||
wrapped := &wrappedStream{ServerStream: ss, ctx: ctx}
|
||||
|
||||
return handler(srv, wrapped)
|
||||
}
|
||||
}
|
||||
|
||||
type wrappedStream struct {
|
||||
grpc.ServerStream
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (w *wrappedStream) Context() context.Context {
|
||||
return w.ctx
|
||||
}
|
||||
|
||||
func (w *wrappedStream) SendMsg(m any) error {
|
||||
zerolog.Ctx(w.ctx).Trace().Str("direction", "send").Msg(fmt.Sprintf("stream message: %T", m))
|
||||
return w.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (w *wrappedStream) RecvMsg(m any) error {
|
||||
err := w.ServerStream.RecvMsg(m)
|
||||
if err == nil {
|
||||
zerolog.Ctx(w.ctx).Trace().Str("direction", "recv").Msg(fmt.Sprintf("stream message: %T", m))
|
||||
}
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user