Skip to content

feat(log): rewrite the logger with automatic format selection - #6

Merged
juicycleff merged 1 commit into
mainfrom
chore/release-v1.3.0
Sep 6, 2026
Merged

juicycleff merged 1 commit into
mainfrom
chore/release-v1.3.0

Conversation

@juicycleff

Copy link
Copy Markdown
Contributor

Releases the logger rewrite as v1.3.0.

Why this PR exists

The code already landed in #5. That PR was squash-merged with its own title as
the subject, Feat/logger rewrite (#5), which semantic-release cannot parse a
type from, so it computed no release and v1.2.2 still points at the old
logger. This PR carries a parseable subject so the release fires, and refreshes
log/llm.txt, which still documented a
NewBeautifulLogger(opts ...BeautifulLoggerOption) that no longer exists.

Merge this as a squash and keep the PR title as the commit subject. The
title is the conventional-commit message semantic-release reads. Changing it to
something like "Release v1.3.0" reintroduces exactly the problem this fixes.

feat maps to a minor bump in .releaserc.json, so v1.2.2 becomes v1.3.0.

Read before upgrading from v1.2.x

This removes exported API and ships as a minor version by deliberate
choice, so go get -u picks it up without warning.

Gone: ZapField, CustomField, LazyField, WrapZapField, WrapZapFields,
FieldsToZap, Object, Array, ValidateField, SanitizeFields, FieldMap,
MergeFields, FormatConfig, DefaultFormatConfig, BeautifulColorScheme,
DefaultBeautifulColorScheme, NewDevelopmentLoggerWithLevel, and the
BeautifulLogger concrete type.

Changed: Field is a struct rather than an interface. Key() and Value()
still work, ZapField() does not exist, and the type can no longer be
implemented outside the package.

Known affected repositories today: forge-w3 uses most of the removed set,
authsome uses FieldMap and BeautifulLogger. Both are pinned to earlier
versions and keep working until they bump.

Logger and SugarLogger are unchanged, and the deprecated constructors all
still work.

What shipped

One implementation replaces four and picks its own output format. A terminal
gets aligned coloured columns, anything else gets JSON, FORGE_LOG_FORMAT
overrides both. Under go test it resolves to a noop so suites stay quiet;
go test -v brings the output back.

before after
pretty, 5 fields 3218 ns, 2402 B, 65 allocs 197 ns, 0 B, 0 allocs
JSON, 5 fields 876 ns, 1 alloc (zap floor) 274 ns, 0 allocs

Eight reproduced defects fixed, including caller attribution pointing at
asm_arm64.s:1447, NewProductionLogger silently dropping ~89% of lines to
zap's sampler, SetGlobalLogger being a no-op for all but one logger type, and
randomised field ordering.

The code for this landed in #5, whose squash subject was the pull request
title. semantic-release cannot parse a type from it, so it computed no release
and v1.2.2 still points at the old logger. This carries the release signal and
the notes that subject never had, and refreshes log/llm.txt, which still
documented a NewBeautifulLogger(opts ...BeautifulLoggerOption) that no longer
exists.

One implementation replaces four, and it picks its own output format. A
terminal gets aligned coloured columns, anything else gets JSON, and
FORGE_LOG_FORMAT overrides both. Inside a go test binary it resolves to a noop
so suites stay quiet, while go test -v brings the output back.

Both encoders run at zero allocations per line. The human-readable one went
from 3218 ns/op, 2402 B and 65 allocations to 197 ns/op and none. The JSON one
runs at 274 ns/op against the 876 ns zap floor it replaces.

Eight reproduced defects are fixed. Caller attribution pointed at
asm_arm64.s:1447 rather than the call site. NewProductionLogger silently
dropped about 89% of lines to zap's default sampler, 109 written for 1000
emitted. SetGlobalLogger was a no-op for every logger type but one. Field order
was randomised per line. Minimalist mode discarded every structured field.
NewBeautifulLoggerJSON emitted no JSON. The development path could tear a line
under concurrency. Build errors were dropped, LoggingConfig.Output was never
read, output was hardcoded to stdout, and nothing detected a TTY.

Read this before upgrading from v1.2.x. Exported API is removed, and this ships
as a minor version by deliberate choice, so go get -u will pick it up without
warning.

Gone: ZapField, CustomField, LazyField, WrapZapField, WrapZapFields,
FieldsToZap, Object, Array, ValidateField, SanitizeFields, FieldMap,
MergeFields, FormatConfig, DefaultFormatConfig, BeautifulColorScheme,
DefaultBeautifulColorScheme, NewDevelopmentLoggerWithLevel, and the
BeautifulLogger concrete type.

Changed: Field is a struct rather than an interface. Key() and Value() still
work, ZapField() does not exist, and the type can no longer be implemented
outside this package.

Known affected repositories as of this release: forge-w3, which uses most of
the removed set, and authsome, which uses FieldMap and BeautifulLogger. Both
are pinned to earlier versions and keep working until they bump.

Still working, all returning the Logger interface: NewBeautifulLogger,
NewBeautifulLoggerCompact, NewBeautifulLoggerMinimal, NewBeautifulLoggerJSON,
NewDevelopmentLogger and NewProductionLogger. Logger and SugarLogger are
unchanged.
@juicycleff
juicycleff merged commit d7271db into main Sep 6, 2026
14 checks passed
github-actions Bot added a commit that referenced this pull request Sep 6, 2026
## [1.3.0](v1.2.2...v1.3.0) (2026-09-06)

### Features

* **log:** rewrite the logger with automatic format selection ([d7271db](d7271db)), closes [#6](#6)
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.3.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant