Skip to content

feat: transport v3 sweep (sub-modules onto core v3, structured sanitize) - #98

Merged
theogravity merged 14 commits into
mainfrom
transport-v3-sweep
Aug 23, 2026
Merged

theogravity merged 14 commits into
mainfrom
transport-v3-sweep

Conversation

@theogravity

@theogravity theogravity commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Summary

PR B of the staged v3 release: the transport v3 sweep. Now that go.loglayer.dev/v3.0.0 is published (PR #96 + #97), every sub-module moves onto the v3 core, and the approved structured-transport v3 behavior ships.

What's in this PR

  • All sub-modules require go.loglayer.dev/v3: transports, plugins, integrations, examples. Core sub-package imports (/v2/transport, /v2/utils/*) → /v3.
  • Every released module takes its next major path bump (29): all of them re-export core v3 types (or sibling http/v3 types) in their public API, so upgrading from the v2 core is breaking. Per Go convention the path moves to the next major:
    • /v2 → /v3 (24): the 18 transports + plugins/oteltrace, plugins/datadogtrace, integrations/loghttp, integrations/sloghandler, plugins/fmtlog, plugins/plugintest, plugins/redact, plugins/sampling, transports/datadog
    • unversioned → /v2 (2): transports/betterstack, transports/newrelic
    • transports/central stays unregistered (not in monorel, no releases)
  • Sibling requires follow the bumps: lumberjack → structured/v3, plugins → plugintest/testing/v3, the http-built wrappers → http/v3, all with local replace directives for dev.
  • Structured transport v3 behavior (approved design, previously unshipped): top-level ANSI/bidi/CRLF sanitization (message via multiline-aware AssembleMessage, Data/metadata keys + string values) and msg-key omission when the message is empty. TDD: 4 new tests, red-green verified; plus multiline-preservation regression.
  • PR-A scaffolding removed: CORE_ONLY gate gone from CI + scripts/foreach-module.sh (full matrix restored, plugins/datadogtrace/livetest re-listed), interim-state docs callouts removed, README swept to v3, v2-shape metadata prose flipped to the v3 default ("metadata" nesting).
  • Changesets: one changeset naming all 29 majors (single file; the empty patch changeset was removed).

Verification

  • bash scripts/foreach-module.sh test — all 37 modules ok, exit 0 (CI parity)
  • bash scripts/foreach-module.sh build / staticcheck — clean; vuln — only policy-accepted stdlib vulns (pre-existing)
  • gofmt, go vet, cd docs && bun run docs:build — clean
  • Three full reviews (code + docs, senior-Go-dev framing, plus an independent /code-review): no Critical; all Important findings fixed (multiline collapse, newrelic metadata key, pretty depth regression, datadog path, module READMEs for the 7 bumped modules, llms/doc sweep, changeset wording)

Changelog

The changeset will publish all 29 module-path majors (transports, plugins, integrations). See Migrating to v3.

Theo Gravity added 14 commits August 22, 2026 12:45
The oteltrace, datadogtrace, loghttp, and sloghandler modules re-export
core v3 types in their public API (New() loglayer.Plugin,
OnBeforeDataOut(loglayer.Data), New(log *loglayer.LogLayer)), so they
own-major to <path>/v3 alongside the transports. Updates: module paths,
source+example imports, docs import paths, go.mod requires/replaces,
changesets (moved from patch to major), migration guide path list.

Also from review:
- structured: escape raw U+202E in test literals (staticcheck ST1018)
- structured: pin full flattened output line (sanitize-vs-flatten)
- datadog-shipping example: import datadog/v3 (was v2, nonexistent)
- docs: fix stale zerolog/zap openers, metadata.md empty-msg claim,
  em dashes in touched files
- structured: preserve Multiline line boundaries via AssembleMessage
  (sanitize.Message on the joined string collapsed authored newlines);
  add regression test
- newrelic: honor Schema.MetadataFieldName via MergeIntoMap (was
  flattening metadata to root unconditionally, dropping struct/scalar
  metadata under the v3 default); update test to nested shape
- pretty: nested metadata value gets one extra inline depth budget so
  MaxInlineDepth truncates deep nesting without collapsing the whole
  metadata bag (v2 root-merge UX preserved under nesting); unwrap the
  depth marker in expanded-mode writer
- datadog: revert docs + example to the real /v2 module path (I had
  wrongly changed them to /v3 earlier; datadog stays at path)
- docs: log-sanitization.md now reflects structured calling
  sanitize.Message; llms-full.txt swept to /v3 for oteltrace,
  datadogtrace, loghttp, sloghandler
Every sub-module re-exports core (or sibling http) v3 types in its public
API, so upgrading from the v2 core is a breaking change. Per Go module
convention, each takes its next major path bump:

- plugins/fmtlog, plugintest, redact, sampling, transports/datadog:
  /v2 -> /v3
- transports/betterstack, newrelic: (unversioned) -> /v2

Sweeps imports, go.mod requires/replaces (plugintest/v3 + http/v3
placeholders with local replaces), go.work, docs, llms, and changesets
(all 7 move to :major; the patch changeset is now empty and removed).

All 37 modules pass. Changeset now names 29 majors covering every
released module.
betterstack + newrelic badges/imports -> /v2, datadog -> /v3 (their next
majors); migrating guide now states every released module takes a major
path bump.
- Module READMEs (datadog, newrelic, betterstack): badges, install
  lines, and example imports to the new /v3 or /v2 module paths
- Docs pages that reference the old paths: cheatsheet, configuration,
  for-typescript-developers, sloghandler, groups, cli,
  multiple-transports, fmtlog, redact, sampling, testing-plugins,
  plugin-list partial
- llms.txt + llms-full.txt go-get/import lines swept to new paths
A WithFields entry whose key equals the resolved metadata nest key
(metadata by default) previously produced duplicate JSON keys in the
same object, silently corrupting output for parsers that keep one. The
data key is now skipped when metadata nests under the schema key; the
nested metadata wins, matching transport.MergeIntoMap. Regression test
added.

Also clarify the SendToLogger GoDoc: custom json.Marshaler values remain
the JSON encoder's domain (the documented sanitize boundary already
excluded nested values; now named explicitly).

From /code-review 98: newrelic FlattenMetadata struct behavior and the
json.Marshaler bypass were verified as intended/consistent with the
shared merge helper and the documented sanitize contract respectively.
- structured: compare the sanitized Data key (what's emitted) against the
  raw metadata nest key, closing the duplicate-key hole for hostile keys
  like "meta\x00data" that sanitize into "metadata"; hoist the per-key
  sanitize into a local (no double sanitize)
- transport.AssembleMessage: fast path for the dominant single-string
  shape (no parts slice, no join), mirroring JoinMessages
- newrelic mergeAttributes: iterate a key snapshot so the 255-attr
  truncation break stays deterministic against mid-loop mutation

Skipped: pretty depthMarker (altitude review: right depth - keeps
combineData the single owner of the metadata key, test-pinned, matches
the file's local-variant pattern); shared contract collision case
(reverted: the RunContract cohort is wrapper transports that
legitimately forward colliding fields to the underlying logger; the
dedup rule lives in the renderer/encoder cohort, where structured has
its own regression test).
Document the 29-module major path bumps and the structured transport's
new sanitize + omit-empty-msg behavior under an Aug 22 entry. PR A's
entry had noted structured stays on v2 pending the follow-up; this is
that follow-up.
The v3 section covered paths + metadata placement but not the
structured transport's new sanitize and omit-empty-msg behavior;
migrating users who assert on its JSON shape need to know. Adds a
Known incompatibilities bullet.
@theogravity
theogravity enabled auto-merge (squash) August 23, 2026 05:38
@theogravity
theogravity merged commit 87d4aa5 into main Aug 23, 2026
13 checks passed
@theogravity
theogravity deleted the transport-v3-sweep branch August 23, 2026 05:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant