pretty console logging via pterm#3
Merged
Merged
Conversation
Replace the tint console sink with a pterm logger so console output is consistent with any pterm tables, spinners, and boxes a consumer prints directly (pterm is a process-global singleton). Render through a small custom slog handler instead of pterm's bundled bridge, because that bridge drops grouped key prefixes, keeps only the last WithAttrs, and orders fields off a map. The handler preserves attribute order, prefixes grouped keys, and accumulates chained With. Add Config.Console for time/caller/width, examples.md covering the major features, a runnable showcase (bin/test showcase), and drop tint.
Time is a tri-state (Auto/On/Off): Auto shows the timestamp only when stderr is captured, not on a local terminal, tracking the same TTY signal as color. Console timestamps are honest local time (no false Z); OTLP still carries the absolute instant that SigNoz shows in UTC. Compact (off by default) keeps args on the message line; the default expands every arg onto its own line, values aligned in a column, sized so the message never wraps. Caller comes from the record PC (the true call site) as a normal, aligned arg rather than pterm's stack-offset guess. Color is scoped per stream: NO_COLOR disables globally, but a captured console strips its own SGR via a plainWriter instead of disabling color for pterm output a consumer sends to its terminal.
The console is a live dev tail, so the date is noise; OTLP carries the absolute timestamp SigNoz shows in UTC. Keep local wall-clock to the ms.
Replace the Compact bool with a Layout tri-state. LayoutAuto (default) trees the args where multi-line reads well — a terminal or GitHub Actions — and keeps the record on one line for other captured output like journald, where each newline is a separate entry, so the journal stays a passable log. LayoutTree/LayoutOneline force it. Drop Console.MaxWidth: the tree sizes each line to its message and the one-line layout never wraps, so it had no role left.
Color now tracks the same "rich viewer" signal as layout: a terminal or GitHub Actions gets color and the tree; journald, files, and other line-oriented capture get plain, one-line output. Previously color was stripped for any non-tty, so GitHub logs were plain despite rendering ANSI fine.
pterm clamps MaxWidth down to the stdout terminal width (80 by fallback) regardless of the sink, so a long one-line record wrapped into the tree and split across several journald entries, defeating the point of the layout. Rejoin pterm's wrapped continuations on the stream so one record stays one physical line. Drop the noWrap sentinel it replaces. Add unit tests for the time/layout decisions, plainWriter, onelineWriter, and a long-record regression guard.
There was a problem hiding this comment.
Pull request overview
This PR replaces the console logging sink from tint to a custom pterm-backed slog.Handler, so console logs share styling with other pterm output (tables/spinners/boxes) while preserving slog attribute ordering, group key prefixes, and chained With accumulation. It also introduces configurable console behavior (timestamp, caller, layout) that adapts based on whether output is going to a “rich viewer” (TTY/GitHub Actions) vs line-oriented capture.
Changes:
- Swap console sink implementation from
tintto a customptermHandler, including one-line capture-safe output and optional aligned tree layout. - Add
Config.ConsolewithTimeModeandLayouttuning; update docs and add runnable “pretty/showcase” test harness paths. - Add/extend tests to lock in grouping/With behavior, layout/time mode behavior, and capture invariants.
Reviewed changes
Copilot reviewed 9 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Documents the new Console config and notes the switch to pterm for console output. |
| pretty_test.go | Updates the “kitchen sink” pretty output test to use the new console config and timestamp toggling. |
| log.go | Replaces tint console handler with a custom pterm slog handler and capture-safe formatting utilities. |
| log_internal_test.go | Updates trace handler tests and adds unit tests for the new console handler behavior. |
| go.mod | Drops tint; adds pterm and go-runewidth (plus indirect deps). |
| go.sum | Updates module checksums for the new dependency set. |
| examples.md | Adds a new examples document showcasing pterm-styled output and console tuning. |
| example_test.go | Adds an opt-in runnable showcase test that prints the examples end-to-end. |
| doc.go | Updates package docs to describe the pterm console sink and the custom handler rationale. |
| config.go | Adds Config.Console, TimeMode, and Layout configuration types and logic. |
| bin/test | Extends the test runner with showcase and updates pretty to demonstrate time variants. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
turkosaurus
commented
Jul 4, 2026
The console showcase (examples.md sections 2-12, TestShowcase, bin/test showcase) documented pterm's own API, not signals, and would drift as pterm changes. Keep examples.md to signals' surface: the logger and Console tuning, with a pointer to pterm for its printers. Move the package doc from doc.go up to signals.go; a dedicated doc.go is optional, and one file already holds Setup.
turkosaurus
added a commit
that referenced
this pull request
Jul 5, 2026
The pretty console added in #3 maps every slog threshold at or above Error to pterm's Error level, so a caller can no longer mute the console. The old tint sink honored a numeric threshold, so StderrLevel of slog.LevelError+1 silenced it. Callers that render their own pterm output, like cmd/infra's feedback lines, now get every Error line twice because both their render and signals' console print it. Map a threshold above Error to pterm.LogLevelDisabled, restoring the mute: StderrLevel of slog.LevelError+1 silences the console sink while OTLP still ships every level. Adds ptermLevel and console-mute tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the tint console sink with a pterm logger, so console output shares styling with any pterm tables, spinners, or boxes a consumer prints directly (pterm is a process-global singleton).
Rendering goes through a small custom slog handler rather than pterm's bundled bridge, because that bridge drops group prefixes, keeps only the last
With, and orders fields off a map. This handler preserves attribute order, prefixes grouped keys, and accumulates chainedWith. The OTLP sink is unchanged.Console behavior adapts to where output lands, keyed on a "rich viewer" signal (a terminal or GitHub Actions):
Console.Layout(auto): a tree with one arg per line and values aligned in a column for a rich viewer, one line otherwise so journald and other line-oriented capture get one entry per record.Console.Time(auto): timestamp hidden on a local terminal and shown when captured, because a captured log needs its own clock. Local wall-clock to the millisecond with no date, because OTLP carries the absolute timestamp SigNoz shows in UTC.Caller (DEBUG or
Console.Caller) comes from the record PC, the true call site, as a normal aligned arg rather than pterm's stack-offset guess.Adds examples.md (logger and Console tuning) and drops tint.
Closes #4. Duplicate of grackleclub/cloud#327.