opentelemetry-python: Sampler Tracestate Fix, View Unit Matching and Byte Truncation

opentelemetry-python is the Python API and SDK for OpenTelemetry. Six commits landed in the last week, and the headline is a fix so samplers actually receive the parent tracestate. The rest are small spec conformance and robustness fixes.

Samplers now see the parent tracestate

Before this change, Tracer.start_span never passed the trace_state argument to the sampler. ParentBased also accepted it without forwarding it to its delegate. So the Sampler.should_sample signature declared a tracestate that no sampler ever got. The commit message says this left the consistent probability sampling design inert, because the composable parent threshold sampler reads its threshold from tracestate.

The fix covers several things:

  • Samplers get the parent tracestate, and root spans correctly get None.
  • The composite sampler keeps vendor tracestate entries instead of replacing the whole tracestate.
  • Stale thresholds are removed.
  • SamplingIntent.update_trace_state is now applied to root spans too.

The main code is in _parent_threshold.py and _sampler.py. The parent threshold sampler also validates the random value now, and falls back to the trace id when it is not valid.

If you wrote a custom sampler that reads trace_state, expect to see real values for the first time. Check that it handles both None and populated state.

View unit matching is now exact

This fix changes how a metrics View selects instruments by unit. The code used fnmatchcase. That treats square brackets as character classes. A UCUM annotated unit such as [degF] was read as a pattern, so a View for it never matched.

The Metrics SDK spec asks for an exact, case sensitive comparison with no wildcards for units. The SDK now compares the unit literally, with regression tests for bracketed units and wildcard characters. The change is in view.py.

One side effect: a View that relied on * in instrument_unit as a wildcard will stop matching. The spec never defined that, but check your config.

Byte array attributes follow attribute limits

The truncation change (#5855) makes bytes and bytearray attribute values obey max_value_length, as the Attribute Limits spec requires. Before, only str was truncated and bytes passed through untouched.

The helper _clean_attribute_value lost its max_string_value_length name and now takes max_value_length. It is a private function, but it lives in opentelemetry/attributes/init.py, so anything importing it directly should be checked. If you attach binary payloads to spans and set OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, those values can now be cut.

Zipkin timeout no longer crashes startup

Both Zipkin exporters parsed OTEL_EXPORTER_ZIPKIN_TIMEOUT with a bare int() in __init__. A value like 10s raised ValueError and took SDK startup down. The fix adds _timeout_from_env() to each exporter. Unset or empty values silently use the default. Non integer values log a warning and use the 10 second default. An explicit timeout argument still wins.

export OTEL_EXPORTER_ZIPKIN_TIMEOUT=10s   # warns, uses 10

This matches how the OTLP HTTP and gRPC exporters already behave.

Semconv and tooling

  • Semantic conventions rebuilt on 1.45.0. This touches many generated files under _incubating/attributes, such as aws_attributes.py and db_attributes.py. The PR carries the public API check approval label.
  • pylint bumped to v4 through a security tagged Renovate update. This only affects lint runs.

What to watch

  • Custom samplers: test them against real parent tracestate now.
  • Metrics Views: audit any unit selectors that used wildcard patterns.
  • Incubating semconv constants can change names or disappear between versions, so pin and review before upgrading.

← All updates