Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions datadog-sidecar-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,43 @@ pub unsafe extern "C" fn ddog_sidecar_session_set_process_tags(
MaybeError::None
}

/// Records the tracer's auto-resolved default service name for the session
/// (process-bound; sidecar emits `svc.auto:<name>` when `DD_SERVICE` is not
/// currently set for the active request). Pass an empty `CharSlice` to clear.
#[no_mangle]
#[allow(clippy::missing_safety_doc)]
pub unsafe extern "C" fn ddog_sidecar_session_set_default_service_name(
transport: &mut Box<SidecarTransport>,
default_service_name: ffi::CharSlice,
) -> MaybeError {
let name = if default_service_name.is_empty() {
None
} else {
Some(default_service_name.to_utf8_lossy().into_owned())
};
try_c!(blocking::set_session_default_service_name(transport, name));

MaybeError::None
}

/// Records whether `DD_SERVICE` is currently set for the session (per-request
/// mutable; refresh on each RINIT). When `true` the sidecar emits
/// `svc.user:true`; when `false` it falls back to the previously-recorded
/// `svc.auto:<name>` (if any).
#[no_mangle]
#[allow(clippy::missing_safety_doc)]
pub unsafe extern "C" fn ddog_sidecar_session_set_user_service_defined(
transport: &mut Box<SidecarTransport>,
is_user_defined: bool,
) -> MaybeError {
try_c!(blocking::set_session_user_service_defined(
transport,
is_user_defined,
));

MaybeError::None
}

#[repr(C)]
pub struct TracerHeaderTags<'a> {
pub lang: ffi::CharSlice<'a>,
Expand Down
16 changes: 16 additions & 0 deletions datadog-sidecar/src/service/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,22 @@ pub fn set_session_process_tags(
Ok(())
}

pub fn set_session_default_service_name(
transport: &mut SidecarTransport,
name: Option<String>,
) -> io::Result<()> {
lock_sender(transport)?.set_session_default_service_name(name);
Ok(())
}

pub fn set_session_user_service_defined(
transport: &mut SidecarTransport,
is_defined: bool,
) -> io::Result<()> {
lock_sender(transport)?.set_session_user_service_defined(is_defined);
Ok(())
}

/// Sends a trace as bytes.
pub fn send_trace_v04_bytes(
transport: &mut SidecarTransport,
Expand Down
1 change: 1 addition & 0 deletions datadog-sidecar/src/service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,4 @@ pub enum SidecarAction {
metrics: Vec<FfeEvaluationMetric>,
},
}

