Skip to content

Commit

Permalink
log,grpc: simpler gRPC logger for server (#348)
Browse files Browse the repository at this point in the history
* pkg/log,grpc: simpler gRPC logger for server

* include client address
  • Loading branch information
jchappelow authored and brennanjl committed Feb 26, 2024
1 parent 514455e commit e437714
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 34 deletions.
7 changes: 7 additions & 0 deletions core/log/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ func (l *Logger) Fatal(msg string, fields ...Field) {
l.L.Fatal(msg, fields...)
}

func (l *Logger) Log(level Level, msg string, fields ...Field) {
if level >= ErrorLevel {
fields = append(fields, detailedFields...)
}
l.L.Log(level, msg, fields...)
}

func (l *Logger) Named(name string) *Logger {
if name == "" {
return l
Expand Down
77 changes: 49 additions & 28 deletions internal/services/grpc_server/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,62 @@ package server
import (
"context"
"fmt"
"strings"
"time"

"github.com/kwilteam/kwil-db/core/log"

"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/peer"
"google.golang.org/grpc/status"
)

// InterceptorLogger adapts zap logger to interceptor logger.
// This code is copied from go-grpc-middleware/interceptors/logging/examples/zap/example_test.go
func InterceptorLogger(l *log.Logger) logging.Logger {
func codeToLevel(code codes.Code) log.Level {
switch code {
case codes.OK:
return log.InfoLevel // log.DebugLevel
case codes.NotFound, codes.Canceled, codes.AlreadyExists, codes.InvalidArgument, codes.Unauthenticated:
return log.InfoLevel

return logging.LoggerFunc(func(ctx context.Context, lvl logging.Level, msg string, fields ...any) {
var f []zap.Field
i := logging.Fields(fields).Iterator()
for i.Next() {
k, v := i.At()
f = append(f, zap.Any(k, v))
}
case codes.DeadlineExceeded, codes.PermissionDenied, codes.ResourceExhausted, codes.FailedPrecondition,
codes.Aborted, codes.OutOfRange, codes.Unavailable:
return log.WarnLevel

case codes.Unknown, codes.Unimplemented, codes.Internal, codes.DataLoss:
return log.ErrorLevel

default:
return log.WarnLevel
}
}

// TODO: this is a hack to get rid of the extended fields every time we log
// log wrapper is not correctly cloned
// here use zap.Logger
lg := l.L.WithOptions(zap.AddCallerSkip(1)).With(f...)

switch lvl {
case logging.LevelDebug:
lg.Debug(msg)
case logging.LevelInfo:
lg.Info(msg)
case logging.LevelWarn:
lg.Warn(msg)
case logging.LevelError:
lg.Error(msg)
default:
panic(fmt.Sprintf("unknown level %v", lvl))
// SimpleInterceptorLogger is a simplified gRPC server request logger. For an
// alternative, see the example from
// go-grpc-middleware/interceptors/logging/examples/zap/example_test.go
func SimpleInterceptorLogger(l *log.Logger) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
tStart := time.Now()
resp, err := handler(ctx, req)
elapsedMs := float64(time.Since(tStart).Microseconds()) / 1e3
code := status.Code(err)
fields := []zap.Field{
zap.String("method", strings.Trim(info.FullMethod, "/")),
zap.String("elapsed", fmt.Sprintf("%.3fms", elapsedMs)),
}
if peer, ok := peer.FromContext(ctx); ok {
fields = append(fields, zap.String("addr", peer.Addr.String()))
}
fields = append(fields, zap.String("code", code.String()))
var msg string
if err != nil {
msg = "call failure"
fields = append(fields, zap.Error(err))
} else {
msg = "call success"
}
})
l.Log(codeToLevel(code), msg, fields...)
return resp, err
}
}
7 changes: 1 addition & 6 deletions internal/services/grpc_server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/kwilteam/kwil-db/core/log"

"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery"
"go.uber.org/zap"
"google.golang.org/grpc"
Expand All @@ -32,10 +31,6 @@ func New(logger log.Logger, lis net.Listener, opts ...Option) *Server {
recovery.WithRecoveryHandler(recoveryFunc),
}

loggingOpts := []logging.Option{
logging.WithLogOnEvents(logging.StartCall, logging.FinishCall),
}

s := &Server{
logger: l,
listener: lis,
Expand All @@ -46,7 +41,7 @@ func New(logger log.Logger, lis net.Listener, opts ...Option) *Server {
}
srvOpts := append(s.srvOpts, grpc.ChainUnaryInterceptor(
recovery.UnaryServerInterceptor(recoveryOpts...),
logging.UnaryServerInterceptor(InterceptorLogger(&l), loggingOpts...),
SimpleInterceptorLogger(&l),
))

s.server = grpc.NewServer(srvOpts...)
Expand Down

0 comments on commit e437714

Please sign in to comment.