feat(loglayer)!: v2 — remove prefix mutation, bump every module to /v2#61
Merged
Conversation
Phase 1 of the v2 cascade. Core changes: - Remove applyPrefix from loglayer.go and the three call sites in builder.go, dispatch.go, log.go. The core no longer mutates Messages[0]; the prefix flows through TransportParams.Prefix and each transport renders it however it likes. - Add transport.JoinPrefixAndMessages helper for transports that want the v1 'prefix folded into Messages[0]' rendering. Early- return on empty prefix or non-string Messages[0]; only allocates when there's an actual prefix to merge. Transport updates (preserving v1 user-visible behavior): - console, pretty, structured, testing, zerolog, zap, slog, logrus, phuslu, charmlog, http, sentry, otellog, gcplogging: each calls the helper at the top of SendToLogger before its existing rendering. - testing.LogLine gained a Prefix field for tests that want the unmangled signal. - blank intentionally left as-is (it's a raw-passthrough transport for advanced users). - lumberjack inherits behavior from structured via delegation. Test fixture updates: - example_test.go's exampleTransport calls the helper. - TestPrefix and TestPrefixSurfacedOnTransportParams updated for the new contract (prefix on params.Prefix, not in Messages[0]). Phase 2 (smart rendering opt-ins for cli/structured/pretty), Phase 3 (module path bumps to /v2), and Phase 4 (changesets + docs) follow.
Phase 3 of the v2 cascade. Module path changes: - Main module: go.loglayer.dev -> go.loglayer.dev/v2. - Every transport sub-module: go.loglayer.dev/transports/<name> -> go.loglayer.dev/transports/<name>/v2. - Every plugin sub-module: same pattern (/plugins/<name>/v2). - Every integration sub-module: same (/integrations/<name>/v2). - All 6 example sub-modules: same. - plugins/datadogtrace/livetest: nested module also bumped. Import path updates (mechanical): - All Go file imports now resolve via the /v2 path. - Each sub-module's go.mod has its replace/require lines pointed at the /v2 path. - The placeholder version on require lines was bumped from v0.0.0-00010101000000-000000000000 to v2.0.0-00010101000000-000000000000 because Go module rules require the require version to match the major (v2.x.y for /v2 modules). This is a BREAKING CHANGE for every consumer: import paths must be updated to /v2 across the board. Phase 4 (changesets, per-module docs, migration guide, whats-new entry) follows.
…geset Phase 4 of the v2 cascade: docs + changesets. - New docs/src/migrating-to-v2.md walking the import-path bump, the prefix flow change, and the two transport strategies (preserve via JoinPrefixAndMessages or smart render). - Sidebar entry under Introduction. - whats-new.md gets a v2.0.0 entry at the top of May 02, 2026. - Multi-package changeset bumps every monorel-managed module to :major (27 packages: main + 19 transports + 6 plugins + 2 integrations). - creating-transports.md, creating-plugins.md, cheatsheet.md, llms.txt, llms-full.txt updated to remove the 'legacy auto- prepend' caveats and document the v2 contract.
Lefthook's pre-push tidy reordered the require blocks on some sub-modules (lumberjack, others) so all go.loglayer.dev-prefixed requires are alphabetically sorted.
Critical: - Update TransportParams.Prefix GoDoc (loglayer.go) to describe v2 contract; remove the stale 'auto-prepend will be removed in a future major version' caveat that referred to v2 itself. - Update Config.Prefix GoDoc (types.go) to describe v2 contract. - Update internal LogLayer.prefix field comment to describe v2 propagation model. - Update whats-new.md v1.7.0 entry to note the auto-prepend was removed in v2.0.0 (resolves the chronological contradiction). - Rewrite docs/src/transports/cli.md 'Using WithPrefix' section for v2: the cli transport reads params.Prefix and renders the prefix in dim grey, separate from the level color. - Delete .changeset/prefix-on-params.md (revived from a stale branch off main; was already consumed by v1.7.0 release). Important: - Sanitize the user prefix in cli's smart-rendering path (sanitize.Message on params.Prefix) so an env- or config-loaded prefix can't smuggle ANSI / CRLF through the new layer. - Add 4 new cli tests: WithPrefix renders inline, WithPrefix gets dim-grey ANSI separate from level color, WithPrefix sanitizes ANSI smuggling, info-level WithPrefix only colors the prefix (body unstyled). - Add direct unit tests for transport.JoinPrefixAndMessages covering all five branches (empty prefix, nil messages, empty messages, non-string first arg, normal case with fresh-slice guarantee). - Sweep em-dashes from new content (migrating-to-v2.md, cli.md, changeset body). - Rename ':::tip Pre-v1.7.0 readers' callout to 'Pre-v2 readers'. - Add 'Do I have to migrate?' and 'Why this change' lede sections to migrating-to-v2.md, with the existing buried '## Why' tail consolidated into the lede. Skipped (deferred to follow-up): - C1 (37 doc pages with v1 import paths): mechanical sweep that fits a separate PR; build still passes since the import paths in the docs are illustrative, not load-bearing. - AGENTS.md / CONTRIBUTING.md template updates for new sub-modules: same follow-up. - I2 (contract test for prefix in transport/transporttest): worth but not blocking. - I4 (cli WithPrefix Example with // Output): would need to omit // Output for color cases; the new tests cover the same ground. - I5 (no benchmark for prefix path): non-blocking; claim about 'one string compare' is verifiable via the helper's source. - I6 (lltest 'byte-for-byte equivalent' comment): pre-existing drift; unrelated to v2. - I7 (doc.go list of helpers): minor; doesn't affect users.
Contributor
Author
|
Round-1 review fixes pushed in Critical (all fixed)
Important (most fixed)
Deferred to follow-up (with reasons)
Tests still green; per-module suite passes; docs build clean. |
Per direction: loglayer-go is too new to make v1-vs-v2 framing visible to readers who land on regular docs. Sweep all 'as of v2' / 'preserve v1 behavior' / 'pre-v2 readers' / 'in v2' references out of regular docs and replace with plain present-tense descriptions of what the code does today. Files swept: - loglayer.go: TransportParams.Prefix GoDoc and internal prefix field comment now describe the contract without versioning. - types.go: Config.Prefix GoDoc same. - transport/helpers.go: JoinPrefixAndMessages doc reframed as 'fold prefix into the first message' rather than 'preserve v1 behavior'. - transports/*/*.go: comment cleanup at every SendToLogger call site that called the helper (the line was 'Preserve the v1 prefix folded into Messages[0] rendering; the core no longer mutates messages, transports own it now' — now 'Fold the prefix into Messages[0] for the rendered output; transports own this rendering choice'). - docs/src/transports/creating-transports.md: drop 'As of v2' and 'Pre-v2 readers' callout; describe current contract plainly. - docs/src/transports/cli.md: drop 'behavior change vs. v1' paragraph; keep just the 'set ColorNever for monochrome' tip. - docs/src/plugins/creating-plugins.md: drop 'In v2' qualifier on the read-only contract. - docs/src/cheatsheet.md: drop 'as of v2' framing; replace stale 'prefix prepended' inline comment with 'Prefix value'. - docs/src/public/llms.txt and llms-full.txt: drop 'as of v2' / 'in v2' framing; update 'Out of Scope (v1)' heading to 'Currently out of scope'. - docs/src/whats-new.md: tighten the v1.7.0 line so the parenthetical doesn't self-contradict. - docs/src/migrating-to-v2.md: em-dash sweep on the new lede. Kept intact (per direction): - whats-new.md v2.0.0 entry — still names v1.7.0 / v2.0.0 because whats-new is the version-history page. - migrating-to-v2.md — still names v1 / v2 because it's the migration page. - .changeset/v2-prefix-passthrough.md — the changeset body is the canonical v2 release note.
Round-3 reviewer found three sites where the sed sweep didn't match because their wording differed slightly from the canonical 'Preserve the v1 ... rendering' pattern: - dispatch.go formatLog GoDoc: 'preserve the v1 prepended-into- messages shape' -> 'fold it into the first message string'. - builder.go dispatch inline comment: same rewrite. - transports/testing/testing.go SendToLogger inline comment: reframed as 'Fold the prefix into Messages[0] so test fixtures see one rendered message string'. Plus three test/example files the regex missed: - example_test.go exampleTransport: comment reframed as 'Fold the prefix into the message so the examples render as one blob'. - loglayer_test.go TestPrefixSurfacedOnTransportParams: drop v2/v1 framing. - transports/cli/cli_test.go TestWithPrefixRendersInline: drop 'v2 contract' framing.
…en-wrap Round-4 reviewer's only finding was cosmetic: the prior comment hyphen-wrapped 'transport.JoinPrefix-\nAndMessages' across two lines, which is unusual in Go comments. Reflow the comment so the full identifier sits on one line.
This was referenced May 2, 2026
theogravity
added a commit
that referenced
this pull request
May 2, 2026
Follow-up to the v2.0.0 release (#61, #63) and user-facing import sweep (#65) addressing issues surfaced by a four-reviewer documentation pass. Critical: - creating-transports.md: drop stale "already prefix-applied" comment on TransportParams.Messages; the core no longer mutates Messages[0]. - llms.txt / llms-full.txt: add transports/cli to the Renderers catalog and install snippet (shipped at v2.0.0 but was missing from both). - introduction.md: show the lltest "go.loglayer.dev/transports/testing/v2" import alias in the test-capture snippet. Important: - GoDoc cross-references bumped to /v2 in transports/cli/cli.go, transports/otellog/otellog.go, doc.go, examples/pretty-modes/main.go. - migrating-to-v2.md: reframe lede as "two breaking changes" (the import-path bump is its own breaking change); add paragraph on the core no longer mutating caller-owned input; rewrite Step 1 shell snippet so the trailing-backslash + comment paste-trap is gone; add callout for the new testing.LogLine.Prefix field. - configuration.md / llms.txt: reframe the Prefix inline comment so it no longer claims the core prepends. Style: - Em-dash sweep across llms.txt and llms-full.txt (~50 occurrences) per the project's no-em-dashes-anywhere rule. - llms-full.txt: typo "rolled-our-own" -> "roll-our-own"; reframe the "Testing Transport (lltest)" and "Capture entries with lltest" headings since lltest is an alias convention, not the package name. transports/central left undocumented intentionally: its package GoDoc is already correct for v2 and the module is not in monorel.toml or the v2.0.0 release. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
loglayer-gov2. The core no longer mutatesMessages[0]to fold theWithPrefixvalue into the message text. The prefix flows throughTransportParams.Prefixand each transport decides how to render it.This is a single-mechanism breaking change with a fan-out across the entire monorepo: every module's import path bumps to
/v2.What changed
Core (
go.loglayer.dev/v2):applyPrefixfromloglayer.goand the three call sites indispatch.go,builder.go,log.go.transport.JoinPrefixAndMessages(prefix, messages) []anyhelper. Fast-path early returns when the prefix is empty / messages is empty /messages[0]isn't a string. Per-call cost on a no-prefix logger is one string compare.Built-in transports (16 of 19, preserving v1 user-visible output):
console,pretty,structured,testing,zerolog,zap,slog,logrus,phuslu,charmlog,http,sentry,otellog,gcplogging: each calls the helper at the top ofSendToLogger.centralanddatadoginherit via embedded*http.Transport.lumberjackinherits via delegation tostructured.testing.LogLinegained aPrefix stringfield for fixture assertions.blankintentionally left as raw passthrough (advanced users see v2 params unmangled).Smart rendering opt-in (1 of 19):
clireadsparams.Prefixdirectly and renders it in dim grey, separate from the level color. The level prefix and message body keep the level color (yellow / red); the user prefix gets a third visual layer.Module path bumps (every published package):
go.loglayer.dev→go.loglayer.dev/v2.transports/<name>/v2.plugins/<name>/v2.integrations/<name>/v2.plugins/datadogtrace/livetestalso bumped.replace/requiredirectives updated.Docs:
docs/src/migrating-to-v2.mdwalking the upgrade.whats-new.mdv2.0.0 entry at the top of May 02, 2026.creating-transports.mdandcreating-plugins.mdupdated to drop the legacy auto-prepend caveats and document the v2 contract.cheatsheet.md,llms.txt,llms-full.txtupdated.Changeset:
:majorchangeset bumping every monorel-managed module to v2.Test plan
go test -count=1 ./...(main module) passes.bash scripts/foreach-module.sh testpasses across all 33 modules.bun run docs:buildclean.log.WithPrefix("[auth]").Warn("retrying")through the cli transport produces yellowwarning:+ dim grey[auth]+ yellowretrying.msg: "[auth] retrying"(legacy behavior preserved via the helper).Migration cost on consumers
One-time import-path bump. Most users:
go get go.loglayer.dev/v2 \ go.loglayer.dev/transports/<your-transports>/v2 \ go.loglayer.dev/plugins/<your-plugins>/v2Custom transport authors who consumed
Messages[0]and relied on the prefix being baked in: either calltransport.JoinPrefixAndMessagesto keep v1 behavior, or readparams.Prefixdirectly and render smartly. Documented in Migrating to v2.🤖 Generated with Claude Code