Documentation
¶
Overview ¶
Package slogx extends the standard log/slog package with:
- Hierarchical trace/span context propagation via Context(ctx).
- Static and dynamic include/exclude filtering by Go package import path.
- A pluggable Store for in-process log retention.
- An HTTP admin + UI handler for live debugging.
Typical setup:
func main() {
slogx.Setup(
slogx.Includes("ella.to/example"),
slogx.Excludes("example.com/noise"),
)
// ...
}
Inside any function that accepts a context, the caller establishes a new span by shadowing ctx:
func Sum(ctx context.Context, xs ...int) int {
ctx = slogx.Context(ctx)
slog.InfoContext(ctx, "summing", "n", len(xs))
// ...
}
Index ¶
- Constants
- func Concurrent(ctx context.Context) bool
- func Context(ctx context.Context) context.Context
- func HttpHandler() http.Handler
- func LevelName(l slog.Level) string
- func Middleware(next http.Handler) http.Handler
- func ParseLevel(s string) (slog.Level, error)
- func SpanID(ctx context.Context) string
- func SpanPath(ctx context.Context) string
- func TraceID(ctx context.Context) string
- func WithTraceID(ctx context.Context, traceID string) context.Context
- type Format
- type Handler
- func (h *Handler) Enabled(ctx context.Context, level slog.Level) bool
- func (h *Handler) Handle(ctx context.Context, r slog.Record) error
- func (h *Handler) Levels() *levelSet
- func (h *Handler) Store() Store
- func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler
- func (h *Handler) WithGroup(name string) slog.Handler
- type Option
- type Query
- type Record
- type Store
- type TraceSummary
Constants ¶
const ( AttrTraceID = "_traceId" AttrParentID = "_parentId" AttrSpanPath = "_spanPath" AttrGoroutine = "_goroutine" )
Attribute keys injected into every record.
const (
DefaultRingBufferSize = 10_000
)
Default configuration values.
const HeaderTraceID = "X-TRACE-ID"
HeaderTraceID is the HTTP header the middleware reads/writes to carry a trace id across hops.
const LevelOff slog.Level = math.MaxInt32
LevelOff disables logging entirely for a scope (global or a package). It is just a very large slog.Level value so that no real record can meet its threshold.
const QueryTraceID = "log_trace_id"
QueryTraceID is the URL query parameter that overrides the header when present. Matches the user-facing spec.
Variables ¶
This section is empty.
Functions ¶
func Concurrent ¶ added in v0.1.0
Concurrent reports whether ctx belongs to a span that runs on a different goroutine than the span that created its parent context (i.e. it was reached by crossing a `go` statement). Once set, it stays set for all descendant spans.
func Context ¶ added in v0.1.0
Context returns a derived context that starts a new span. On the first call (no trace-id in ctx) a new trace-id is also generated. The returned context carries:
- trace id (stable for the whole trace),
- current span id (this new span),
- span path (slash-joined ancestor chain, including this span),
- goroutine-concurrency flag (true if this span was created on a different goroutine than its parent, or inherited from such a span).
Use at the start of any function that accepts ctx:
ctx = slogx.Context(ctx)
func HttpHandler ¶
HttpHandler returns the admin/UI handler for the currently active slogx. Setup must have been called first.
Endpoints (all JSON unless noted):
GET / -> embedded index.html
GET /traces?limit=100 -> [TraceSummary, ...]
GET /logs?traceId=...&limit -> [Record, ...]
GET /levels -> { "global": "INFO", "packages": [...] }
PATCH /levels -> { "global"?: "DEBUG",
"set"?: {"pkg":"DEBUG"},
"unset"?: ["pkg"] }
func LevelName ¶ added in v0.1.0
LevelName returns the canonical name for a slog.Level used in slogx config ("OFF", "DEBUG", "INFO", "WARN", "ERROR"). Offsets are preserved for levels that don't map to a canonical name.
func Middleware ¶ added in v0.1.0
Middleware establishes a trace-id context and a root span for each inbound HTTP request so that logs emitted during request processing show up under a single trace in the UI.
Trace-id resolution order:
- ?log_trace_id=... (override)
- X-TRACE-ID header (propagation)
- generated
The resolved trace-id is also echoed on the response header.
func ParseLevel ¶ added in v0.1.0
ParseLevel accepts a case-insensitive level name ("off", "debug", "info", "warn", "error") and returns the corresponding slog.Level (or LevelOff).
func SpanID ¶ added in v0.1.0
SpanID returns the current (innermost) span id from ctx, or "" if none.
func SpanPath ¶ added in v0.1.0
SpanPath returns the slash-joined ancestor chain of span ids from ctx.
Types ¶
type Format ¶ added in v0.1.0
type Format int
Format selects the serialization used for the stdout/file sink.
type Handler ¶ added in v0.1.0
type Handler struct {
// contains filtered or unexported fields
}
Handler is slogx's custom slog.Handler. It:
- enriches every record with _traceId, _parentId, _spanPath from ctx,
- filters records by a global + per-package level set,
- fans out to a user-visible slog sink (JSON/text to an io.Writer) and a pluggable Store for the UI.
func Setup ¶ added in v0.1.0
Setup installs slogx as the default slog logger and returns the installed Handler. It is safe to call Setup more than once (the previous handler is replaced).
func (*Handler) Enabled ¶ added in v0.1.0
Enabled implements slog.Handler. Uses the level-set floor so slog can skip record construction entirely when no rule could possibly allow the level.
func (*Handler) Levels ¶ added in v0.1.0
func (h *Handler) Levels() *levelSet
Levels returns the handler's live level set. Exposed for the admin HTTP API.
func (*Handler) Store ¶ added in v0.1.0
Store returns the handler's live Store. Exposed for the admin HTTP API.
type Option ¶ added in v0.1.0
type Option func(*config)
Option configures Setup.
func AddSource ¶ added in v0.1.0
AddSource controls whether the underlying slog sink includes source info.
func GlobalLevel ¶ added in v0.1.0
GlobalLevel sets the minimum level for records from packages that have no explicit override. Use LevelOff to turn logging off by default (handy when you want to opt-in specific packages with PackageLevel).
func Level ¶ added in v0.1.0
Level is an alias for GlobalLevel. Kept for ergonomic parity with slog.
func Output ¶ added in v0.1.0
Output sets the destination for the stdout-style sink. Default: os.Stdout. Pass io.Discard to disable the sink entirely.
func PackageLevel ¶ added in v0.1.0
PackageLevel sets a per-package (prefix) minimum level that overrides the global level. Longest matching prefix wins. Pass LevelOff to silence a package entirely.
slogx.PackageLevel("ella.to/noisy", slogx.LevelOff)
slogx.PackageLevel("ella.to/app/api", slog.LevelDebug)
func RingBufferSize ¶ added in v0.1.0
RingBufferSize sets the capacity of the default ring buffer store. Ignored if WithStore was also provided.
func WithFormat ¶ added in v0.1.0
WithFormat selects JSON or text output for the stdout-style sink.
type Record ¶ added in v0.1.0
type Record struct {
Time time.Time `json:"time"`
Level slog.Level `json:"level"`
Message string `json:"message"`
Source string `json:"source,omitempty"`
Package string `json:"package,omitempty"`
TraceID string `json:"traceId,omitempty"`
ParentID string `json:"parentId,omitempty"`
SpanPath string `json:"spanPath,omitempty"`
Concurrent bool `json:"concurrent,omitempty"`
Attrs map[string]any `json:"attrs,omitempty"`
}
Record is the serialized form of a slog.Record as retained by a Store.
type Store ¶ added in v0.1.0
type Store interface {
Append(r Record)
Query(q Query) []Record
Traces(limit int) []TraceSummary
}
Store retains log records for later inspection.
type TraceSummary ¶ added in v0.1.0
type TraceSummary struct {
TraceID string `json:"traceId"`
FirstTime time.Time `json:"firstTime"`
LastTime time.Time `json:"lastTime"`
Count int `json:"count"`
RootMsg string `json:"rootMessage,omitempty"`
MaxLevel slog.Level `json:"maxLevel"`
}
TraceSummary is a lightweight aggregate used by the UI index.