-
Notifications
You must be signed in to change notification settings - Fork 21
feat(sidecar): enable telemetry for stats #2175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||
| //! automatically once idle: an empty drain sets the `please_reload` bit (telling PHP workers | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| //! to stop writing), and the subsequent flush performs a final drain before removal. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| use crate::service::{InstanceId, RuntimeMetadata}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use base64::prelude::BASE64_URL_SAFE_NO_PAD; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use base64::Engine; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use datadog_ipc::shm_stats::{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -18,6 +19,8 @@ use futures::{future::join_all, TryFutureExt}; | |||||||||||||||||||||||||||||||||||||||||||||||||||
| use http::uri::PathAndQuery; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use libdd_capabilities_impl::{HttpClientCapability, NativeCapabilities}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use libdd_common::{Endpoint, MutexExt}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use libdd_telemetry::config::Config; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use libdd_telemetry::worker::TelemetryWorkerHandle; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use libdd_trace_stats::stats_exporter::{StatsExporter, StatsMetadata}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::collections::HashMap; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::ffi::CString; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -104,6 +107,7 @@ fn make_exporter( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| s: &SpanConcentratorState, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| endpoint: Endpoint, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| flush_interval: Duration, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| telemetry: Option<TelemetryWorkerHandle>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> StatsExporter<NativeCapabilities, ShmSpanConcentrator> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| StatsExporter::new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| flush_interval, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -119,7 +123,7 @@ fn make_exporter( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| )), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(feature = "stats-obfuscation")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "0", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| telemetry, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -135,6 +139,7 @@ pub async fn run_stats_flush_loop( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| states: Weak<Mutex<HashMap<ConcentratorKey, Arc<SpanConcentratorState>>>>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| map_key: ConcentratorKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| flush_interval: Duration, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| telemetry: Option<TelemetryWorkerHandle>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let Some(arc) = states.upgrade() else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -146,7 +151,13 @@ pub async fn run_stats_flush_loop( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| let Some(state) = state else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let exporter = make_exporter(&state, state.endpoint.clone(), flush_interval); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| let exporter = make_exporter( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| &state, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| state.endpoint.clone(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| flush_interval, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+154
to
+158
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When one service/env has multiple active stats concentrators, such as different versions because the concentrator key includes Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
| telemetry.clone(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| loop { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| tokio::time::sleep(flush_interval).await; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -191,7 +202,11 @@ pub async fn run_stats_flush_loop( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| guard.remove(&map_key); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Err(e) = exporter.send(true).await { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Err(e) = | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| make_exporter(&state, state.endpoint.clone(), flush_interval, telemetry) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .send(true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| warn!("Failed final stats flush: {e}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -210,6 +225,7 @@ pub async fn run_stats_flush_loop( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Returns `None` when stats config is not available (agentless or not yet configured). | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub(crate) fn get_or_create_concentrator( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| concentrators: &Arc<Mutex<HashMap<ConcentratorKey, Arc<SpanConcentratorState>>>>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| telemetry_clients: &crate::service::telemetry::TelemetryCachedClientSet, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| env: &str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| version: &str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| runtime_id: &str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -270,8 +286,46 @@ pub(crate) fn get_or_create_concentrator( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| guard.insert(map_key.clone(), state.clone()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let weak = Arc::downgrade(concentrators); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let flush_interval = config.flush_interval; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| let trace_config = session.get_trace_config(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let runtime_metadata = RuntimeMetadata::new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| trace_config.language.clone(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| trace_config.language_version.clone(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| trace_config.tracer_version.clone(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| drop(trace_config); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+290
to
+296
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| let process_tags = session.process_tags.lock_or_panic().clone(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let instance_id = InstanceId { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| session_id: runtime_id.to_owned(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| runtime_id: runtime_id.to_owned(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+298
to
+300
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the first IPC fallback span for a service/env arrives before any telemetry client exists, Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let telemetry = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let telemetry_mutex = telemetry_clients.get_or_create( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| &service_name, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| env, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| &instance_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| &runtime_metadata, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| || {session | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .session_config | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .lock_or_panic() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .as_ref() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .cloned() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .unwrap_or_else(|| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| warn!("Session telemetry config unavailable for env={env} version={version} service={service_name}; telemetry disabled in stats"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Config::default() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+308
to
+317
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was wondering why cargo fmt didn't format this part and according to claude:
with that format, cargo fmt works again. (btw I checked and escaped newlines in strings are also un-indented so the log still looks like before) |
||||||||||||||||||||||||||||||||||||||||||||||||||||
| process_tags, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let worker = telemetry_mutex | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .lock_or_panic() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .as_ref() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(|c| c.worker.clone()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| worker | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| tokio::spawn(async move { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| run_stats_flush_loop(weak, map_key, flush_interval).await; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| run_stats_flush_loop(weak, map_key, flush_interval, telemetry).await; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Some(state) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -292,7 +346,7 @@ pub async fn flush_all_stats_now( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| .values() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(|s| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| make_exporter(s, s.endpoint.clone(), Duration::from_secs(10)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| make_exporter(s, s.endpoint.clone(), Duration::from_secs(10), None), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
| s.endpoint.clone(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This binds the flush loop to the telemetry worker that existed when the concentrator was created, but telemetry clients are removed on
LifecycleAction::Stopwhile SHM concentrators are global and can remain active until an idle flush removes them. If another runtime for the same service/env continues using the existing concentrator after a Stop/start cycle,get_or_create_concentratorreturns the old state and collapsed-span points keep going to the stopped worker instead of the newly created telemetry client; look up or refresh the worker when flushing rather than capturing it for the concentrator lifetime.Useful? React with 👍 / 👎.