3 changes: 3 additions & 0 deletions datadog-sidecar/src/service/runtime_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ impl ActiveApplication {
.expect("Expecting remote config invariants to be set early")
.clone();

// Target is hashed on the sidecar side and on the PHP read side
// (sidecar.c:ddog_remote_configs_service_env_change). PHP passes the
// bare process_tags Vec, so we must too — otherwise SHM lookups miss.
let process_tags = session.process_tags.lock_or_panic().clone();

if *session.remote_config_enabled.lock_or_panic() {
Expand Down
28 changes: 27 additions & 1 deletion datadog-sidecar/src/service/sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ use tracing::trace;
struct SidecarOutbox {
set_session_config: Option<SidecarInterfaceRequest>,
set_session_process_tags: Option<SidecarInterfaceRequest>,
set_session_default_service_name: Option<SidecarInterfaceRequest>,
set_session_user_service_defined: Option<SidecarInterfaceRequest>,
set_universal_service_tags: Option<SidecarInterfaceRequest>,
set_request_config: Option<SidecarInterfaceRequest>,
clear_queue_id: Option<SidecarInterfaceRequest>,
Expand All @@ -43,10 +45,12 @@ struct SidecarOutbox {
}

impl SidecarOutbox {
fn slots_mut(&mut self) -> [&mut Option<SidecarInterfaceRequest>; 7] {
fn slots_mut(&mut self) -> [&mut Option<SidecarInterfaceRequest>; 9] {
[
&mut self.set_session_config,
&mut self.set_session_process_tags,
&mut self.set_session_default_service_name,
&mut self.set_session_user_service_defined,
&mut self.set_universal_service_tags,
&mut self.set_request_config,
&mut self.clear_queue_id,
Expand Down Expand Up @@ -122,6 +126,12 @@ fn coalesce(outbox: &mut SidecarOutbox, incoming: SidecarInterfaceRequest) {
SidecarInterfaceRequest::SetSessionProcessTags { .. } => {
outbox.set_session_process_tags = Some(incoming);
}
SidecarInterfaceRequest::SetSessionDefaultServiceName { .. } => {
outbox.set_session_default_service_name = Some(incoming);
}
SidecarInterfaceRequest::SetSessionUserServiceDefined { .. } => {
outbox.set_session_user_service_defined = Some(incoming);
}
SidecarInterfaceRequest::SetUniversalServiceTags { .. } => {
outbox.set_universal_service_tags = Some(incoming);
}
Expand Down Expand Up @@ -236,6 +246,22 @@ impl SidecarSender {
self.try_drain_outbox();
}

pub fn set_session_default_service_name(&mut self, name: Option<String>) {
coalesce(
&mut self.outbox,
SidecarInterfaceRequest::SetSessionDefaultServiceName { name },
);
self.try_drain_outbox();
}

pub fn set_session_user_service_defined(&mut self, is_defined: bool) {
coalesce(
&mut self.outbox,
SidecarInterfaceRequest::SetSessionUserServiceDefined { is_defined },
);
self.try_drain_outbox();
}

#[allow(clippy::too_many_arguments)]
pub fn set_universal_service_tags(
&mut self,
Expand Down
27 changes: 27 additions & 0 deletions datadog-sidecar/src/service/session_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub(crate) struct SessionInfo {
pub(crate) pid: Arc<AtomicI32>,
pub(crate) remote_config_enabled: Arc<Mutex<bool>>,
pub(crate) process_tags: Arc<Mutex<Vec<Tag>>>,
pub(crate) auto_resolved_service_name: Arc<Mutex<Option<String>>>,
pub(crate) user_service_defined: Arc<Mutex<bool>>,
pub(crate) stats_config: Arc<Mutex<Option<crate::service::stats_flusher::StatsConfig>>>,
otlp_metrics_endpoint: Arc<Mutex<Option<Endpoint>>>,
}
Expand Down Expand Up @@ -131,6 +133,31 @@ impl SessionInfo {
self.runtimes.lock_or_panic()
}

pub(crate) fn process_tags_with_svc_source(&self) -> Vec<Tag> {
let mut tags = self.process_tags.lock_or_panic().clone();
if *self.user_service_defined.lock_or_panic() {
if let Ok(tag) = Tag::new("svc.user", "true") {
tags.push(tag);
}
} else if let Some(name) = self.auto_resolved_service_name.lock_or_panic().as_ref() {
if let Ok(tag) = Tag::new("svc.auto", name.clone()) {
tags.push(tag);
}
}
tags
}

pub(crate) fn refresh_stats_process_tags(&self) {
if let Some(stats) = self.stats_config.lock_or_panic().as_mut() {
stats.process_tags = self
.process_tags_with_svc_source()
.iter()
.map(|t| t.to_string())
.collect::<Vec<_>>()
.join(",");
}
}

pub(crate) fn get_telemetry_config(
&self,
) -> MutexGuard<'_, Option<libdd_telemetry::config::Config>> {
Expand Down
9 changes: 9 additions & 0 deletions datadog-sidecar/src/service/sidecar_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ pub trait SidecarInterface {
/// * `process_tags` - The process tags.
async fn set_session_process_tags(process_tags: Vec<Tag>);

/// Records the auto-resolved default service name for the session
/// (process-bound; the tracer's fallback when `DD_SERVICE` is unset).
/// Pass `None` to clear it.
async fn set_session_default_service_name(name: Option<String>);

/// Records whether `DD_SERVICE` is currently set for the session
/// (per-request mutable; tracer should refresh on RINIT).
async fn set_session_user_service_defined(is_defined: bool);

/// Removes the application entry for the given queue ID from the instance.
///
/// # Arguments
Expand Down
37 changes: 34 additions & 3 deletions datadog-sidecar/src/service/sidecar_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ impl SidecarInterface for ConnectionSidecarHandler {
.unwrap_or("unknown-service");
let env = entry.get().env.as_deref().unwrap_or("none");

let process_tags = session.process_tags.lock_or_panic().clone();
let process_tags = session.process_tags_with_svc_source();

// Pre-compute session config so both the primary and retry get_or_create calls
// can use it without re-locking the session.
Expand Down Expand Up @@ -763,8 +763,8 @@ impl SidecarInterface for ConnectionSidecarHandler {
} else {
config.hostname.clone()
},
process_tags: config
.process_tags
process_tags: session
.process_tags_with_svc_source()
.iter()
.map(|t| t.to_string())
.collect::<Vec<_>>()
Expand Down Expand Up @@ -828,6 +828,37 @@ impl SidecarInterface for ConnectionSidecarHandler {
.unwrap_or_default();
let session = self.server.get_session(session_id);
*session.process_tags.lock_or_panic() = process_tags;
session.refresh_stats_process_tags();
}

async fn set_session_default_service_name(
&self,
_peer: PeerCredentials,
name: Option<String>,
) {
let session_id = self
.session_id
.get()
.map(|s| s.as_str())
.unwrap_or_default();
let session = self.server.get_session(session_id);
*session.auto_resolved_service_name.lock_or_panic() = name;
session.refresh_stats_process_tags();
}

async fn set_session_user_service_defined(
&self,
_peer: PeerCredentials,
is_defined: bool,
) {
let session_id = self
.session_id
.get()
.map(|s| s.as_str())
.unwrap_or_default();
let session = self.server.get_session(session_id);
*session.user_service_defined.lock_or_panic() = is_defined;
session.refresh_stats_process_tags();
}

async fn shutdown_runtime(&self, _peer: PeerCredentials, instance_id: InstanceId) {
Expand Down
2 changes: 1 addition & 1 deletion datadog-sidecar/src/service/telemetry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ fn get_telemetry_client(
return None;
};

let process_tags = session.process_tags.lock_or_panic().clone();
let process_tags = session.process_tags_with_svc_source();

Some(sidecar.telemetry_clients.get_or_create(
service_name,
Expand Down
Loading