feat: transport v3 sweep (sub-modules onto core v3, structured sanitize) - #98
Merged
Merged
Conversation
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.
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
PR B of the staged v3 release: the transport v3 sweep. Now that
go.loglayer.dev/v3.0.0is 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
go.loglayer.dev/v3: transports, plugins, integrations, examples. Core sub-package imports (/v2/transport,/v2/utils/*) →/v3.http/v3types) 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/v2(2):transports/betterstack,transports/newrelictransports/centralstays unregistered (not in monorel, no releases)replacedirectives for dev.AssembleMessage, Data/metadata keys + string values) andmsg-key omission when the message is empty. TDD: 4 new tests, red-green verified; plus multiline-preservation regression.CORE_ONLYgate gone from CI +scripts/foreach-module.sh(full matrix restored,plugins/datadogtrace/livetestre-listed), interim-state docs callouts removed, README swept to v3, v2-shape metadata prose flipped to the v3 default ("metadata" nesting).Verification
bash scripts/foreach-module.sh test— all 37 modulesok, exit 0 (CI parity)bash scripts/foreach-module.sh build/staticcheck— clean;vuln— only policy-accepted stdlib vulns (pre-existing)cd docs && bun run docs:build— clean/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.