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))
| API | Detail |
|---|---|
SetLoggerV2 | Replace internal gRPC logger |
env GRPC_GO_LOG_SEVERITY_LEVEL | info / warning / error |
2. Setting Log Level
| Level | Use |
|---|---|
| DEBUG | Local dev / troubleshooting |
| INFO | Production default |
| WARN | Anomalies |
| ERROR | Operational failures |
3. Implementing Custom Logger
| Interface | Detail |
|---|---|
grpclog.LoggerV2 | Implement for routing to slog/zap/zerolog |
| Per-request logger | Attach 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 |
| zap | Very fast |
| zerolog | Zero-alloc JSON |
6. Logging Metadata
| Field | Source |
|---|---|
| request_id | x-request-id header |
| trace_id / span_id | traceparent |
| user_agent | user-agent |
7. Logging Request Duration
| Measure | Detail |
|---|---|
| Wall-clock | time.Since(start) |
| Histogram | Emit as Prometheus metric |
8. Logging Error Details
| Field | Detail |
|---|---|
| status.code | From status.Code(err) |
| status.message | From st.Message() |
| details | Iterate st.Details() |
| stack | Only at WARN/ERROR — not for Canceled |
9. Filtering Sensitive Data
| Field | Action |
|---|---|
| password / token | Redact |
| PII (email, phone) | Hash or mask |
| Payment data | Never log |
| Custom proto option | (log.sensitive) = true |
10. Integrating with Logging Framework
| Pattern | Detail |
|---|---|
| Per-request logger | Inject via ctx, append fields per layer |
| Async sinks | Buffered shipper to ELK/Loki |
| Sampling | 1% INFO sampling under high load |