Skip to content

stdouttrace: use non-OTLP representation for span attributes - #9307

Open
pellared wants to merge 12 commits into
open-telemetry:mainfrom
pellared:fix/stdouttrace-nonfinite-9305
Open

pellared wants to merge 12 commits into
open-telemetry:mainfrom
pellared:fix/stdouttrace-nonfinite-9305

Conversation

@pellared

@pellared pellared commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

NaN and infinities in span attributes currently fail JSON encoding and leave affected spans unwritten. Share the attribute package's non-OTLP formatting for every export, following merged #9150.

Attribute values use native JSON types: strings, booleans, finite numbers, arrays, objects, and null for empty values. Bytes use Base64 strings; special floats become "NaN", "Infinity", and "-Infinity". JSON-looking strings stay strings, and user map entries named Type or Value remain ordinary data. Integer precision and signed zero are retained.

Span, event, and link attributes remain ordered arrays of single-attribute objects; resource and instrumentation scope attribute sets become JSON objects. Empty sets are {}, nil resources remain null, and populated scope attributes and scope/library metadata are retained.

Use exporter-local json.RawMessage wrappers so every span is encoded once. Timestamp removal updates owned span/event copies without copying events twice or mutating input spans. Shared attribute marshaling and other exporters are unaffected. Ordinary export errors retain their span indices, later spans are attempted, and observability success counts remain accurate. Focused race tests and make precommit pass.

Fixes #9305.

Eight-sample benchmarks below compare against main dfb660c5e using the same fixtures on both versions. Finite scalar attributes retain 26 allocations but use about 46% more bytes. The 1024-element float-array case uses one fewer allocation but about 145% more bytes; nested attributes drop from 40 to 27 allocations with an 11% byte increase. Timestamp removal uses 24 allocations instead of 22 and about 50% more bytes. The memory growth comes from canonical string formatting and json.RawMessage conversion. Shared-host timing variation, especially for timestamp removal, limits timing conclusions. Non-finite rejection paths are excluded because they do not provide a comparable successful-export baseline.

Benchmark commands: GOMAXPROCS=16 make benchmark/./exporters/stdout/stdouttrace ARGS='-bench=BenchmarkExporterAttributes -benchmem -count=8 -benchtime=200ms' and GOMAXPROCS=16 make benchmark/./exporters/stdout/stdouttrace ARGS='-bench=BenchmarkExporterWithoutTimestamps -benchmem -count=8 -benchtime=100ms'. The timestamp baseline used -benchtime=200ms; updated timestamp samples used 100ms.

goos: linux
goarch: amd64
pkg: go.opentelemetry.io/otel/exporters/stdout/stdouttrace
cpu: AMD EPYC 7571
                                  │ main-dfb660c5e.txt │             updated.txt             │
                                  │       sec/op       │    sec/op     vs base               │
ExporterAttributes/finite-16              15.58µ ±  3%   15.38µ ±  3%   -1.29% (p=0.041 n=8)
ExporterAttributes/finiteSlice-16         166.5µ ±  1%   155.4µ ±  3%   -6.63% (p=0.010 n=8)
ExporterAttributes/nested-16              21.00µ ±  1%   15.55µ ±  1%  -25.96% (p=0.000 n=8)
ExporterWithoutTimestamps-16              42.11µ ± 31%   19.32µ ± 12%  -54.13% (p=0.000 n=8)
geomean                                   38.92µ         29.11µ        -25.20%

                                  │ main-dfb660c5e.txt │             updated.txt              │
                                  │        B/op        │     B/op      vs base                │
ExporterAttributes/finite-16              1.322Ki ± 0%   1.926Ki ± 0%   +45.64% (p=0.000 n=8)
ExporterAttributes/finiteSlice-16         13.39Ki ± 0%   32.80Ki ± 0%  +144.98% (p=0.000 n=8)
ExporterAttributes/nested-16              1.870Ki ± 0%   2.082Ki ± 0%   +11.33% (p=0.000 n=8)
ExporterWithoutTimestamps-16              1.355Ki ± 0%   2.027Ki ± 0%   +49.57% (p=0.000 n=8)
geomean                                   2.588Ki        4.041Ki        +56.12%

                                  │ main-dfb660c5e.txt │             updated.txt             │
                                  │     allocs/op      │ allocs/op   vs base                 │
ExporterAttributes/finite-16                26.00 ± 0%   26.00 ± 0%        ~ (p=1.000 n=8) ¹
ExporterAttributes/finiteSlice-16           28.00 ± 0%   27.00 ± 0%   -3.57% (p=0.000 n=8)
ExporterAttributes/nested-16                40.00 ± 0%   27.00 ± 0%  -32.50% (p=0.000 n=8)
ExporterWithoutTimestamps-16                22.00 ± 0%   24.00 ± 0%   +9.09% (p=0.000 n=8)
geomean                                     28.29        25.97        -8.20%
¹ all samples are equal

@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Pull request dashboard status

Waiting on reviewers · refreshed 2026-11-09 19:55 UTC

Review the latest changes.

Also blocked by: Merge conflicts.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

@codecov

codecov Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.8%. Comparing base (dfb660c) to head (b21b278).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##            main   #9307     +/-   ##
=======================================
- Coverage   89.8%   89.8%   -0.1%     
=======================================
  Files        357     358      +1     
  Lines      23987   24009     +22     
=======================================
+ Hits       21562   21581     +19     
- Misses      2425    2428      +3     
Files with missing lines Coverage Δ
exporters/stdout/stdouttrace/json.go 100.0% <100.0%> (ø)
exporters/stdout/stdouttrace/trace.go 83.3% <100.0%> (+3.3%) ⬆️

... and 6 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@pellared pellared changed the title fix(stdouttrace): export non-finite attribute values stdouttrace: use non-OTLP representation for span attributes Nov 9, 2026
@pellared
pellared marked this pull request as ready for review November 9, 2026 13:52
@opentelemetry-pr-dashboard
opentelemetry-pr-dashboard Bot requested a balanced review from Copilot November 9, 2026 13:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain, although tests and benchmarks were not independently run during the review.

No open issues 🎉

What changed in this PR

Updates stdouttrace to use non-OTLP attribute formatting, following stdoutlog in #9150 and addressing #9305 so NaN and infinity values no longer prevent spans from being exported.

Changes:

  • Adds exporter-local JSON wrappers for span, event, link, resource, and scope attributes.
  • Preserves input spans during timestamp removal and retains per-span error handling and success accounting.
  • Adds representation and error-handling regression tests, benchmarks, package documentation, and changelog entries.

No review findings remain. Tests and benchmarks were not independently run during this review.

File Description
exporters/​stdout/​stdouttrace/​trace.go Uses JSON wrappers and removes timestamps from owned copies.
exporters/​stdout/​stdouttrace/​trace_test.go Updates expected output and non-finite success accounting.
exporters/​stdout/​stdouttrace/​nonfinite_test.go Adds attribute-format, input-preservation, and error regression tests plus benchmarks.
exporters/​stdout/​stdouttrace/​json.go Implements exporter-local non-OTLP attribute wrappers.
exporters/​stdout/​stdouttrace/​doc.go Documents the attribute representation.
CHANGELOG.md Records the format change and non-finite export fix.

Review effort: Balanced

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.

stdouttrace: export NaN and infinity attributes instead of dropping spans

2 participants