From 9ec69fa4a0dd1ad8f0652a70420e5bb9c226e9a2 Mon Sep 17 00:00:00 2001 From: Munir Date: Mon, 30 Mar 2026 14:31:29 -0400 Subject: [PATCH 1/7] chore(telemetry): add session id support --- libdd-telemetry-ffi/src/builder/expanded.rs | 181 ++++++++++++++++++++ libdd-telemetry-ffi/src/builder/macros.rs | 5 +- libdd-telemetry-ffi/src/lib.rs | 31 ++++ libdd-telemetry/src/config.rs | 13 ++ libdd-telemetry/src/worker/http_client.rs | 30 +++- libdd-telemetry/src/worker/mod.rs | 117 ++++++++++++- 6 files changed, 373 insertions(+), 4 deletions(-) diff --git a/libdd-telemetry-ffi/src/builder/expanded.rs b/libdd-telemetry-ffi/src/builder/expanded.rs index 74daf6e8c0..7a88f5244a 100644 --- a/libdd-telemetry-ffi/src/builder/expanded.rs +++ b/libdd-telemetry-ffi/src/builder/expanded.rs @@ -245,6 +245,70 @@ mod macros { }; ffi::MaybeError::None } + #[no_mangle] + pub unsafe extern "C" fn ddog_telemetry_builder_with_str_session_id( + telemetry_builder: &mut TelemetryWorkerBuilder, + param: ffi::CharSlice, + ) -> ffi::MaybeError { + telemetry_builder.config.session_id = match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ + let res = std::fmt::format(format_args!("{e:?}")); + res + }), + )); + } + }; + ffi::MaybeError::None + } + #[no_mangle] + pub unsafe extern "C" fn ddog_telemetry_builder_with_str_root_session_id( + telemetry_builder: &mut TelemetryWorkerBuilder, + param: ffi::CharSlice, + ) -> ffi::MaybeError { + telemetry_builder.config.root_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ + let res = std::fmt::format(format_args!("{e:?}")); + res + }), + )); + } + }; + ffi::MaybeError::None + } + #[no_mangle] + pub unsafe extern "C" fn ddog_telemetry_builder_with_str_parent_session_id( + telemetry_builder: &mut TelemetryWorkerBuilder, + param: ffi::CharSlice, + ) -> ffi::MaybeError { + telemetry_builder.config.parent_session_id = + match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ + let res = std::fmt::format(format_args!("{e:?}")); + res + }), + )); + } + }; + ffi::MaybeError::None + } #[repr(C)] #[allow(dead_code)] pub enum TelemetryWorkerBuilderStrProperty { @@ -259,6 +323,9 @@ mod macros { HostKernelRelease, HostKernelVersion, RuntimeId, + SessionId, + RootSessionId, + ParentSessionId, } #[no_mangle] /** @@ -288,6 +355,12 @@ mod macros { * runtime_id + * session_id + + * root_session_id + + * parent_session_id + */ pub unsafe extern "C" fn ddog_telemetry_builder_with_property_str( telemetry_builder: &mut TelemetryWorkerBuilder, @@ -481,6 +554,57 @@ mod macros { } }; } + SessionId => { + telemetry_builder.config.session_id = + match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ + let res = std::fmt::format(format_args!("{e:?}")); + res + }), + )); + } + }; + } + RootSessionId => { + telemetry_builder.config.root_session_id = + match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ + let res = std::fmt::format(format_args!("{e:?}")); + res + }), + )); + } + }; + } + ParentSessionId => { + telemetry_builder.config.parent_session_id = + match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ + let res = std::fmt::format(format_args!("{e:?}")); + res + }), + )); + } + }; + } } ffi::MaybeError::None } @@ -512,6 +636,12 @@ mod macros { * runtime_id + * session_id + + * root_session_id + + * parent_session_id + */ pub unsafe extern "C" fn ddog_telemetry_builder_with_str_named_property( telemetry_builder: &mut TelemetryWorkerBuilder, @@ -715,6 +845,57 @@ mod macros { } }; } + "session_id" => { + telemetry_builder.config.session_id = + match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ + let res = std::fmt::format(format_args!("{e:?}")); + res + }), + )); + } + }; + } + "root_session_id" => { + telemetry_builder.config.root_session_id = + match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ + let res = std::fmt::format(format_args!("{e:?}")); + res + }), + )); + } + }; + } + "parent_session_id" => { + telemetry_builder.config.parent_session_id = + match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ + let res = std::fmt::format(format_args!("{e:?}")); + res + }), + )); + } + }; + } _ => return ffi::MaybeError::None, } ffi::MaybeError::None diff --git a/libdd-telemetry-ffi/src/builder/macros.rs b/libdd-telemetry-ffi/src/builder/macros.rs index 4c9377b44d..150b23fcb8 100644 --- a/libdd-telemetry-ffi/src/builder/macros.rs +++ b/libdd-telemetry-ffi/src/builder/macros.rs @@ -36,7 +36,10 @@ crate::c_setters!( host.kernel_release, host.kernel_version, - runtime_id + runtime_id, + session_id, + root_session_id, + parent_session_id, } ); diff --git a/libdd-telemetry-ffi/src/lib.rs b/libdd-telemetry-ffi/src/lib.rs index fde98bedaf..c402197ef6 100644 --- a/libdd-telemetry-ffi/src/lib.rs +++ b/libdd-telemetry-ffi/src/lib.rs @@ -200,6 +200,37 @@ mod tests { ); assert_eq!(builder.runtime_id.as_deref(), Some("abcd")); + assert_eq!( + ddog_telemetry_builder_with_property_str( + &mut builder, + TelemetryWorkerBuilderStrProperty::SessionId, + ffi::CharSlice::from("sess-1") + ), + MaybeError::None, + ); + assert_eq!(builder.config.session_id.as_deref(), Some("sess-1")); + assert_eq!( + ddog_telemetry_builder_with_property_str( + &mut builder, + TelemetryWorkerBuilderStrProperty::RootSessionId, + ffi::CharSlice::from("root-9") + ), + MaybeError::None, + ); + assert_eq!(builder.config.root_session_id.as_deref(), Some("root-9")); + assert_eq!( + ddog_telemetry_builder_with_property_str( + &mut builder, + TelemetryWorkerBuilderStrProperty::ParentSessionId, + ffi::CharSlice::from("parent-2") + ), + MaybeError::None, + ); + assert_eq!( + builder.config.parent_session_id.as_deref(), + Some("parent-2") + ); + assert_eq!( ddog_telemetry_builder_with_property_str( &mut builder, diff --git a/libdd-telemetry/src/config.rs b/libdd-telemetry/src/config.rs index 07dd8dfb69..f0a556f7f5 100644 --- a/libdd-telemetry/src/config.rs +++ b/libdd-telemetry/src/config.rs @@ -33,6 +33,13 @@ pub struct Config { pub restartable: bool, pub debug_enabled: bool, + + #[serde(default)] + pub session_id: Option, + #[serde(default)] + pub root_session_id: Option, + #[serde(default)] + pub parent_session_id: Option, } fn endpoint_with_telemetry_path( @@ -166,6 +173,9 @@ impl Default for Config { direct_submission_enabled: false, restartable: false, debug_enabled: false, + session_id: None, + root_session_id: None, + parent_session_id: None, } } } @@ -249,6 +259,9 @@ impl Config { direct_submission_enabled: settings.direct_submission_enabled, restartable: false, debug_enabled: false, + session_id: None, + root_session_id: None, + parent_session_id: None, }; if let Ok(url) = parse_uri(&trace_agent_url) { let _res = this.set_endpoint(Endpoint { diff --git a/libdd-telemetry/src/worker/http_client.rs b/libdd-telemetry/src/worker/http_client.rs index 5f00744b12..b7d7312385 100644 --- a/libdd-telemetry/src/worker/http_client.rs +++ b/libdd-telemetry/src/worker/http_client.rs @@ -22,8 +22,36 @@ pub mod header { pub const LIBRARY_LANGUAGE: HeaderName = HeaderName::from_static("dd-client-library-language"); pub const LIBRARY_VERSION: HeaderName = HeaderName::from_static("dd-client-library-version"); - /// Header key for whether to enable debug mode of telemetry. pub const DEBUG_ENABLED: HeaderName = HeaderName::from_static("dd-telemetry-debug-enabled"); + + pub const DD_SESSION_ID: HeaderName = HeaderName::from_static("dd-session-id"); + pub const DD_ROOT_SESSION_ID: HeaderName = HeaderName::from_static("dd-root-session-id"); + pub const DD_PARENT_SESSION_ID: HeaderName = HeaderName::from_static("dd-parent-session-id"); +} + +pub(crate) fn add_instrumentation_session_headers( + mut builder: HttpRequestBuilder, + session_id: Option<&str>, + root_session_id: Option<&str>, + parent_session_id: Option<&str>, +) -> HttpRequestBuilder { + let Some(s) = session_id.filter(|id| !id.is_empty()) else { + return builder; + }; + builder = builder.header(header::DD_SESSION_ID, s); + if let Some(r) = root_session_id + .filter(|r| !r.is_empty()) + .filter(|r| *r != s) + { + builder = builder.header(header::DD_ROOT_SESSION_ID, r); + } + if let Some(p) = parent_session_id + .filter(|p| !p.is_empty()) + .filter(|p| *p != s) + { + builder = builder.header(header::DD_PARENT_SESSION_ID, p); + } + builder } pub type ResponseFuture = diff --git a/libdd-telemetry/src/worker/mod.rs b/libdd-telemetry/src/worker/mod.rs index 3bfa1bcccb..12fb904de7 100644 --- a/libdd-telemetry/src/worker/mod.rs +++ b/libdd-telemetry/src/worker/mod.rs @@ -758,13 +758,18 @@ impl TelemetryWorker { ) .header( http_client::header::LIBRARY_LANGUAGE, - // Note: passing by ref here just causes the clone to happen underneath tel.application.language_name.clone(), ) .header( http_client::header::LIBRARY_VERSION, tel.application.tracer_version.clone(), ); + let req = http_client::add_instrumentation_session_headers( + req, + self.config.session_id.as_deref(), + self.config.root_session_id.as_deref(), + self.config.parent_session_id.as_deref(), + ); let body = http_common::Body::from(serialize::serialize(&tel)?); Ok(req.body(body)?) @@ -1190,7 +1195,13 @@ impl TelemetryWorkerBuilder { #[cfg(test)] mod tests { - use crate::worker::TelemetryWorkerHandle; + use crate::data::Payload; + use crate::worker::http_client::header::{ + DD_PARENT_SESSION_ID, DD_ROOT_SESSION_ID, DD_SESSION_ID, + }; + use crate::worker::{TelemetryWorker, TelemetryWorkerBuilder, TelemetryWorkerHandle}; + use libdd_common::{http_common, Endpoint}; + use tokio::runtime::Runtime; fn is_send(_: T) {} fn is_sync(_: T) {} @@ -1202,4 +1213,106 @@ mod tests { #[allow(clippy::redundant_closure)] let _ = |h: TelemetryWorkerHandle| is_sync(h); } + + fn test_worker( + session_id: Option, + root_session_id: Option, + parent_session_id: Option, + ) -> TelemetryWorker { + let mut b = TelemetryWorkerBuilder::new( + "h".into(), + "svc".into(), + "lang".into(), + "1".into(), + "tv".into(), + ); + b.config + .set_endpoint(Endpoint::from_slice("http://127.0.0.1:1")) + .unwrap(); + b.runtime_id = Some("rid".into()); + b.config.session_id = session_id; + b.config.root_session_id = root_session_id; + b.config.parent_session_id = parent_session_id; + let rt = Runtime::new().unwrap(); + b.build_worker(rt.handle().clone()).1 + } + + #[test] + fn telemetry_http_includes_dd_session_id() { + let req = test_worker(Some("sess".into()), None, None) + .build_request(&Payload::AppHeartbeat(())) + .unwrap(); + assert_eq!( + req.headers().get(DD_SESSION_ID).unwrap().to_str().unwrap(), + "sess" + ); + assert!(req.headers().get(DD_ROOT_SESSION_ID).is_none()); + assert!(req.headers().get(DD_PARENT_SESSION_ID).is_none()); + } + + #[test] + fn telemetry_http_omits_parent_when_duplicate_of_session() { + let req = test_worker(Some("sess".into()), None, Some("sess".into())) + .build_request(&Payload::AppHeartbeat(())) + .unwrap(); + assert_eq!( + req.headers().get(DD_SESSION_ID).unwrap().to_str().unwrap(), + "sess" + ); + assert!(req.headers().get(DD_PARENT_SESSION_ID).is_none()); + } + + #[test] + fn telemetry_http_omits_session_family_without_valid_session_id() { + let assert_no_session_headers = |req: &http_common::HttpRequest| { + assert!(req.headers().get(DD_SESSION_ID).is_none()); + assert!(req.headers().get(DD_ROOT_SESSION_ID).is_none()); + assert!(req.headers().get(DD_PARENT_SESSION_ID).is_none()); + }; + + let req = test_worker(None, Some("root".into()), Some("parent".into())) + .build_request(&Payload::AppHeartbeat(())) + .unwrap(); + assert_no_session_headers(&req); + + let req = test_worker( + Some(String::new()), + Some("root".into()), + Some("parent".into()), + ) + .build_request(&Payload::AppHeartbeat(())) + .unwrap(); + assert_no_session_headers(&req); + } + + #[test] + fn telemetry_http_includes_dd_session_root_and_parent_session_ids() { + let req = test_worker( + Some("sess".into()), + Some("root".into()), + Some("parent".into()), + ) + .build_request(&Payload::AppHeartbeat(())) + .unwrap(); + assert_eq!( + req.headers().get(DD_SESSION_ID).unwrap().to_str().unwrap(), + "sess" + ); + assert_eq!( + req.headers() + .get(DD_ROOT_SESSION_ID) + .unwrap() + .to_str() + .unwrap(), + "root" + ); + assert_eq!( + req.headers() + .get(DD_PARENT_SESSION_ID) + .unwrap() + .to_str() + .unwrap(), + "parent" + ); + } } From 847e5fa3d782afc61804567a541b0fcc3dc7e6e1 Mon Sep 17 00:00:00 2001 From: Munir Abdinur Date: Wed, 1 Apr 2026 14:26:59 -0400 Subject: [PATCH 2/7] update test Co-authored-by: Munir Abdinur --- libdd-telemetry/src/worker/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libdd-telemetry/src/worker/mod.rs b/libdd-telemetry/src/worker/mod.rs index 12fb904de7..ed453eff63 100644 --- a/libdd-telemetry/src/worker/mod.rs +++ b/libdd-telemetry/src/worker/mod.rs @@ -1251,14 +1251,15 @@ mod tests { } #[test] - fn telemetry_http_omits_parent_when_duplicate_of_session() { - let req = test_worker(Some("sess".into()), None, Some("sess".into())) + fn telemetry_http_omits_parent_and_root_when_duplicate_of_session() { + let req = test_worker(Some("sess-id".into()), Some("sess-id".into()), Some("sess-id".into())) .build_request(&Payload::AppHeartbeat(())) .unwrap(); assert_eq!( req.headers().get(DD_SESSION_ID).unwrap().to_str().unwrap(), "sess" ); + assert!(req.headers().get(DD_ROOT_SESSION_ID).is_none()); assert!(req.headers().get(DD_PARENT_SESSION_ID).is_none()); } From d9580ec8b90db9fe8fea8e36594aa759e798d1f9 Mon Sep 17 00:00:00 2001 From: Munir Abdinur Date: Fri, 3 Apr 2026 15:27:17 -0400 Subject: [PATCH 3/7] fix test Co-authored-by: Munir Abdinur --- libdd-telemetry/src/worker/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdd-telemetry/src/worker/mod.rs b/libdd-telemetry/src/worker/mod.rs index ed453eff63..9cb5d0dc95 100644 --- a/libdd-telemetry/src/worker/mod.rs +++ b/libdd-telemetry/src/worker/mod.rs @@ -1257,7 +1257,7 @@ mod tests { .unwrap(); assert_eq!( req.headers().get(DD_SESSION_ID).unwrap().to_str().unwrap(), - "sess" + "sess-id" ); assert!(req.headers().get(DD_ROOT_SESSION_ID).is_none()); assert!(req.headers().get(DD_PARENT_SESSION_ID).is_none()); From 97c7629b043f494ca115b823448f738ac55fee59 Mon Sep 17 00:00:00 2001 From: Munir Date: Fri, 3 Apr 2026 15:46:55 -0400 Subject: [PATCH 4/7] reorder params --- libdd-telemetry-ffi/src/builder/expanded.rs | 26 ++++++++++----------- libdd-telemetry-ffi/src/builder/macros.rs | 2 +- libdd-telemetry/src/config.rs | 8 +++---- libdd-telemetry/src/worker/http_client.rs | 4 +++- libdd-telemetry/src/worker/mod.rs | 4 ++-- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/libdd-telemetry-ffi/src/builder/expanded.rs b/libdd-telemetry-ffi/src/builder/expanded.rs index 7a88f5244a..f226ac6b09 100644 --- a/libdd-telemetry-ffi/src/builder/expanded.rs +++ b/libdd-telemetry-ffi/src/builder/expanded.rs @@ -324,8 +324,8 @@ mod macros { HostKernelVersion, RuntimeId, SessionId, - RootSessionId, ParentSessionId, + RootSessionId, } #[no_mangle] /** @@ -357,10 +357,10 @@ mod macros { * session_id - * root_session_id - * parent_session_id + * root_session_id + */ pub unsafe extern "C" fn ddog_telemetry_builder_with_property_str( telemetry_builder: &mut TelemetryWorkerBuilder, @@ -571,8 +571,8 @@ mod macros { } }; } - RootSessionId => { - telemetry_builder.config.root_session_id = + ParentSessionId => { + telemetry_builder.config.parent_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) @@ -588,8 +588,8 @@ mod macros { } }; } - ParentSessionId => { - telemetry_builder.config.parent_session_id = + RootSessionId => { + telemetry_builder.config.root_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) @@ -638,10 +638,10 @@ mod macros { * session_id - * root_session_id - * parent_session_id + * root_session_id + */ pub unsafe extern "C" fn ddog_telemetry_builder_with_str_named_property( telemetry_builder: &mut TelemetryWorkerBuilder, @@ -862,8 +862,8 @@ mod macros { } }; } - "root_session_id" => { - telemetry_builder.config.root_session_id = + "parent_session_id" => { + telemetry_builder.config.parent_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) @@ -879,8 +879,8 @@ mod macros { } }; } - "parent_session_id" => { - telemetry_builder.config.parent_session_id = + "root_session_id" => { + telemetry_builder.config.root_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) diff --git a/libdd-telemetry-ffi/src/builder/macros.rs b/libdd-telemetry-ffi/src/builder/macros.rs index 150b23fcb8..58c2686eac 100644 --- a/libdd-telemetry-ffi/src/builder/macros.rs +++ b/libdd-telemetry-ffi/src/builder/macros.rs @@ -38,8 +38,8 @@ crate::c_setters!( runtime_id, session_id, - root_session_id, parent_session_id, + root_session_id } ); diff --git a/libdd-telemetry/src/config.rs b/libdd-telemetry/src/config.rs index f0a556f7f5..464b02a0ee 100644 --- a/libdd-telemetry/src/config.rs +++ b/libdd-telemetry/src/config.rs @@ -37,9 +37,9 @@ pub struct Config { #[serde(default)] pub session_id: Option, #[serde(default)] - pub root_session_id: Option, - #[serde(default)] pub parent_session_id: Option, + #[serde(default)] + pub root_session_id: Option, } fn endpoint_with_telemetry_path( @@ -174,8 +174,8 @@ impl Default for Config { restartable: false, debug_enabled: false, session_id: None, - root_session_id: None, parent_session_id: None, + root_session_id: None, } } } @@ -260,8 +260,8 @@ impl Config { restartable: false, debug_enabled: false, session_id: None, - root_session_id: None, parent_session_id: None, + root_session_id: None, }; if let Ok(url) = parse_uri(&trace_agent_url) { let _res = this.set_endpoint(Endpoint { diff --git a/libdd-telemetry/src/worker/http_client.rs b/libdd-telemetry/src/worker/http_client.rs index b7d7312385..4e86f690e9 100644 --- a/libdd-telemetry/src/worker/http_client.rs +++ b/libdd-telemetry/src/worker/http_client.rs @@ -29,11 +29,13 @@ pub mod header { pub const DD_PARENT_SESSION_ID: HeaderName = HeaderName::from_static("dd-parent-session-id"); } +/// `session_id`, then `parent_session_id`, then `root_session_id` (must match call sites in +/// `build_request`). pub(crate) fn add_instrumentation_session_headers( mut builder: HttpRequestBuilder, session_id: Option<&str>, - root_session_id: Option<&str>, parent_session_id: Option<&str>, + root_session_id: Option<&str>, ) -> HttpRequestBuilder { let Some(s) = session_id.filter(|id| !id.is_empty()) else { return builder; diff --git a/libdd-telemetry/src/worker/mod.rs b/libdd-telemetry/src/worker/mod.rs index 9cb5d0dc95..03eb023415 100644 --- a/libdd-telemetry/src/worker/mod.rs +++ b/libdd-telemetry/src/worker/mod.rs @@ -767,8 +767,8 @@ impl TelemetryWorker { let req = http_client::add_instrumentation_session_headers( req, self.config.session_id.as_deref(), - self.config.root_session_id.as_deref(), self.config.parent_session_id.as_deref(), + self.config.root_session_id.as_deref(), ); let body = http_common::Body::from(serialize::serialize(&tel)?); @@ -1231,8 +1231,8 @@ mod tests { .unwrap(); b.runtime_id = Some("rid".into()); b.config.session_id = session_id; - b.config.root_session_id = root_session_id; b.config.parent_session_id = parent_session_id; + b.config.root_session_id = root_session_id; let rt = Runtime::new().unwrap(); b.build_worker(rt.handle().clone()).1 } From bbb98153228b2a1b0219e3c60d0d7f4b9568bf19 Mon Sep 17 00:00:00 2001 From: Munir Date: Fri, 3 Apr 2026 15:54:24 -0400 Subject: [PATCH 5/7] fmt --- libdd-telemetry/src/worker/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libdd-telemetry/src/worker/mod.rs b/libdd-telemetry/src/worker/mod.rs index 03eb023415..5180513b31 100644 --- a/libdd-telemetry/src/worker/mod.rs +++ b/libdd-telemetry/src/worker/mod.rs @@ -1252,9 +1252,13 @@ mod tests { #[test] fn telemetry_http_omits_parent_and_root_when_duplicate_of_session() { - let req = test_worker(Some("sess-id".into()), Some("sess-id".into()), Some("sess-id".into())) - .build_request(&Payload::AppHeartbeat(())) - .unwrap(); + let req = test_worker( + Some("sess-id".into()), + Some("sess-id".into()), + Some("sess-id".into()), + ) + .build_request(&Payload::AppHeartbeat(())) + .unwrap(); assert_eq!( req.headers().get(DD_SESSION_ID).unwrap().to_str().unwrap(), "sess-id" From c6b332a9e65c087859f2ea1f15cb86d024379963 Mon Sep 17 00:00:00 2001 From: Munir Date: Fri, 10 Apr 2026 15:23:05 -0400 Subject: [PATCH 6/7] regenerate expanded.rs --- libdd-telemetry-ffi/src/builder/expanded.rs | 315 ++++++-------------- 1 file changed, 85 insertions(+), 230 deletions(-) diff --git a/libdd-telemetry-ffi/src/builder/expanded.rs b/libdd-telemetry-ffi/src/builder/expanded.rs index f226ac6b09..c8958d44e5 100644 --- a/libdd-telemetry-ffi/src/builder/expanded.rs +++ b/libdd-telemetry-ffi/src/builder/expanded.rs @@ -1,7 +1,6 @@ // Copyright 2021-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 -pub use macros::*; #[allow(clippy::redundant_closure_call)] #[allow(clippy::missing_safety_doc)] #[allow(unused_parens)] @@ -23,10 +22,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -44,10 +40,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -66,10 +59,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -88,10 +78,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -110,10 +97,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -131,10 +115,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -152,10 +133,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -173,10 +151,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -194,10 +169,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -215,10 +187,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -236,10 +205,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -250,63 +216,53 @@ mod macros { telemetry_builder: &mut TelemetryWorkerBuilder, param: ffi::CharSlice, ) -> ffi::MaybeError { - telemetry_builder.config.session_id = match (|s: ffi::CharSlice| -> Result<_, String> { + telemetry_builder.session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; ffi::MaybeError::None } #[no_mangle] - pub unsafe extern "C" fn ddog_telemetry_builder_with_str_root_session_id( + pub unsafe extern "C" fn ddog_telemetry_builder_with_str_parent_session_id( telemetry_builder: &mut TelemetryWorkerBuilder, param: ffi::CharSlice, ) -> ffi::MaybeError { - telemetry_builder.config.root_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { + telemetry_builder.parent_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; ffi::MaybeError::None } #[no_mangle] - pub unsafe extern "C" fn ddog_telemetry_builder_with_str_parent_session_id( + pub unsafe extern "C" fn ddog_telemetry_builder_with_str_root_session_id( telemetry_builder: &mut TelemetryWorkerBuilder, param: ffi::CharSlice, ) -> ffi::MaybeError { - telemetry_builder.config.parent_session_id = - match (|s: ffi::CharSlice| -> Result<_, String> { - Ok(Some(s.to_utf8_lossy().into_owned())) - })(param) - { - Ok(o) => o, - Err(e) => { - return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), - )); - } - }; + telemetry_builder.root_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ std::fmt::format(format_args!("{0:?}", e)) }), + )); + } + }; ffi::MaybeError::None } #[repr(C)] @@ -378,10 +334,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -395,10 +348,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -412,10 +362,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -429,10 +376,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -446,10 +390,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -463,10 +404,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -479,10 +417,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -496,10 +431,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -513,10 +445,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -530,10 +459,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -546,33 +472,26 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; } SessionId => { - telemetry_builder.config.session_id = - match (|s: ffi::CharSlice| -> Result<_, String> { - Ok(Some(s.to_utf8_lossy().into_owned())) - })(param) - { - Ok(o) => o, - Err(e) => { - return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), - )); - } - }; + telemetry_builder.session_id = match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ std::fmt::format(format_args!("{0:?}", e)) }), + )); + } + }; } ParentSessionId => { - telemetry_builder.config.parent_session_id = + telemetry_builder.parent_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) @@ -580,16 +499,13 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; } RootSessionId => { - telemetry_builder.config.root_session_id = + telemetry_builder.root_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) @@ -597,10 +513,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -652,10 +565,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -669,10 +579,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -686,10 +593,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -703,10 +607,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -720,10 +621,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -737,10 +635,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -754,10 +649,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -770,10 +662,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -787,10 +676,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -804,10 +690,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -821,10 +704,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -837,33 +717,26 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; } "session_id" => { - telemetry_builder.config.session_id = - match (|s: ffi::CharSlice| -> Result<_, String> { - Ok(Some(s.to_utf8_lossy().into_owned())) - })(param) - { - Ok(o) => o, - Err(e) => { - return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), - )); - } - }; + telemetry_builder.session_id = match (|s: ffi::CharSlice| -> Result<_, String> { + Ok(Some(s.to_utf8_lossy().into_owned())) + })(param) + { + Ok(o) => o, + Err(e) => { + return ffi::MaybeError::Some(libdd_common_ffi::Error::from( + ({ std::fmt::format(format_args!("{0:?}", e)) }), + )); + } + }; } "parent_session_id" => { - telemetry_builder.config.parent_session_id = + telemetry_builder.parent_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) @@ -871,16 +744,13 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; } "root_session_id" => { - telemetry_builder.config.root_session_id = + telemetry_builder.root_session_id = match (|s: ffi::CharSlice| -> Result<_, String> { Ok(Some(s.to_utf8_lossy().into_owned())) })(param) @@ -888,10 +758,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -910,10 +777,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -946,10 +810,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -975,10 +836,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -989,10 +847,7 @@ mod macros { Ok(o) => o, Err(e) => { return ffi::MaybeError::Some(libdd_common_ffi::Error::from( - ({ - let res = std::fmt::format(format_args!("{e:?}")); - res - }), + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; From b5c89719fcdf3d1115b9466bc66f0cc7504c1c2e Mon Sep 17 00:00:00 2001 From: Munir Date: Fri, 10 Apr 2026 16:14:58 -0400 Subject: [PATCH 7/7] add parent_id == session_id test --- libdd-telemetry/src/worker/mod.rs | 35 +++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/libdd-telemetry/src/worker/mod.rs b/libdd-telemetry/src/worker/mod.rs index 5b29a117a4..3f43389d76 100644 --- a/libdd-telemetry/src/worker/mod.rs +++ b/libdd-telemetry/src/worker/mod.rs @@ -1251,11 +1251,11 @@ mod tests { } #[test] - fn telemetry_http_omits_parent_and_root_when_duplicate_of_session() { + fn telemetry_http_omits_root_session_id_when_same_as_session_id() { let req = test_worker( Some("sess-id".into()), Some("sess-id".into()), - Some("sess-id".into()), + Some("parent".into()), ) .build_request(&Payload::AppHeartbeat(())) .unwrap(); @@ -1264,6 +1264,37 @@ mod tests { "sess-id" ); assert!(req.headers().get(DD_ROOT_SESSION_ID).is_none()); + assert_eq!( + req.headers() + .get(DD_PARENT_SESSION_ID) + .unwrap() + .to_str() + .unwrap(), + "parent" + ); + } + + #[test] + fn telemetry_http_omits_parent_session_id_when_same_as_session_id() { + let req = test_worker( + Some("sess-id".into()), + Some("root".into()), + Some("sess-id".into()), + ) + .build_request(&Payload::AppHeartbeat(())) + .unwrap(); + assert_eq!( + req.headers().get(DD_SESSION_ID).unwrap().to_str().unwrap(), + "sess-id" + ); + assert_eq!( + req.headers() + .get(DD_ROOT_SESSION_ID) + .unwrap() + .to_str() + .unwrap(), + "root" + ); assert!(req.headers().get(DD_PARENT_SESSION_ID).is_none()); }