Skip to content

Commit c690b5e

Browse files
feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility (#2091)
# What does this PR do? This PR adds a configuration to the Trace Exporter to export spans with purely OpenTelemetry semantics. When enabled, this configuration updates the DD Span => OTLP Span mapping to exclude the following span tags from the output: - `service.name` - `operation.name` - `resource.name` - `span.type` - `error.msg` - `error.message` - `span.kind` This change also fixes the DD Span error message lookup to account for both the `error.msg` and `error.message` tag keys, since they are used interchangeably across Datadog SDKs. # Motivation We want to enable OpenTelemetry SDK users to migrate to the Datadog SDK in their language ecosystem, so this change allows them to export OTLP spans from the Datadog SDK without the shape of their data changing. This is most notable when using the OpenTelemetry Tracing API and OpenTelemetry Instrumentation Libraries to generate traces -- with this new semantic mode, the OTLP span should reach the backend without its semantics changing. # Additional Notes This may result in a breaking change since it affects the public function `libdd_trace_utils::otlp_encoder::map_traces_to_otlp`. # How to test the change? This is tested through unit tests in `libdd-trace-utils/src/otlp_encoder/mapper.rs` that validate the Datadog-specific attributes are excluded from the OTLP span. Co-authored-by: zach.montoya <zach.montoya@datadoghq.com>
1 parent bf2ae0f commit c690b5e

4 files changed

Lines changed: 276 additions & 37 deletions

File tree

libdd-data-pipeline/src/otlp/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ pub struct OtlpTraceConfig {
3535
/// Protocol (for future use; currently only HttpJson is supported).
3636
#[allow(dead_code)]
3737
pub(crate) protocol: OtlpProtocol,
38+
/// When `true`, does not add DD-specific per-span attributes to the OTLP payload.
39+
// These attributes are: (`service.name`, `operation.name`, `resource.name`,
40+
// `span.type`, `error.msg`, `error.message`, `span.kind`)
41+
pub otel_trace_semantics_enabled: bool,
3842
}
3943

4044
/// Parsed OTLP trace-metrics exporter configuration.

libdd-data-pipeline/src/trace_exporter/builder.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,13 @@ impl TraceExporterBuilder {
330330
self
331331
}
332332

333-
/// Strip Datadog-specific `dd.*`/`_dd.*` data-point attributes from the exported histogram.
333+
/// Enables OTel trace semantics, which does not add DD-specific per-span attributes
334+
/// (`service.name`, `operation.name`, `resource.name`, `span.type`, `error.msg`,
335+
/// `error.message`, `span.kind`) to the OTLP payload.
336+
/// Also strips Datadog-specific `dd.*`/`_dd.*` data-point attributes from the exported
337+
/// histogram. This is useful when exporting to a native OTel backend that does not expect
338+
/// Datadog semantics. The host language tracer is expected to observe this behavior by
339+
/// setting the `DD_TRACE_OTEL_SEMANTICS_ENABLED` environment variable to `true`.
334340
pub fn enable_otel_trace_semantics(&mut self) -> &mut Self {
335341
self.otel_trace_semantics_enabled = true;
336342
self
@@ -488,6 +494,7 @@ impl TraceExporterBuilder {
488494
headers: build_otlp_header_map(self.otlp_headers),
489495
timeout: otlp_timeout,
490496
protocol: OtlpProtocol::HttpJson,
497+
otel_trace_semantics_enabled: self.otel_trace_semantics_enabled,
491498
});
492499

493500
let otlp_metrics_config = self.otlp_metrics_endpoint.map(|url| OtlpMetricsConfig {

libdd-data-pipeline/src/trace_exporter/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,8 @@ impl<C: HttpClientCapability + SleepCapability + MaybeSend + Sync + 'static> Tra
566566
r.client_computed_stats = self.otlp_stats_enabled;
567567
r
568568
};
569-
let request = map_traces_to_otlp(traces, &resource_info);
569+
let request =
570+
map_traces_to_otlp(traces, &resource_info, config.otel_trace_semantics_enabled);
570571
let json_body = serde_json::to_vec(&request).map_err(|e| {
571572
error!("OTLP JSON serialization error: {e}");
572573
TraceExporterError::Internal(InternalErrorKind::InvalidWorkerState(e.to_string()))

0 commit comments

Comments
 (0)