diff --git a/libdd-telemetry-ffi/src/builder/expanded.rs b/libdd-telemetry-ffi/src/builder/expanded.rs index 74daf6e8c0..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,61 @@ 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.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.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.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 +279,9 @@ mod macros { HostKernelRelease, HostKernelVersion, RuntimeId, + SessionId, + ParentSessionId, + RootSessionId, } #[no_mangle] /** @@ -288,6 +311,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 +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)) }), )); } }; @@ -322,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)) }), )); } }; @@ -339,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)) }), )); } }; @@ -356,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)) }), )); } }; @@ -373,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)) }), )); } }; @@ -390,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)) }), )); } }; @@ -406,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)) }), )); } }; @@ -423,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)) }), )); } }; @@ -440,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)) }), )); } }; @@ -457,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)) }), )); } }; @@ -473,14 +472,52 @@ 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.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.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.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 +549,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 +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)) }), )); } }; @@ -539,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)) }), )); } }; @@ -556,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)) }), )); } }; @@ -573,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)) }), )); } }; @@ -590,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)) }), )); } }; @@ -607,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)) }), )); } }; @@ -624,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)) }), )); } }; @@ -640,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)) }), )); } }; @@ -657,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)) }), )); } }; @@ -674,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)) }), )); } }; @@ -691,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)) }), )); } }; @@ -707,14 +717,52 @@ 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.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.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.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 +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)) }), )); } }; @@ -765,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)) }), )); } }; @@ -794,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)) }), )); } }; @@ -808,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)) }), )); } }; 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..68cc487f70 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(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::{