diff --git a/libdd-telemetry-ffi/src/builder/expanded.rs b/libdd-telemetry-ffi/src/builder/expanded.rs index 74daf6e8c0..fb4dab3496 100644 --- a/libdd-telemetry-ffi/src/builder/expanded.rs +++ b/libdd-telemetry-ffi/src/builder/expanded.rs @@ -23,10 +23,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 +41,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 +60,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 +79,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 +98,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 +116,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 +134,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 +152,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 +170,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 +188,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 +206,62 @@ 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)) }), + )); + } + }; + 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( + ({ 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( + 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( + ({ 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( + 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( + ({ std::fmt::format(format_args!("{0:?}", e)) }), )); } }; @@ -259,6 +281,9 @@ mod macros { HostKernelRelease, HostKernelVersion, RuntimeId, + SessionId, + ParentSessionId, + RootSessionId, } #[no_mangle] /** @@ -288,6 +313,12 @@ mod macros { * runtime_id + * session_id + + * parent_session_id + + * root_session_id + */ pub unsafe extern "C" fn ddog_telemetry_builder_with_property_str( telemetry_builder: &mut TelemetryWorkerBuilder, @@ -305,10 +336,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)) }), )); } }; @@ -322,10 +350,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)) }), )); } }; @@ -339,10 +364,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)) }), )); } }; @@ -356,10 +378,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)) }), )); } }; @@ -373,10 +392,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)) }), )); } }; @@ -390,10 +406,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)) }), )); } }; @@ -406,10 +419,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)) }), )); } }; @@ -423,10 +433,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)) }), )); } }; @@ -440,10 +447,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)) }), )); } }; @@ -457,10 +461,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)) }), )); } }; @@ -473,14 +474,53 @@ 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( + ({ std::fmt::format(format_args!("{0:?}", e)) }), + )); + } + }; + } + 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( + ({ std::fmt::format(format_args!("{0:?}", e)) }), + )); + } + }; + } + 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( + ({ std::fmt::format(format_args!("{0:?}", e)) }), + )); + } + }; + } } ffi::MaybeError::None } @@ -512,6 +552,12 @@ mod macros { * runtime_id + * session_id + + * parent_session_id + + * root_session_id + */ pub unsafe extern "C" fn ddog_telemetry_builder_with_str_named_property( telemetry_builder: &mut TelemetryWorkerBuilder, @@ -522,10 +568,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)) }), )); } }; @@ -539,10 +582,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)) }), )); } }; @@ -556,10 +596,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)) }), )); } }; @@ -573,10 +610,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)) }), )); } }; @@ -590,10 +624,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)) }), )); } }; @@ -607,10 +638,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)) }), )); } }; @@ -624,10 +652,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)) }), )); } }; @@ -640,10 +665,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)) }), )); } }; @@ -657,10 +679,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)) }), )); } }; @@ -674,10 +693,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)) }), )); } }; @@ -691,10 +707,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)) }), )); } }; @@ -707,14 +720,53 @@ 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( + ({ std::fmt::format(format_args!("{0:?}", e)) }), + )); + } + }; + } + "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( + ({ std::fmt::format(format_args!("{0:?}", e)) }), + )); + } + }; + } + "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( + ({ std::fmt::format(format_args!("{0:?}", e)) }), + )); + } + }; + } _ => return ffi::MaybeError::None, } ffi::MaybeError::None @@ -729,10 +781,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)) }), )); } }; @@ -765,10 +814,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)) }), )); } }; @@ -794,10 +840,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)) }), )); } }; @@ -808,10 +851,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)) }), )); } }; diff --git a/libdd-telemetry-ffi/src/builder/macros.rs b/libdd-telemetry-ffi/src/builder/macros.rs index 4c9377b44d..58c2686eac 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, + parent_session_id, + root_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 69da2ac0f0..1ecdf1c512 100644 --- a/libdd-telemetry/src/config.rs +++ b/libdd-telemetry/src/config.rs @@ -34,6 +34,13 @@ pub struct Config { pub restartable: bool, pub debug_enabled: bool, + + #[serde(default)] + pub session_id: Option, + #[serde(default)] + pub parent_session_id: Option, + #[serde(default)] + pub root_session_id: Option, } fn endpoint_with_telemetry_path( @@ -168,6 +175,9 @@ impl Default for Config { direct_submission_enabled: false, restartable: false, debug_enabled: false, + session_id: None, + parent_session_id: None, + root_session_id: None, } } } @@ -252,6 +262,9 @@ impl Config { direct_submission_enabled: settings.direct_submission_enabled, restartable: false, debug_enabled: false, + 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 673d4186e6..5d0274425d 100644 --- a/libdd-telemetry/src/worker/http_client.rs +++ b/libdd-telemetry/src/worker/http_client.rs @@ -22,8 +22,38 @@ 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"); +} + +/// `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>, + parent_session_id: Option<&str>, + root_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 6da6725acf..93a2b040b6 100644 --- a/libdd-telemetry/src/worker/mod.rs +++ b/libdd-telemetry/src/worker/mod.rs @@ -770,13 +770,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.parent_session_id.as_deref(), + self.config.root_session_id.as_deref(), + ); let body = http_common::Body::from(serialize::serialize(&tel)?); Ok(req.body(body)?) @@ -1268,7 +1273,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) {} @@ -1281,6 +1292,144 @@ mod tests { 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.parent_session_id = parent_session_id; + b.config.root_session_id = root_session_id; + let rt = Runtime::new().unwrap(); + b.build_worker(Some(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_root_session_id_when_same_as_session_id() { + let req = test_worker( + Some("sess-id".into()), + Some("sess-id".into()), + Some("parent".into()), + ) + .build_request(&Payload::AppHeartbeat(())) + .unwrap(); + assert_eq!( + req.headers().get(DD_SESSION_ID).unwrap().to_str().unwrap(), + "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()); + } + + #[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" + ); + } + mod reset { use super::super::*; use crate::data::{