Write JSON logs in the shape Portainer's viewer reads (1.3.0) #8

Merged
joeyr merged 1 commit from feat/portainer-logs into main 2026-10-05 20:33:16 -05:00
Owner

log.format: json now writes the shape Portainer's log viewer colours: time (local YYYY-MM-DD HH:mm:ss), level, caller, message, and a stack_trace array on errors.

  • logger/portainer.go (new): an encoder config, a level encoder that folds dpanic/panic/fatal into error, and a core wrapper that turns zap's stack string into an array of up to 12 {func, source, line} frames, module path trimmed.
  • logger/loader.go: a three-line hook for the json format. console is unchanged.
  • caller stays zap's package/file.go:line rather than closed phase tags: Portainer shows the last two segments, which is exactly that, and phase tags would touch nearly every upstream log call. Recorded in CLAUDE.md.
  • Tests: the keys and their shapes, the level mapping, a real stack trace, and the frame cap. Also checked with the built image against an unreachable Jellyfin: the info lines and both error lines come out in this shape.
  • VERSION 1.3.0, CHANGELOG, config-example.yml.

🤖 Generated with Claude Code

`log.format: json` now writes the shape Portainer's log viewer colours: `time` (local `YYYY-MM-DD HH:mm:ss`), `level`, `caller`, `message`, and a `stack_trace` array on errors. - `logger/portainer.go` (new): an encoder config, a level encoder that folds dpanic/panic/fatal into `error`, and a core wrapper that turns zap's stack string into an array of up to 12 `{func, source, line}` frames, module path trimmed. - `logger/loader.go`: a three-line hook for the json format. `console` is unchanged. - `caller` stays zap's `package/file.go:line` rather than closed phase tags: Portainer shows the last two segments, which is exactly that, and phase tags would touch nearly every upstream log call. Recorded in CLAUDE.md. - Tests: the keys and their shapes, the level mapping, a real stack trace, and the frame cap. Also checked with the built image against an unreachable Jellyfin: the info lines and both error lines come out in this shape. - VERSION 1.3.0, CHANGELOG, config-example.yml. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Write JSON logs in the shape Portainer's viewer reads (1.3.0)
All checks were successful
CI / lint (pull_request) Successful in 56s
CI / image (pull_request) Has been skipped
CI / gate (pull_request) Successful in 1m0s
69f44741b9
Portainer's JSON log viewer colours exactly five keys: time (a string),
level, caller, message and stack_trace (an array of {func, source,
line}). zap's production JSON used ts, msg and a stacktrace string, so
every line rendered as plain trailing fields.

logger/portainer.go builds the json logger: time as local
"2006-01-02 15:04:05", lowercase levels with dpanic/panic/fatal folded
into error, and a core wrapper that moves zap's stack string into a
stack_trace array of at most 12 frames, module path trimmed from the
function names. caller stays zap's package/file.go:line, the two
segments Portainer shows; phase tags would touch nearly every upstream
log call. The console format is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
joeyr merged commit 1ed1b6bd80 into main 2026-10-05 20:33:16 -05:00
joeyr deleted branch feat/portainer-logs 2026-10-05 20:33:17 -05:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
joeyr/jellyfin-newsletter!8
No description provided.