Skip to content

Add suggested string representation of complex attributes for non-OTLP protocols#4848

Merged
reyang merged 7 commits intoopen-telemetry:mainfrom
trask:complex-attr-string-representation
Feb 2, 2026
Merged

Add suggested string representation of complex attributes for non-OTLP protocols#4848
reyang merged 7 commits intoopen-telemetry:mainfrom
trask:complex-attr-string-representation

Conversation

@trask
Copy link
Copy Markdown
Member

@trask trask commented Jan 20, 2026

I think the only concrete impact this has in the specification is for the Prometheus exporter. It could apply to the Zipkin exporter but that's been deprecated, so I think it's up to language implementations if they want to update their Zipkin exporter to emit complex attributes or not.

@trask trask changed the title Suggested string representation of complex attributes for non-OTLP protocols Add suggested string representation of complex attributes for non-OTLP protocols Jan 20, 2026
@trask trask marked this pull request as ready for review January 20, 2026 20:07
@trask trask requested review from a team as code owners January 20, 2026 20:07
Comment thread specification/common/README.md Outdated
Comment thread specification/common/README.md
Comment thread specification/common/README.md Outdated
@trask trask force-pushed the complex-attr-string-representation branch from 6d0acbe to b404fb8 Compare January 21, 2026 20:41
@trask trask force-pushed the complex-attr-string-representation branch from b404fb8 to debb47b Compare January 22, 2026 05:28
@tigrannajaryan
Copy link
Copy Markdown
Member

I quick checked Collector codebase and I think this matches what Collector does, which is good: https://github.com/open-telemetry/opentelemetry-collector/blob/77ffe4a370df7289fbc64c56b37eb3669fddd4ba/pdata/pcommon/value.go#L386

@open-telemetry/collector-maintainers it would be great if you can double check. I think it is nice to have Collector aligned with this too.

@trask
Copy link
Copy Markdown
Member Author

trask commented Jan 27, 2026

I quick checked Collector codebase and I think this matches what Collector does, which is good: https://github.com/open-telemetry/opentelemetry-collector/blob/77ffe4a370df7289fbc64c56b37eb3669fddd4ba/pdata/pcommon/value.go#L386

Thanks @tigrannajaryan!

The only difference I see there is the handling of NaN, Infinity, and -Infinity.

In this PR, I propose ProtoJSON format for those values:

Protobuf JSON JSON example Notes
float, double number 1.1, -10.0, 0, "NaN", "Infinity" JSON value will be a number or one of the special string values "NaN", "Infinity", and "-Infinity". Either numbers or strings are accepted. Empty strings are invalid. Exponent notation is also accepted.

While the Collector Value AsString produces these string values:

  • json: unsupported value: NaN
  • json: unsupported value: +Inf
  • json: unsupported value: -Inf

Copy link
Copy Markdown
Member

@mx-psi mx-psi left a comment

Choose a reason for hiding this comment

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

This looks good to me and as Tigran said I believe it matches the existing AsString method in the Collector's pdata

Comment thread specification/common/README.md
@trask
Copy link
Copy Markdown
Member Author

trask commented Jan 27, 2026

While the Collector Value AsString produces these string values:

  • json: unsupported value: NaN
  • json: unsupported value: +Inf
  • json: unsupported value: -Inf

A bit more research on the Collector:

  • The above string representations are produced for top-level NaN, +Inf, -Inf values (the "json: unsupported value: " is part of the string representation)
  • When Nan, +Inf, -Inf values are present inside of maps/lists, they cause the string representation of the whole map/list to be the empty string, due to behavior of the standard json library.

I opened open-telemetry/opentelemetry-collector#14487 to discuss if this edge case is worth handling in the Collector (this specification PR already uses SHOULD, so it's not mandatory, and I think there's a reasonable argument to using a standard Json library over supporting these edge cases).

Comment thread specification/common/README.md Outdated
@reyang reyang added this pull request to the merge queue Feb 2, 2026
Merged via the queue into open-telemetry:main with commit adbab30 Feb 2, 2026
7 of 8 checks passed
@carlosalberto carlosalberto mentioned this pull request Feb 11, 2026
github-merge-queue Bot pushed a commit that referenced this pull request Feb 13, 2026
### Context

- Deprecate Jaeger propagator and make propagator implementation
optional.

([#4827](#4827))
- Deprecate OT Trace propagator and make propagator implementation
optional.

([#4851](#4851))

### Metrics

- Add normative language to the Metrics API/SDK spec concurrency
requirements.

([#4868](#4868))

### Logs

- Add optional `Exception` parameter to Emit LogRecord.

([#4824](#4824))
- Add normative language to the Logging API/SDK spec concurrency
requirements.

([#4885](#4885))

### Resource

- Refine the handling of OTEL_RESOURCE_ATTRIBUTES.

([#4856](#4856))

### Common

- Add string representation guidance for complex attribute value types
(byte arrays,
  empty values, arrays, and maps) for non-OTLP protocols.

([#4848](#4848))

### Compatibility

- Stabilize Prometheus Counter to OTLP Sum transformation.

([#4862](#4862))
- Stabilize Prometheus Gauge to OTLP Gauge transformation.

([#4871](#4871))

### SDK Configuration

- Swap Tracer/Meter/LoggerConfig `disabled` for `enabled` to avoid
double negatives

([#4823](#4823))
- Declarative configuration: rename `ComponentProvider` to
`PluginComponentProvider`, `CreatePlugin` to `CreateComponent` in effort
to
  use consistent vocabulary

([#4806](#4806))
- Declarative configuration: Update instrumentation config behavior to
return
  empty object when not set

([#4817](#4817))
pull Bot pushed a commit to weiyilai/opentelemetry-collector that referenced this pull request Apr 21, 2026
…open-telemetry#15138)

## Summary

Update `float64AsString` to return `"NaN"`, `"Infinity"`, and
`"-Infinity"` instead of `"json: unsupported value: ..."` for special
float values.

Fixes open-telemetry#14487

## Problem

The current `Value.AsString()` for double values containing `NaN`,
`+Inf`, or `-Inf` returns strings like:
```
json: unsupported value: +Inf
json: unsupported value: NaN
```

The [OpenTelemetry specification's suggested string
representation](open-telemetry/opentelemetry-specification#4848)
for non-OTLP protocols specifies these should be `"NaN"`, `"Infinity"`,
and `"-Infinity"`.

## Fix

Updated `float64AsString` in `pdata/pcommon/value.go` to return
spec-compliant strings:
- `math.NaN()` → `"NaN"`
- `math.Inf(1)` → `"Infinity"`
- `math.Inf(-1)` → `"-Infinity"`

## Test Plan

- [x] Updated existing `"bad float64"` test case and added `NaN` and
`-Infinity` cases
- [x] Full `pdata` test suite passes with `-race`
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.

10 participants