logx

Overview

A standalone slog composition (console format, level filtering, fanout) plus a PHP/Monolog-style console formatter.

logx is a standalone Go module (github.com/gp-system/logx, +logx/monolog): a small toolkit for composing the default log/slog logger. Three combinators (ConsoleHandler, LevelFilter, Fanout) give you a console format switch, a minimum-level gate and a Monolog-style multi-handler stack, all as plain slog.Handler values. On top, logx/monolog is a standalone formatter that renders [date] channel.LEVEL: message {context} lines, PHP-style, with full-path stack traces pulled out of an errs error.

It used to live as a subpackage of telemetry, imported as telemetry's own logx subpackage; it has since moved into its own module, because composing a console logger has nothing to do with OpenTelemetry or Sentry wiring, and a program that just wants readable console logs shouldn't have to pull in the OTel SDK or sentry-go to get them. telemetry.Setup still uses logx exactly as before, just as a regular module dependency instead of a subpackage: nothing about the runtime behavior changed, only which module the code lives in.

Its only dependency is errs, and only from logx/monolog: the formatter reads errs.CodeOf and walks errs.FullFrames/errs.Frame to render a wrapped error's stack. The logx package itself (ConsoleHandler, LevelFilter, Fanout, Config) imports nothing beyond the standard library.

Install

go get github.com/gp-system/logx@main # no tagged release yet
Import pathWhat it adds
github.com/gp-system/logxthe slog composition: ConsoleHandler, LevelFilter, Fanout, Config
github.com/gp-system/logx/monologthe PHP/Monolog-style console formatter, usable as a plain slog.Handler on its own

Configuration

logx.Config carries no env prefix of its own: the variables are meant to be embedded unprefixed, at the top level of whatever composes them (in the framework, telemetry.Config's Log field).

VariableDefaultMeaning
LOG_LEVELINFOthe logger's minimum level (applies to every handler in the fanout)
LOG_STDOUTfalsealso write to the console in production mode (JSON); leave off when a collector scrapes container output, or you ingest twice
LOG_FORMATempty (auto)the console format: empty means text in dev / JSON in prod; monolog selects PHP/Monolog-style lines regardless of mode

An unknown LOG_FORMAT value fails Config.Validate() with an error instead of silently falling back.

The composition: Fanout and LevelFilter

Three small slog.Handler combinators are the whole package:

func ConsoleHandler(w io.Writer, cfg Config, dev bool, channel string) slog.Handler
func Fanout(handlers ...slog.Handler) slog.Handler          // several handlers, one record each
func LevelFilter(min slog.Level, next slog.Handler) slog.Handler // a minimum-level gate

LevelFilter exists because not every leaf handler filters on its own (an OTLP bridge, for instance, forwards every record it is given): put it outermost and every handler behind it only ever sees records at or above the minimum level. Fanout hands each handler its own clone of the record and honors Enabled as a per-handler gate; with a single handler it returns it as-is, allocation-free.

Usage

A plain Go program, no framework, no telemetry:

main.go
package main

import (
    "log/slog"
    "os"

    "github.com/gp-system/logx"
)

func main() {
    cfg := logx.Config{Level: slog.LevelInfo, Format: "monolog"}

    slog.SetDefault(slog.New(
        logx.LevelFilter(cfg.Level, logx.Fanout(
            logx.ConsoleHandler(os.Stdout, cfg, true, "myapp"),
            // add more slog.Handler values here: a file handler, a custom sink, ...
        )),
    ))

    slog.Info("service starting", "addr", ":3000")
}

Inside the framework, telemetry.Setup builds the default logger the same way, just with two more handlers in the fanout: the OTel log bridge and the Sentry capture handler. See Telemetry: Logging for that composition.

  • logx: Monolog formatter: the [date] channel.LEVEL: message format, stack traces from errs, and a Laravel/Symfony concept mapping.
  • Telemetry: Overview: how telemetry.Setup fans logx's console handler out alongside the OTel bridge and the Sentry handler.
  • errs: Overview: the error type logx/monolog renders stack traces from.
Copyright © 2026