100 lines
2.5 KiB
Go
100 lines
2.5 KiB
Go
package logging
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
)
|
|
|
|
type contextKey int
|
|
|
|
const (
|
|
loggerKey contextKey = iota
|
|
requestIDKey
|
|
userIDKey
|
|
traceIDKey
|
|
)
|
|
|
|
// NewContext returns a new context with the logger attached.
|
|
func NewContext(ctx context.Context, logger *Logger) context.Context {
|
|
return context.WithValue(ctx, loggerKey, logger)
|
|
}
|
|
|
|
// FromContext extracts the logger from the context.
|
|
// Returns a no-op logger if none is found.
|
|
func FromContext(ctx context.Context) *Logger {
|
|
if logger, ok := ctx.Value(loggerKey).(*Logger); ok {
|
|
return logger
|
|
}
|
|
return Nop()
|
|
}
|
|
|
|
// WithRequestID adds a request ID to the context.
|
|
func WithRequestID(ctx context.Context, requestID string) context.Context {
|
|
return context.WithValue(ctx, requestIDKey, requestID)
|
|
}
|
|
|
|
// RequestIDFromContext extracts the request ID from the context.
|
|
func RequestIDFromContext(ctx context.Context) string {
|
|
if id, ok := ctx.Value(requestIDKey).(string); ok {
|
|
return id
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// WithUserID adds a user ID to the context.
|
|
func WithUserID(ctx context.Context, userID string) context.Context {
|
|
return context.WithValue(ctx, userIDKey, userID)
|
|
}
|
|
|
|
// UserIDFromContext extracts the user ID from the context.
|
|
func UserIDFromContext(ctx context.Context) string {
|
|
if id, ok := ctx.Value(userIDKey).(string); ok {
|
|
return id
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// WithTraceID adds a trace ID to the context.
|
|
func WithTraceID(ctx context.Context, traceID string) context.Context {
|
|
return context.WithValue(ctx, traceIDKey, traceID)
|
|
}
|
|
|
|
// TraceIDFromContext extracts the trace ID from the context.
|
|
func TraceIDFromContext(ctx context.Context) string {
|
|
if id, ok := ctx.Value(traceIDKey).(string); ok {
|
|
return id
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// ContextAttrs returns slog attributes from context values.
|
|
func ContextAttrs(ctx context.Context) []slog.Attr {
|
|
var attrs []slog.Attr
|
|
|
|
if id := RequestIDFromContext(ctx); id != "" {
|
|
attrs = append(attrs, slog.String("request_id", id))
|
|
}
|
|
if id := UserIDFromContext(ctx); id != "" {
|
|
attrs = append(attrs, slog.String("user_id", id))
|
|
}
|
|
if id := TraceIDFromContext(ctx); id != "" {
|
|
attrs = append(attrs, slog.String("trace_id", id))
|
|
}
|
|
|
|
return attrs
|
|
}
|
|
|
|
// LoggerWithContext returns a logger enriched with context attributes.
|
|
func LoggerWithContext(ctx context.Context, logger *Logger) *Logger {
|
|
attrs := ContextAttrs(ctx)
|
|
if len(attrs) == 0 {
|
|
return logger
|
|
}
|
|
|
|
args := make([]any, 0, len(attrs)*2)
|
|
for _, attr := range attrs {
|
|
args = append(args, attr.Key, attr.Value.Any())
|
|
}
|
|
return logger.With(args...)
|
|
}
|