Skip to content

Commit 27aa92c

Browse files
feat(libdd-trace-utils): check for empty value in header datadog-client-computed-stats (#1900)
# What does this PR do? Treat an empty string as a falsy value for the `Datadog-Client-Computed-Stats` header. # Motivation We want to support agent computed stats in the Serverless Compatibility Layer. Currently when the `Datadog-Client-Computed-Stats` header is sent it always disables agent computed stats, even when the value of the header is an empty string. https://datadoghq.atlassian.net/browse/SVLS-8789 # Additional Notes - [Java Tracer sends an empty string](https://github.com/DataDog/dd-trace-java/blob/6e28457d70c41bf847c4af7b3ba4e2f6c1371070/dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/DDAgentApi.java#L110-L117) for `Datadog-Client-Computed-Stats` header where other tracers omit the header altogether - Go Agent [treats an empty string as a falsy value](https://github.com/DataDog/datadog-agent/blob/76aff83162011a15e5ee50295ac835f708e8ffa9/pkg/trace/api/api.go#L1049) - See DataDog/serverless-components#51 for adding agent computed stats in the Serverless Compatibility Layer. # How to test the change? Added a debug log in a test build: Before change with `DD_TRACE_STATS_COMPUTATION_ENABLED=false` ``` DEBUG datadog_trace_agent::trace_processor: Resolved tracer header tags: TracerHeaderTags { lang: "java", lang_version: "21.0.6", lang_interpreter: "OpenJDK 64-Bit Server VM", lang_vendor: "Microsoft", tracer_version: "1.61.1~e32291a78b", container_id: "", client_computed_top_level: true, client_computed_stats: true, dropped_p0_traces: 0, dropped_p0_spans: 0 } ``` After change with `DD_TRACE_STATS_COMPUTATION_ENABLED=false` ``` DEBUG datadog_trace_agent::trace_processor: Resolved tracer header tags: TracerHeaderTags { lang: "java", lang_version: "21.0.6", lang_interpreter: "OpenJDK 64-Bit Server VM", lang_vendor: "Microsoft", tracer_version: "1.61.1~e32291a78b", container_id: "", client_computed_top_level: true, client_computed_stats: false, dropped_p0_traces: 0, dropped_p0_spans: 0 } ``` Co-authored-by: duncan.harvey <duncan.harvey@datadoghq.com>
1 parent 530cd96 commit 27aa92c

1 file changed

Lines changed: 28 additions & 6 deletions

File tree

libdd-trace-utils/src/tracer_header_tags.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ pub struct TracerHeaderTags<'a> {
2727
pub lang_vendor: &'a str,
2828
pub tracer_version: &'a str,
2929
pub container_id: &'a str,
30-
// specifies that the client has marked top-level spans, when set. Any non-empty value will
31-
// mean 'yes'.
30+
// specifies that the client has marked top-level spans, when set. If the header is present
31+
// this value will resolve to 'true'
3232
pub client_computed_top_level: bool,
33-
// specifies whether the client has computed stats so that the agent doesn't have to. Any
34-
// non-empty value will mean 'yes'.
33+
// specifies whether the client has computed stats so that the agent doesn't have to. If the
34+
// header is present and is non-empty this value will resolve to 'true'
3535
pub client_computed_stats: bool,
3636
// number of trace chunks dropped in the tracer
3737
pub dropped_p0_traces: usize,
@@ -133,8 +133,8 @@ impl<'a> From<&'a HeaderMap<HeaderValue>> for TracerHeaderTags<'a> {
133133
if headers.get("datadog-client-computed-top-level").is_some() {
134134
tags.client_computed_top_level = true;
135135
}
136-
if headers.get("datadog-client-computed-stats").is_some() {
137-
tags.client_computed_stats = true;
136+
if let Some(v) = headers.get("datadog-client-computed-stats") {
137+
tags.client_computed_stats = !v.to_str().unwrap_or_default().is_empty();
138138
}
139139
if let Some(count) = headers.get("datadog-client-dropped-p0-traces") {
140140
tags.dropped_p0_traces = count
@@ -262,4 +262,26 @@ mod tests {
262262
assert_eq!(tags.dropped_p0_traces, 12);
263263
assert_eq!(tags.dropped_p0_spans, 0);
264264
}
265+
266+
#[test]
267+
fn test_header_map_to_tags_computed_stats_empty_string() {
268+
let val = "";
269+
let mut header_map = HeaderMap::new();
270+
header_map.insert("datadog-client-computed-stats", val.parse().unwrap());
271+
let tags: TracerHeaderTags = (&header_map).into();
272+
assert!(
273+
!tags.client_computed_stats,
274+
"expected client_computed_stats=false for datadog-client-computed-stats header value {val:?}"
275+
);
276+
}
277+
278+
#[test]
279+
fn test_header_map_to_tags_computed_stats_not_set() {
280+
let header_map = HeaderMap::new();
281+
let tags: TracerHeaderTags = (&header_map).into();
282+
assert!(
283+
!tags.client_computed_stats,
284+
"expected client_computed_stats=false when datadog-client-computed-stats header is not set"
285+
);
286+
}
265287
}

0 commit comments

Comments
 (0)