rdev/internal/logging/context.go
jordan d69da6d627 feat: add structured logging infrastructure and SDLC extensions
Major changes:
- Add internal/logging package with field constants, context propagation,
  sensitive data auto-redaction, and per-component log levels
- Add worker timeout constants (TimeoutQuickOp, TimeoutHealthCheck, etc.)
- Extend SDLC with callback handlers, generate endpoints, and executor
- Add new cookbook trees for aeries and slackpath progression
- Add skeleton templates for queue, realtime, and microservices
- Add worker component template with async job processing
- Refactor services and handlers to use new logging infrastructure
- Split component.go into component_infra.go and component_listing.go

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 22:56:04 -07:00

71 lines
1.9 KiB
Go

package logging
import (
"context"
)
// contextKey is the key type for context values to avoid collisions.
type contextKey struct{}
// loggerKey is the key used to store the logger in context.
var loggerKey = contextKey{}
// defaultLogger is used when no logger is found in context.
// It's initialized lazily to avoid import cycles.
var defaultLogger *Logger
// SetDefault sets the default logger used when FromContext finds no logger.
// Call this during application initialization.
func SetDefault(l *Logger) {
defaultLogger = l
}
// Default returns the default logger.
// Returns a nop logger if SetDefault was never called.
func Default() *Logger {
if defaultLogger == nil {
return Nop()
}
return defaultLogger
}
// WithContext returns a new context with the logger attached.
func WithContext(ctx context.Context, l *Logger) context.Context {
return context.WithValue(ctx, loggerKey, l)
}
// FromContext extracts the logger from context.
// Returns the default logger if no logger is found.
func FromContext(ctx context.Context) *Logger {
if ctx == nil {
return Default()
}
if l, ok := ctx.Value(loggerKey).(*Logger); ok {
return l
}
return Default()
}
// WithFields returns a new context with additional fields added to the logger.
// This is a convenience function for adding fields in middleware.
func WithFields(ctx context.Context, args ...any) context.Context {
l := FromContext(ctx).With(args...)
return WithContext(ctx, l)
}
// WithRequestContext returns a new context with request-scoped fields.
// This is typically called by middleware to enrich the logger.
func WithRequestContext(ctx context.Context, requestID, userID, apiKeyID string) context.Context {
l := FromContext(ctx)
if requestID != "" {
l = l.WithRequestID(requestID)
}
if userID != "" {
l = l.WithUserID(userID)
}
if apiKeyID != "" {
l = l.With(FieldAPIKeyID, apiKeyID)
}
return WithContext(ctx, l)
}