diff --git a/datadog-remote-config/examples/remote_config_fetch.rs b/datadog-remote-config/examples/remote_config_fetch.rs index 99aeb18a73..d53146a3e6 100644 --- a/datadog-remote-config/examples/remote_config_fetch.rs +++ b/datadog-remote-config/examples/remote_config_fetch.rs @@ -33,6 +33,7 @@ async fn main() { env: ENV.to_string(), app_version: VERSION.to_string(), tags: vec![Tag::new("test", "value").unwrap()], + process_tags: vec![], }, RUNTIME_ID.to_string(), ConfigOptions { diff --git a/datadog-remote-config/src/fetch/fetcher.rs b/datadog-remote-config/src/fetch/fetcher.rs index 504f3f1dc0..9378c8e5a6 100644 --- a/datadog-remote-config/src/fetch/fetcher.rs +++ b/datadog-remote-config/src/fetch/fetcher.rs @@ -277,6 +277,7 @@ impl ConfigFetcher { env, app_version, tags, + process_tags, } = (*target).clone(); let mut cached_target_files = vec![]; @@ -325,6 +326,8 @@ impl ConfigFetcher { env, app_version, tags: tags.iter().map(|t| t.to_string()).collect(), + process_tags: process_tags.iter().map(|t| t.to_string()).collect(), + container_tags: vec![], }), is_agent: false, client_agent: None, @@ -601,6 +604,19 @@ pub mod tests { env: "env".to_string(), app_version: "1.3.5".to_string(), tags: vec![], + process_tags: vec![], + }) + }); + pub(crate) static DUMMY_TARGET_WITH_PROCESS_TAGS: LazyLock> = LazyLock::new(|| { + Arc::new(Target { + service: "service".to_string(), + env: "env".to_string(), + app_version: "1.3.5".to_string(), + tags: vec![], + process_tags: vec![ + libdd_common::tag!("entrypoint.workdir", "datadog-remote-config"), + libdd_common::tag!("entrypoint.type", "script"), + ], }) }); @@ -898,6 +914,52 @@ pub mod tests { } } + #[tokio::test] + #[cfg_attr(miri, ignore)] + async fn test_process_tags_forwarded_in_client_tracer() { + let server: Arc = RemoteConfigServer::spawn(); + server.files.lock().unwrap().insert( + PATH_FIRST.clone(), + ( + vec![DUMMY_TARGET_WITH_PROCESS_TAGS.clone()], + 1, + "v1".to_string(), + ), + ); + + let storage = Arc::new(Storage::default()); + let mut fetcher = ConfigFetcher::new( + storage, + Arc::new(ConfigFetcherState::new(server.dummy_options().invariants)), + ); + let mut opaque_state = ConfigClientState::default(); + + let fetched = fetcher + .fetch_once( + DUMMY_RUNTIME_ID, + DUMMY_TARGET_WITH_PROCESS_TAGS.clone(), + &server.dummy_product_capabilities(), + "foo", + &mut opaque_state, + ) + .await + .unwrap() + .unwrap(); + + assert_eq!(fetched.len(), 1); + + let req = server.last_request.lock().unwrap(); + let req = req.as_ref().unwrap(); + let tracer = req.client.as_ref().unwrap().client_tracer.as_ref().unwrap(); + assert_eq!( + tracer.process_tags, + &[ + "entrypoint.workdir:datadog-remote-config", + "entrypoint.type:script" + ] + ); + } + #[test] #[cfg_attr(miri, ignore)] fn test_capability_encoding() { diff --git a/datadog-remote-config/src/fetch/shared.rs b/datadog-remote-config/src/fetch/shared.rs index 24397aeac9..38197f324a 100644 --- a/datadog-remote-config/src/fetch/shared.rs +++ b/datadog-remote-config/src/fetch/shared.rs @@ -385,6 +385,7 @@ pub mod tests { env: "env".to_string(), app_version: "7.8.9".to_string(), tags: vec![], + process_tags: vec![], }) }); diff --git a/datadog-remote-config/src/lib.rs b/datadog-remote-config/src/lib.rs index 8269c8672c..c249fa55b4 100644 --- a/datadog-remote-config/src/lib.rs +++ b/datadog-remote-config/src/lib.rs @@ -32,6 +32,7 @@ pub struct Target { pub env: String, pub app_version: String, pub tags: Vec, + pub process_tags: Vec, } #[repr(C)] diff --git a/datadog-sidecar-ffi/src/lib.rs b/datadog-sidecar-ffi/src/lib.rs index 78bab1d2e6..2978dc953a 100644 --- a/datadog-sidecar-ffi/src/lib.rs +++ b/datadog-sidecar-ffi/src/lib.rs @@ -255,6 +255,7 @@ pub unsafe extern "C" fn ddog_remote_config_reader_for_endpoint<'a>( env: env_name.to_utf8_lossy().into(), app_version: app_version.to_utf8_lossy().into(), tags: tags.as_slice().to_vec(), + process_tags: vec![], }), )) } @@ -588,7 +589,7 @@ pub unsafe extern "C" fn ddog_sidecar_session_set_config( remote_config_capabilities_count: usize, remote_config_enabled: bool, is_fork: bool, - process_tags: ffi::CharSlice, + process_tags: &libdd_common_ffi::Vec, ) -> MaybeError { #[cfg(unix)] let remote_config_notify_target = libc::getpid(); @@ -632,7 +633,7 @@ pub unsafe extern "C" fn ddog_sidecar_session_set_config( .as_slice() .to_vec(), remote_config_enabled, - process_tags: process_tags.to_utf8_lossy().into(), + process_tags: process_tags.to_vec(), }, is_fork )); @@ -646,12 +647,12 @@ pub unsafe extern "C" fn ddog_sidecar_session_set_config( pub unsafe extern "C" fn ddog_sidecar_session_set_process_tags( transport: &mut Box, session_id: ffi::CharSlice, - process_tags: ffi::CharSlice, + process_tags: &libdd_common_ffi::Vec, ) -> MaybeError { try_c!(blocking::set_session_process_tags( transport, session_id.to_utf8_lossy().into(), - process_tags.to_utf8_lossy().into(), + process_tags.to_vec(), )); MaybeError::None diff --git a/datadog-sidecar-ffi/tests/sidecar.rs b/datadog-sidecar-ffi/tests/sidecar.rs index 4a564d9122..1536995d2b 100644 --- a/datadog-sidecar-ffi/tests/sidecar.rs +++ b/datadog-sidecar-ffi/tests/sidecar.rs @@ -87,6 +87,7 @@ fn test_ddog_sidecar_register_app() { .unwrap(); unsafe { + let process_tags = libdd_common_ffi::Vec::default(); ddog_sidecar_session_set_config( &mut transport, "session_id".into(), @@ -112,7 +113,7 @@ fn test_ddog_sidecar_register_app() { 0, false, false, - "".into(), + &process_tags, ) .unwrap_none(); @@ -163,7 +164,7 @@ fn test_ddog_sidecar_register_app() { 0, false, false, - "".into(), + &process_tags, ) .unwrap_none(); diff --git a/datadog-sidecar/src/service/blocking.rs b/datadog-sidecar/src/service/blocking.rs index b290f40e64..8ea858e8f5 100644 --- a/datadog-sidecar/src/service/blocking.rs +++ b/datadog-sidecar/src/service/blocking.rs @@ -249,7 +249,7 @@ pub fn set_session_config( /// /// * `transport` - The transport used for communication. /// * `session_id` - The ID of the session. -/// * `process_tags` - The process tags string to set. +/// * `process_tags` - The process tags to set. /// /// # Returns /// @@ -257,7 +257,7 @@ pub fn set_session_config( pub fn set_session_process_tags( transport: &mut SidecarTransport, session_id: String, - process_tags: String, + process_tags: Vec, ) -> io::Result<()> { transport.send(SidecarInterfaceRequest::SetSessionProcessTags { session_id, diff --git a/datadog-sidecar/src/service/mod.rs b/datadog-sidecar/src/service/mod.rs index 5c25ff9906..b5e3ddb081 100644 --- a/datadog-sidecar/src/service/mod.rs +++ b/datadog-sidecar/src/service/mod.rs @@ -64,7 +64,7 @@ pub struct SessionConfig { pub remote_config_products: Vec, pub remote_config_capabilities: Vec, pub remote_config_enabled: bool, - pub process_tags: String, + pub process_tags: Vec, } #[derive(Debug, Deserialize, Serialize)] diff --git a/datadog-sidecar/src/service/remote_configs.rs b/datadog-sidecar/src/service/remote_configs.rs index d030dd21f3..ab00df1b3d 100644 --- a/datadog-sidecar/src/service/remote_configs.rs +++ b/datadog-sidecar/src/service/remote_configs.rs @@ -110,6 +110,7 @@ impl RemoteConfigs { app_version: String, tags: Vec, dynamic_instrumentation_state: DynamicInstrumentationConfigState, + process_tags: Vec, ) -> RemoteConfigsGuard { match self.0.lock_or_panic().entry(options.invariants) { Entry::Occupied(e) => e.into_mut(), @@ -148,6 +149,7 @@ impl RemoteConfigs { capabilities: options.capabilities, }, dynamic_instrumentation_state, + process_tags, ) } diff --git a/datadog-sidecar/src/service/runtime_info.rs b/datadog-sidecar/src/service/runtime_info.rs index bca8c0abad..68b3eb52cf 100644 --- a/datadog-sidecar/src/service/runtime_info.rs +++ b/datadog-sidecar/src/service/runtime_info.rs @@ -142,6 +142,9 @@ impl ActiveApplication { .as_ref() .expect("Expecting remote config invariants to be set early") .clone(); + + let process_tags = session.process_tags.lock_or_panic().clone(); + if *session.remote_config_enabled.lock_or_panic() { self.remote_config_guard = Some( remote_configs.add_runtime( @@ -158,6 +161,7 @@ impl ActiveApplication { .expect("set_metadata was called before"), self.global_tags.clone(), dynamic_instrumentation_state, + process_tags, ), ); } diff --git a/datadog-sidecar/src/service/session_info.rs b/datadog-sidecar/src/service/session_info.rs index a966c9ab76..34495cb67a 100644 --- a/datadog-sidecar/src/service/session_info.rs +++ b/datadog-sidecar/src/service/session_info.rs @@ -14,7 +14,7 @@ use crate::log::{MultiEnvFilterGuard, MultiWriterGuard}; use crate::{spawn_map_err, tracer}; use datadog_live_debugger::sender::{DebuggerType, PayloadSender}; use datadog_remote_config::fetch::ConfigOptions; -use libdd_common::MutexExt; +use libdd_common::{tag::Tag, MutexExt}; use tracing::log::warn; use tracing::{debug, error, info, trace}; @@ -43,7 +43,7 @@ pub(crate) struct SessionInfo { pub(crate) session_id: String, pub(crate) pid: Arc, pub(crate) remote_config_enabled: Arc>, - pub(crate) process_tags: Arc>>, + pub(crate) process_tags: Arc>>, } impl Clone for SessionInfo { diff --git a/datadog-sidecar/src/service/sidecar_interface.rs b/datadog-sidecar/src/service/sidecar_interface.rs index bfcdfe05ca..eeddcde5e9 100644 --- a/datadog-sidecar/src/service/sidecar_interface.rs +++ b/datadog-sidecar/src/service/sidecar_interface.rs @@ -73,9 +73,9 @@ pub trait SidecarInterface { /// # Arguments /// /// * `session_id` - The ID of the session. - /// * `process_tags` - The process tags string. + /// * `process_tags` - The process tags. #[force_backpressure] - async fn set_session_process_tags(session_id: String, process_tags: String); + async fn set_session_process_tags(session_id: String, process_tags: Vec); /// Shuts down a runtime. /// diff --git a/datadog-sidecar/src/service/sidecar_server.rs b/datadog-sidecar/src/service/sidecar_server.rs index e7a9875bca..d3655f6bcb 100644 --- a/datadog-sidecar/src/service/sidecar_server.rs +++ b/datadog-sidecar/src/service/sidecar_server.rs @@ -567,8 +567,7 @@ impl SidecarInterface for SidecarServer { *session.remote_config_notify_function.lock().unwrap() = remote_config_notify_function; } *session.remote_config_enabled.lock_or_panic() = config.remote_config_enabled; - *session.process_tags.lock_or_panic() = - (!config.process_tags.is_empty()).then_some(config.process_tags.clone()); + *session.process_tags.lock_or_panic() = config.process_tags.clone(); session.modify_telemetry_config(|cfg| { cfg.telemetry_heartbeat_interval = config.telemetry_heartbeat_interval; let endpoint = get_product_endpoint( @@ -664,10 +663,10 @@ impl SidecarInterface for SidecarServer { self, _: Context, session_id: String, - process_tags: String, + process_tags: Vec, ) -> Self::SetSessionProcessTagsFut { let session = self.get_session(&session_id); - *session.process_tags.lock_or_panic() = (!process_tags.is_empty()).then_some(process_tags); + *session.process_tags.lock_or_panic() = process_tags; no_response() } diff --git a/datadog-sidecar/src/service/telemetry.rs b/datadog-sidecar/src/service/telemetry.rs index 2199ac328b..64c125b701 100644 --- a/datadog-sidecar/src/service/telemetry.rs +++ b/datadog-sidecar/src/service/telemetry.rs @@ -77,7 +77,7 @@ impl TelemetryCachedClient { instance_id: &InstanceId, runtime_meta: &RuntimeMetadata, get_config: impl FnOnce() -> libdd_telemetry::config::Config, - process_tags: Option, + process_tags: Vec, ) -> Self { let mut builder = TelemetryWorkerBuilder::new_fetch_host( service.to_string(), @@ -88,7 +88,13 @@ impl TelemetryCachedClient { builder.runtime_id = Some(instance_id.runtime_id.clone()); builder.application.env = Some(env.to_string()); - builder.application.process_tags = process_tags; + builder.application.process_tags = (!process_tags.is_empty()).then(|| { + process_tags + .iter() + .map(|tag| tag.to_string()) + .collect::>() + .join(",") + }); let config = get_config(); builder.config = config.clone(); @@ -300,7 +306,7 @@ impl TelemetryCachedClientSet { instance_id: &InstanceId, runtime_meta: &RuntimeMetadata, get_config: F, - process_tags: Option, + process_tags: Vec, ) -> Arc> where F: FnOnce() -> libdd_telemetry::config::Config, diff --git a/datadog-sidecar/src/shm_remote_config.rs b/datadog-sidecar/src/shm_remote_config.rs index a20c98d8d6..11b9cb9c63 100644 --- a/datadog-sidecar/src/shm_remote_config.rs +++ b/datadog-sidecar/src/shm_remote_config.rs @@ -461,12 +461,14 @@ impl ShmRemoteConfigs { tags: Vec, product_capabilities: ProductCapabilities, dynamic_instrumentation_state: DynamicInstrumentationConfigState, + process_tags: Vec, ) -> ShmRemoteConfigsGuard { let target = Arc::new(Target { service, env, app_version, tags, + process_tags, }); self.0.add_runtime( runtime_id.clone(), @@ -776,6 +778,7 @@ mod tests { env: "env".to_string(), app_version: "1.3.5".to_string(), tags: vec![], + process_tags: vec![], }) }); @@ -852,6 +855,7 @@ mod tests { capabilities: server.dummy_options().capabilities, }, DynamicInstrumentationConfigState::Disabled, + DUMMY_TARGET.process_tags.clone(), ); receiver.recv().await; diff --git a/datadog-tracer-flare/src/lib.rs b/datadog-tracer-flare/src/lib.rs index cfdd49fa42..eb5875cdf6 100644 --- a/datadog-tracer-flare/src/lib.rs +++ b/datadog-tracer-flare/src/lib.rs @@ -192,6 +192,7 @@ impl TracerFlareManager { env, app_version, tags: vec![], + process_tags: vec![], }, runtime_id, config_to_fetch, diff --git a/libdd-trace-protobuf/src/pb/remoteconfig.proto b/libdd-trace-protobuf/src/pb/remoteconfig.proto index 7b1aa7f897..606bc851e7 100644 --- a/libdd-trace-protobuf/src/pb/remoteconfig.proto +++ b/libdd-trace-protobuf/src/pb/remoteconfig.proto @@ -35,6 +35,8 @@ message ClientTracer { string env = 5; string app_version = 6; repeated string tags = 7; + repeated string process_tags = 9; + repeated string container_tags = 10; } message ClientAgent { diff --git a/libdd-trace-protobuf/src/remoteconfig.rs b/libdd-trace-protobuf/src/remoteconfig.rs index b579721a18..9e0a62494a 100644 --- a/libdd-trace-protobuf/src/remoteconfig.rs +++ b/libdd-trace-protobuf/src/remoteconfig.rs @@ -54,6 +54,10 @@ pub struct ClientTracer { pub app_version: ::prost::alloc::string::String, #[prost(string, repeated, tag = "7")] pub tags: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(string, repeated, tag = "9")] + pub process_tags: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(string, repeated, tag = "10")] + pub container_tags: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, } #[derive(Deserialize, Serialize)] #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]