Documentation
¶
Overview ¶
Package logger is the project-wide slog wrapper. All logging goes through context.Context — services and handlers must NOT embed a *slog.Logger field. Use Load(ctx) to fetch the logger and WithService(ctx, name) at the service boundary so every record carries the same "service" attribute.
Output format is fixed: text handler to stderr with RFC3339 timestamps and stable attribute ordering. This guarantees a single consistent format across the entire process; do not construct ad-hoc slog.New(...) instances in service code — call NewLogger or NewTestLogger here so format and handler options stay aligned.
Index ¶
- Variables
- func APIConsoleMiddleware() echo.MiddlewareFunc
- func AddAttrs(ctx context.Context, attrs ...slog.Attr) context.Context
- func EchoMiddleware(logger *slog.Logger) echo.MiddlewareFunc
- func Load(ctx context.Context) *slog.Logger
- func Middleware(logger *slog.Logger) func(http.Handler) http.Handler
- func NewLogger(level slog.Level) *slog.Logger
- func NewTestLogger() *slog.Logger
- func Save(ctx context.Context, logger *slog.Logger) context.Context
- func WithService(ctx context.Context, name string) context.Context
- func WithWorker(ctx context.Context, service, job string) context.Context
- type CapturedRequest
- type RequestRingBuffer
Constants ¶
This section is empty.
Variables ¶
var GlobalRingBuffer = NewRequestRingBuffer(defaultBufferSize)
GlobalRingBuffer is the global buffer for the Live API Console. It stores the last 100 requests.
var Key = ctxval.NewKey[*slog.Logger]("logger") //nolint:gochecknoglobals // existing issue.
Key is the typed context key under which the logger is stored. Exported so middleware that wants raw ctxval access can reuse it.
Functions ¶
func APIConsoleMiddleware ¶
func APIConsoleMiddleware() echo.MiddlewareFunc
APIConsoleMiddleware captures incoming API requests and stores them in the ring buffer. It should be injected after standard loggers but before request processing.
func AddAttrs ¶
AddAttrs returns a child context whose logger has attrs pre-attached to every record. slog.Logger.With does not mutate the parent so this is safe for concurrent use across requests.
func EchoMiddleware ¶
func EchoMiddleware(logger *slog.Logger) echo.MiddlewareFunc
EchoMiddleware creates an Echo middleware that injects a logger into the request context.
func Load ¶
Load returns the logger carried on ctx, or slog.Default() when none is set. Always returns non-nil so callers can chain methods without a guard.
func Middleware ¶
Middleware creates an HTTP middleware that injects a logger into the request context.
func NewTestLogger ¶
NewTestLogger returns a logger with debug level enabled, useful in tests.
func WithService ¶
WithService returns a child context whose logger carries service=<name>. Call this once at the entry of every service handler so downstream records emitted via Load(ctx) are uniformly tagged. The service tag persists across AddAttrs calls because slog.Logger.With layers attributes.
func WithWorker ¶
WithWorker returns a child context whose logger carries service=<service> and worker=<service>-<job>, so records emitted by a background routine are attributable to the specific job that produced them.
Safety rules (the logger is a *slog.Logger pointer carried in ctx):
- Call this ONCE at the entry of the worker goroutine, never inside a loop. Each call layers attributes onto a new logger; repeating it on a long-lived context would grow the attribute chain (and memory) without bound.
- Derive ctx from the process/lifecycle context (e.g. the janitor context), never from a per-request context, so worker logs don't inherit request_id and don't pin a finished request alive.
Enrichment is copy-on-write: slog.Logger.With does not mutate the parent, so concurrent workers and requests never corrupt each other's logger.
Types ¶
type CapturedRequest ¶
type CapturedRequest struct {
Timestamp time.Time `json:"timestamp"`
Headers map[string]string `json:"headers"`
ID string `json:"id"`
Method string `json:"method"`
Path string `json:"path"`
Body string `json:"body,omitempty"`
Status int `json:"status"`
Duration time.Duration `json:"duration_ms"`
}
CapturedRequest represents a single HTTP request captured by the console middleware.
type RequestRingBuffer ¶
type RequestRingBuffer struct {
// contains filtered or unexported fields
}
RequestRingBuffer holds the last N captured requests.
func NewRequestRingBuffer ¶
func NewRequestRingBuffer(maxSize int) *RequestRingBuffer
NewRequestRingBuffer creates a new ring buffer for captured requests.
func (*RequestRingBuffer) Add ¶
func (r *RequestRingBuffer) Add(req *CapturedRequest)
Add appends a new request into the ring buffer and notifies subscribers.
func (*RequestRingBuffer) GetAll ¶
func (r *RequestRingBuffer) GetAll() []*CapturedRequest
GetAll returns all captured requests in chronological order.
func (*RequestRingBuffer) Subscribe ¶
func (r *RequestRingBuffer) Subscribe() chan *CapturedRequest
Subscribe adds a channel to receive incoming requests.
func (*RequestRingBuffer) Unsubscribe ¶
func (r *RequestRingBuffer) Unsubscribe(ch chan *CapturedRequest)
Unsubscribe removes a channel from receiving requests.