Description
bridgeSpan.LogFields in bridge/opentracing/bridge.go translates every
OpenTracing Span.LogFields/Span.LogKV call into an OTel span event with a
hardcoded empty name:
func (s *bridgeSpan) LogFields(fields ...otlog.Field) {
s.otelSpan.AddEvent(
"",
trace.WithAttributes(otLogFieldsToOTelAttrs(fields)...),
)
}
https://github.com/open-telemetry/opentelemetry-go/blob/main/bridge/opentracing/bridge.go#L157-L162
The OpenTracing API has no explicit "event name" parameter on LogFields,
but by convention a field keyed "event" is meant to carry the event's
name/description (see the OpenTracing spec / opentracing-go/log
package docs). This bridge ignores that convention entirely and always
passes "" as the OTel event name, regardless of what fields are logged.
This becomes a real interoperability bug downstream: the OTLP spec's
Span.Event.name field is documented as "semantically required to be set
to non-empty string":
https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto#L220-L228
message Event {
fixed64 time_unix_nano = 1;
// The name of the event.
// This field is semantically required to be set to non-empty string.
string name = 2;
...
}
Backends that enforce this (e.g. AWS OpenSearch Ingestion Service /
OpenSearch Data Prepper's otel_trace_source) reject the entire OTLP
export request when any event in the batch has an empty name:
org.opensearch.dataprepper.model.trace.DefaultSpanEvent:
checkArgument(!builder.name.isEmpty(), "name cannot be an empty string");
https://github.com/opensearch-project/data-prepper/blob/main/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/trace/DefaultSpanEvent.java
Because Data Prepper's OTelTraceGrpcService rejects the whole gRPC
request on this validation error, a single OpenTracing LogFields call
anywhere in a batch causes the OTel collector to receive an HTTP 400 for
the entire export, marks it as a Permanent/non-retryable error, and drops
every span in that batch — not just the one with the empty-name event.
Real-world trigger
Observed via Thanos (thanos-io/thanos), which vendors Cortex's cache
instrumentation and calls the OpenTracing API directly:
// internal/cortex/chunk/cache/instrumented.go
sp := ot.SpanFromContext(ctx)
sp.LogFields(otlog.Int("keys requested", len(keys)))
...
sp.LogFields(otlog.Int("keys found", len(found)), otlog.Int("keys missing", len(keys)-len(found)))
Thanos wires this through go.opentelemetry.io/otel/bridge/opentracing
(pkg/tracing/migration/bridge.go), so every one of these LogFields calls
becomes an OTel span event with name: "", ultimately causing OTel
collectors exporting Thanos traces to an OSIS/Data Prepper endpoint to have
their entire batch rejected with HTTP 400 and silently dropped.
What I expected to happen
LogFields/LogKV should produce a non-empty OTel event name — e.g. use
the value of a field keyed "event" per OpenTracing convention, and fall
back to some constant (e.g. "log") when no such field is present, instead
of unconditionally passing "".
What happened instead
The event name is always "", which is spec-non-compliant per
opentelemetry-proto's own documentation of Event.name, and causes silent,
whole-batch trace data loss against any backend that validates the field
(e.g. AWS OSIS / OpenSearch Data Prepper).
Environment
go.opentelemetry.io/otel/bridge/opentracing v1.36.0
- Observed indirectly via
thanos-io/thanos (Cortex-derived cache
instrumentation) exporting to AWS OpenSearch Ingestion Service
(opensearch-project/data-prepper's otel_trace_source)
Additional context
Repro: ran an unmasked OSS Data Prepper instance (otel_trace_source ->
stdout sink) against captured OTLP export traffic and confirmed the
raw error:
Failed to parse request with error 'name cannot be an empty string'.
with every rejected span's events{} blocks having attributes (e.g.
"keys requested", "keys found") but no name field set at all.
Description
bridgeSpan.LogFieldsinbridge/opentracing/bridge.gotranslates everyOpenTracing
Span.LogFields/Span.LogKVcall into an OTel span event with ahardcoded empty name:
https://github.com/open-telemetry/opentelemetry-go/blob/main/bridge/opentracing/bridge.go#L157-L162
The OpenTracing API has no explicit "event name" parameter on
LogFields,but by convention a field keyed
"event"is meant to carry the event'sname/description (see the OpenTracing spec /
opentracing-go/logpackage docs). This bridge ignores that convention entirely and always
passes
""as the OTel event name, regardless of what fields are logged.This becomes a real interoperability bug downstream: the OTLP spec's
Span.Event.namefield is documented as "semantically required to be setto non-empty string":
https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto#L220-L228
Backends that enforce this (e.g. AWS OpenSearch Ingestion Service /
OpenSearch Data Prepper's
otel_trace_source) reject the entire OTLPexport request when any event in the batch has an empty name:
https://github.com/opensearch-project/data-prepper/blob/main/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/trace/DefaultSpanEvent.java
Because Data Prepper's
OTelTraceGrpcServicerejects the whole gRPCrequest on this validation error, a single OpenTracing
LogFieldscallanywhere in a batch causes the OTel collector to receive an HTTP 400 for
the entire export, marks it as a
Permanent/non-retryable error, and dropsevery span in that batch — not just the one with the empty-name event.
Real-world trigger
Observed via Thanos (
thanos-io/thanos), which vendors Cortex's cacheinstrumentation and calls the OpenTracing API directly:
Thanos wires this through
go.opentelemetry.io/otel/bridge/opentracing(
pkg/tracing/migration/bridge.go), so every one of theseLogFieldscallsbecomes an OTel span event with
name: "", ultimately causing OTelcollectors exporting Thanos traces to an OSIS/Data Prepper endpoint to have
their entire batch rejected with HTTP 400 and silently dropped.
What I expected to happen
LogFields/LogKVshould produce a non-empty OTel event name — e.g. usethe value of a field keyed
"event"per OpenTracing convention, and fallback to some constant (e.g.
"log") when no such field is present, insteadof unconditionally passing
"".What happened instead
The event name is always
"", which is spec-non-compliant peropentelemetry-proto's own documentation ofEvent.name, and causes silent,whole-batch trace data loss against any backend that validates the field
(e.g. AWS OSIS / OpenSearch Data Prepper).
Environment
go.opentelemetry.io/otel/bridge/opentracingv1.36.0thanos-io/thanos(Cortex-derived cacheinstrumentation) exporting to AWS OpenSearch Ingestion Service
(
opensearch-project/data-prepper'sotel_trace_source)Additional context
Repro: ran an unmasked OSS Data Prepper instance (
otel_trace_source->stdoutsink) against captured OTLP export traffic and confirmed theraw error:
with every rejected span's
events{}blocks having attributes (e.g."keys requested","keys found") but nonamefield set at all.