Implementing Logging

1. Using grpclog Package

Example: Set custom grpc logger

import "google.golang.org/grpc/grpclog"
grpclog.SetLoggerV2(grpclog.NewLoggerV2WithVerbosity(os.Stderr, os.Stderr, os.Stderr, 2))
APIDetail
SetLoggerV2Replace internal gRPC logger
env GRPC_GO_LOG_SEVERITY_LEVELinfo / warning / error

2. Setting Log Level

LevelUse
DEBUGLocal dev / troubleshooting
INFOProduction default
WARNAnomalies
ERROROperational failures

3. Implementing Custom Logger

InterfaceDetail
grpclog.LoggerV2Implement for routing to slog/zap/zerolog
Per-request loggerAttach via ctx with fields

4. Logging Requests and Responses

Example: Logging interceptor

func LogIntc(ctx context.Context, req any, info *grpc.UnaryServerInfo,
    h grpc.UnaryHandler) (any, error) {
    start := time.Now()
    res, err := h(ctx, req)
    slog.LogAttrs(ctx, slog.LevelInfo, "rpc",
        slog.String("method", info.FullMethod),
        slog.String("code", status.Code(err).String()),
        slog.Duration("dur", time.Since(start)),
    )
    return res, err
}

5. Using Structured Logging

Library (Go)Notes
log/slog Go 1.21+Stdlib structured logger
zapVery fast
zerologZero-alloc JSON

6. Logging Metadata

FieldSource
request_idx-request-id header
trace_id / span_idtraceparent
user_agentuser-agent

7. Logging Request Duration

MeasureDetail
Wall-clocktime.Since(start)
HistogramEmit as Prometheus metric

8. Logging Error Details

FieldDetail
status.codeFrom status.Code(err)
status.messageFrom st.Message()
detailsIterate st.Details()
stackOnly at WARN/ERROR — not for Canceled

9. Filtering Sensitive Data

FieldAction
password / tokenRedact
PII (email, phone)Hash or mask
Payment dataNever log
Custom proto option(log.sensitive) = true

10. Integrating with Logging Framework

PatternDetail
Per-request loggerInject via ctx, append fields per layer
Async sinksBuffered shipper to ELK/Loki
Sampling1% INFO sampling under high load