Skip to content

Commit 158eed0

Browse files
refactor(statsd): wrap client in arc
1 parent f9ac7f2 commit 158eed0

11 files changed

Lines changed: 482 additions & 427 deletions

File tree

datadog-sidecar/src/service/session_info.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub(crate) struct SessionInfo {
3030
pub(crate) session_config: Arc<Mutex<Option<libdd_telemetry::config::Config>>>,
3131
debugger_config: Arc<Mutex<datadog_live_debugger::sender::Config>>,
3232
tracer_config: Arc<Mutex<tracer::Config>>,
33-
dogstatsd: Arc<Mutex<Option<libdd_dogstatsd_client::Client>>>,
33+
dogstatsd: Arc<Mutex<Option<libdd_dogstatsd_client::DogStatsDClient>>>,
3434
remote_config_options: Arc<Mutex<Option<ConfigOptions>>>,
3535
pub(crate) agent_infos: Arc<Mutex<Option<AgentInfoGuard>>>,
3636
pub(crate) remote_config_interval: Arc<Mutex<Duration>>,
@@ -210,13 +210,15 @@ impl SessionInfo {
210210
f(&mut self.get_trace_config());
211211
}
212212

213-
pub(crate) fn get_dogstatsd(&self) -> MutexGuard<'_, Option<libdd_dogstatsd_client::Client>> {
213+
pub(crate) fn get_dogstatsd(
214+
&self,
215+
) -> MutexGuard<'_, Option<libdd_dogstatsd_client::DogStatsDClient>> {
214216
self.dogstatsd.lock_or_panic()
215217
}
216218

217219
pub(crate) fn configure_dogstatsd<F>(&self, f: F)
218220
where
219-
F: FnOnce(&mut Option<libdd_dogstatsd_client::Client>),
221+
F: FnOnce(&mut Option<libdd_dogstatsd_client::DogStatsDClient>),
220222
{
221223
f(&mut self.get_dogstatsd());
222224
}

