feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility#2091
feat(otlp)!: Export OTLP spans with attribute-level OTel compatibility#2091zacharycmontoya wants to merge 8 commits into
Conversation
|
📚 Documentation Check Results📦
|
Clippy Allow Annotation ReportComparing clippy allow annotations between branches:
Summary by Rule
Annotation Counts by File
Annotation Stats by Crate
About This ReportThis report tracks Clippy allow annotations for specific rules, showing how they've changed in this PR. Decreasing the number of these annotations generally improves code quality. |
🔒 Cargo Deny Results📦
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #2091 +/- ##
==========================================
+ Coverage 73.44% 73.57% +0.12%
==========================================
Files 465 475 +10
Lines 77949 79139 +1190
==========================================
+ Hits 57248 58223 +975
- Misses 20701 20916 +215
🚀 New features to boost your workflow:
|
…mode. This is implemented by adding a new bool field enable_otel_trace_compatibility to TraceExporterBuilder with a public setter, propagating it to the OtlpTraceConfig, and using it in the OTLP trace export immediately to omit Datadog-specific attributes like "operation.name"
… 'error.message' span tags on the output OTLP span when OTel Trace Compatibility is enabled
6f89fcc to
2d0d234
Compare
Artifact Size Benchmark Reportaarch64-alpine-linux-musl
aarch64-unknown-linux-gnu
libdatadog-x64-windows
libdatadog-x86-windows
x86_64-alpine-linux-musl
x86_64-unknown-linux-gnu
|
| pub fn map_traces_to_otlp<T: TraceData>( | ||
| trace_chunks: Vec<Vec<Span<T>>>, | ||
| resource_info: &OtlpResourceInfo, | ||
| enable_otel_trace_compatibility: bool, |
There was a problem hiding this comment.
For maintainers, is it preferred to make a breaking change by adding this bool to the public function? Or add a separate overload so as to not break back-compat? Or smuggle the bool value into the resource info (where it doesn't really belong)?
…ns in the OTel compat mode. It is already present as a first-class SpanKind field
link04
left a comment
There was a problem hiding this comment.
Nothing I found with the AI could be breaking based on the expectations.
| pub fn map_traces_to_otlp<T: TraceData>( | ||
| trace_chunks: Vec<Vec<Span<T>>>, | ||
| resource_info: &OtlpResourceInfo, | ||
| otel_trace_semantics_enabled: bool, |
There was a problem hiding this comment.
Very nitpick, but maybe this could be a proper enum, like TraceSemantics { Datadog, Otel }, to avoid boolean blindness. Though unimportant and a matter of taste, so feel free to ignore.
| } else { | ||
| 0 | ||
| }; | ||
| let total = (if has_per_span_service && !otel_trace_semantics_enabled { |
There was a problem hiding this comment.
You can use boolean to numeric conversion to avoid the if chains here, something like
let total = (has_per_span_service && !otel_trace_semantics_enable) as usize
+ ...There was a problem hiding this comment.
How about...
let promoted = if otel_trace_semantics_enabled {
0
} else {
has_per_span_service as usize
+ has_operation_name as usize
+ has_span_type as usize
+ has_resource_name as usize
};
let total = promoted
+ (span.meta.len() - excluded_compat_tags)
+ span.metrics.len()
+ span.meta_struct.len();| /// This is useful when exporting to a native OTel backend that does not expect Datadog | ||
| /// semantics. The host language tracer is expected to observe this behavior by setting the | ||
| /// `DD_TRACE_OTEL_SEMANTICS_ENABLED` environment variable to `true`. | ||
| pub fn enable_otel_trace_semantics(&mut self) -> &mut Self { |
There was a problem hiding this comment.
Do you need to add a corresponding function to the FFI API?
| /// Protocol (for future use; currently only HttpJson is supported). | ||
| #[allow(dead_code)] | ||
| pub(crate) protocol: OtlpProtocol, | ||
| /// When `true`, does not add DD-specific per-span attributes (`service.name`, |
There was a problem hiding this comment.
Aren't you also stripping error.msg, error.message, and span.kind?
| } | ||
|
|
||
| /// Enables OTel trace semantics, which does not add DD-specific per-span attributes | ||
| /// (`service.name`, `operation.name`, `resource.name`, `span.type`) to the OTLP payload. |
| // DD tracers use either "error.msg" or "error.message". | ||
| // A span should only carry one of these, so the order of preference is arbitrary. |
There was a problem hiding this comment.
nit and ignore if I'm wrong....
| // DD tracers use either "error.msg" or "error.message". | |
| // A span should only carry one of these, so the order of preference is arbitrary. | |
| // A span carries at most one of these; error.message is used by all SDKs except .NET, which uses error.msg |
| } else { | ||
| 0 | ||
| }; | ||
| let total = (if has_per_span_service && !otel_trace_semantics_enabled { |
There was a problem hiding this comment.
How about...
let promoted = if otel_trace_semantics_enabled {
0
} else {
has_per_span_service as usize
+ has_operation_name as usize
+ has_span_type as usize
+ has_resource_name as usize
};
let total = promoted
+ (span.meta.len() - excluded_compat_tags)
+ span.metrics.len()
+ span.meta_struct.len();
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.nameoperation.nameresource.namespan.typeerror.msgerror.messagespan.kindThis change also fixes the DD Span error message lookup to account for both the
error.msganderror.messagetag 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.rsthat validate the Datadog-specific attributes are excluded from the OTLP span.