datadog-sidecar/src/service/sidecar_server.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use datadog_ipc::ipc_server::OwnedServerConn;
4747
use datadog_live_debugger::sender::{agent_info_supports_debugger_v2_endpoint, DebuggerType};
4848
use libdd_capabilities_impl::NativeCapabilities;
4949
use libdd_common::tag::Tag;
50-
use libdd_dogstatsd_client::{new, DogStatsDActionOwned};
50+
use libdd_dogstatsd_client::{DogStatsDActionOwned, DogStatsDClient};
5151
use libdd_remote_config::fetch::{ConfigInvariants, ConfigOptions, MultiTargetStats};
5252
use libdd_telemetry::config::{Config, TelemetryEndpoint};
5353
use libdd_tinybytes as tinybytes;
@@ -753,7 +753,7 @@ impl SidecarInterface for ConnectionSidecarHandler {
753753
*endpoint = config.otlp_metrics_endpoint.clone();
754754
});
755755
session.configure_dogstatsd(|dogstatsd| {
756-
let d = new(config.dogstatsd_endpoint.clone()).ok();
756+
let d = DogStatsDClient::new(config.dogstatsd_endpoint.clone()).ok();
757757
*dogstatsd = d;
758758
});
759759
session.modify_debugger_config(|cfg| {

libdd-data-pipeline/src/trace_exporter/builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::trace_exporter::{
2222
use arc_swap::ArcSwap;
2323
use libdd_capabilities::{HttpClientCapability, LogWriterCapability, MaybeSend, SleepCapability};
2424
use libdd_common::{parse_uri, tag, Endpoint};
25-
use libdd_dogstatsd_client::new;
25+
use libdd_dogstatsd_client::DogStatsDClient;
2626
use libdd_shared_runtime::SharedRuntime;
2727
#[cfg(not(target_arch = "wasm32"))]
2828
use libdd_shared_runtime::{BlockingRuntime, ForkSafeRuntime};
@@ -577,7 +577,7 @@ impl<R: SharedRuntime> TraceExporterBuilder<R> {
577577

578578
let dogstatsd = self
579579
.dogstatsd_url
580-
.and_then(|u| new(Endpoint::from_slice(&u)).ok().map(Arc::new));
580+
.and_then(|u| DogStatsDClient::new(Endpoint::from_slice(&u)).ok());
581581

582582
let base_url = self.url.as_deref().unwrap_or(DEFAULT_AGENT_URL);
583583

libdd-data-pipeline/src/trace_exporter/metrics.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
use crate::health_metrics::{HealthMetric, SendResult};
55
use either::Either;
66
use libdd_common::tag::Tag;
7-
use libdd_dogstatsd_client::{Client, DogStatsDAction};
7+
use libdd_dogstatsd_client::{DogStatsDAction, DogStatsDClient};
88
use tracing::debug;
99

1010
/// Handles emission of health metrics to DogStatsD
1111
#[derive(Debug)]
1212
pub(crate) struct MetricsEmitter<'a> {
13-
dogstatsd: Option<&'a Client>,
13+
dogstatsd: Option<&'a DogStatsDClient>,
1414
common_tags: &'a [Tag],
1515
}
1616

1717
impl<'a> MetricsEmitter<'a> {
1818
/// Create a new MetricsEmitter
19-
pub(crate) fn new(dogstatsd: Option<&'a Client>, common_tags: &'a [Tag]) -> Self {
19+
pub(crate) fn new(dogstatsd: Option<&'a DogStatsDClient>, common_tags: &'a [Tag]) -> Self {
2020
Self {
2121
dogstatsd,
2222
common_tags,

libdd-data-pipeline/src/trace_exporter/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use http::Uri;
4242
use libdd_capabilities::{HttpClientCapability, LogWriterCapability, MaybeSend, SleepCapability};
4343
use libdd_common::tag::Tag;
4444
use libdd_common::Endpoint;
45-
use libdd_dogstatsd_client::Client;
45+
use libdd_dogstatsd_client::DogStatsDClient;
4646
#[cfg(not(target_arch = "wasm32"))]
4747
use libdd_shared_runtime::BlockingRuntime;
4848
use libdd_shared_runtime::{SharedRuntime, WorkerHandle};
@@ -253,7 +253,7 @@ pub struct TraceExporter<
253253
serializer: TraceSerializer,
254254
shared_runtime: Arc<R>,
255255
/// None if dogstatsd is disabled
256-
dogstatsd: Option<Arc<Client>>,
256+
dogstatsd: Option<DogStatsDClient>,
257257
common_stats_tags: Vec<Tag>,
258258
client_computed_top_level: bool,
259259
client_side_stats: StatsComputationConfig,
@@ -567,15 +567,15 @@ impl<
567567
/// Emit a health metric to dogstatsd
568568
fn emit_metric(&self, metric: HealthMetric, custom_tags: Option<Vec<&Tag>>) {
569569
if self.health_metrics_enabled {
570-
let emitter = MetricsEmitter::new(self.dogstatsd.as_deref(), &self.common_stats_tags);
570+
let emitter = MetricsEmitter::new(self.dogstatsd.as_ref(), &self.common_stats_tags);
571571
emitter.emit(metric, custom_tags);
572572
}
573573
}
574574

575575
/// Emit all health metrics from a SendResult
576576
fn emit_send_result(&self, result: &SendResult) {
577577
if self.health_metrics_enabled {
578-
let emitter = MetricsEmitter::new(self.dogstatsd.as_deref(), &self.common_stats_tags);
578+
let emitter = MetricsEmitter::new(self.dogstatsd.as_ref(), &self.common_stats_tags);
579579
emitter.emit_from_send_result(result);
580580
}
581581
}

libdd-data-pipeline/src/trace_exporter/stats.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub(crate) struct StatsContext<'a, R: SharedRuntime> {
5151
pub shared_runtime: &'a R,
5252
pub stats_cardinality_limit: Option<usize>,
5353
/// Optional DogStatsD client forwarded to the [`StatsExporter`].
54-
pub dogstatsd: Option<std::sync::Arc<libdd_dogstatsd_client::Client>>,
54+
pub dogstatsd: Option<libdd_dogstatsd_client::DogStatsDClient>,
5555
/// Optional telemetry handle forwarded to the [`StatsExporter`].
5656
#[cfg(feature = "telemetry")]
5757
pub telemetry: Option<libdd_telemetry::worker::TelemetryWorkerHandle>,
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use libdd_common::tag::Tag;
5+
use serde::{Deserialize, Serialize};
6+
use std::fmt::Debug;
7+
8+
/// The `DogStatsDActionOwned` enum gathers the metric types that can be sent to the DogStatsD
9+
/// server. This type takes ownership of the relevant data to support the sidecar better.
10+
/// For documentation on the dogstatsd metric types: https://docs.datadoghq.com/metrics/types/?tab=count#metric-types
11+
///
12+
/// Originally I attempted to combine this type with `DogStatsDAction` but this GREATLY complicates
13+
/// the types to the point of insanity. I was unable to come up with a satisfactory approach that
14+
/// allows both the data-pipeline and sidecar crates to use the same type. If a future rustacean
15+
/// wants to take a stab and open a PR please do so!
16+
#[derive(Debug, Serialize, Deserialize)]
17+
pub enum DogStatsDActionOwned {
18+
#[allow(missing_docs)]
19+
Count(String, i64, Vec<Tag>),
20+
#[allow(missing_docs)]
21+
Distribution(String, f64, Vec<Tag>),
22+
#[allow(missing_docs)]
23+
Gauge(String, f64, Vec<Tag>),
24+
#[allow(missing_docs)]
25+
Histogram(String, f64, Vec<Tag>),
26+
/// Cadence only support i64 type as value
27+
/// but Golang implementation uses string (https://github.com/DataDog/datadog-go/blob/331d24832f7eac97b091efd696278fe2c4192b29/statsd/statsd.go#L230)
28+
/// and PHP implementation uses float or string (https://github.com/DataDog/php-datadogstatsd/blob/0efdd1c38f6d3dd407efbb899ad1fd2e5cd18085/src/DogStatsd.php#L251)
29+
Set(String, i64, Vec<Tag>),
30+
}
31+
32+
/// The `DogStatsDAction` enum gathers the metric types that can be sent to the DogStatsD server.
33+
#[derive(Debug, Serialize, Deserialize)]
34+
pub enum DogStatsDAction<'a, T: AsRef<str>, V: IntoIterator<Item = &'a Tag>> {
35+
// TODO: instead of AsRef<str> we can accept a marker Trait that users of this crate implement
36+
#[allow(missing_docs)]
37+
Count(T, i64, V),
38+
#[allow(missing_docs)]
39+
Distribution(T, f64, V),
40+
#[allow(missing_docs)]
41+
Gauge(T, f64, V),
42+
#[allow(missing_docs)]
43+
Histogram(T, f64, V),
44+
/// Cadence only support i64 type as value
45+
/// but Golang implementation uses string (https://github.com/DataDog/datadog-go/blob/331d24832f7eac97b091efd696278fe2c4192b29/statsd/statsd.go#L230)
46+
/// and PHP implementation uses float or string (https://github.com/DataDog/php-datadogstatsd/blob/0efdd1c38f6d3dd407efbb899ad1fd2e5cd18085/src/DogStatsd.php#L251)
47+
Set(T, i64, V),
48+
}
49+
50+
#[cfg(test)]
51+
mod tests {
52+
use super::*;
53+
#[test]
54+
fn test_owned_sync() {
55+
// This test ensures that if a new variant is added to either `DogStatsDActionOwned` or
56+
// `DogStatsDAction` this test will NOT COMPILE to act as a reminder that BOTH locations
57+
// must be updated.
58+
let owned_act = DogStatsDActionOwned::Count("test".to_string(), 1, vec![]);
59+
match owned_act {
60+
DogStatsDActionOwned::Count(_, _, _) => {}
61+
DogStatsDActionOwned::Distribution(_, _, _) => {}
62+
DogStatsDActionOwned::Gauge(_, _, _) => {}
63+
DogStatsDActionOwned::Histogram(_, _, _) => {}
64+
DogStatsDActionOwned::Set(_, _, _) => {}
65+
}
66+
67+
let act = DogStatsDAction::Count("test".to_string(), 1, vec![]);
68+
match act {
69+
DogStatsDAction::Count(_, _, _) => {}
70+
DogStatsDAction::Distribution(_, _, _) => {}
71+
DogStatsDAction::Gauge(_, _, _) => {}
72+
DogStatsDAction::Histogram(_, _, _) => {}
73+
DogStatsDAction::Set(_, _, _) => {}
74+
}
75+
// TODO: when std::mem::variant_count is in stable we can do this instead
76+
// assert_eq!(
77+
// std::mem::variant_count::<DogStatsDActionOwned>(),
78+
// std::mem::variant_count::<DogStatsDAction<String, Vec<&Tag>>>(),
79+
// "DogStatsDActionOwned and DogStatsDAction should have the same number of variants,
80+
// did you forget to update one?", );
81+
}
82+
}

0 commit comments

Comments
 (0)