diff --git a/orb-dogd/src/dd.rs b/orb-dogd/src/dd.rs index 41de2869..30d320f3 100644 --- a/orb-dogd/src/dd.rs +++ b/orb-dogd/src/dd.rs @@ -47,6 +47,13 @@ pub(crate) enum Metric { val: f64, tags: Vec, }, + /// Milliseconds latency value; emits Datadog's `|ms` type. + /// Used by [`MetricEmitter::timing`]. + Timing { + stat: String, + val: i64, + tags: Vec, + }, } impl Default for DogstatsdClient { @@ -111,6 +118,11 @@ impl DogstatsdClient { warn!("emitting metric failed with: {e}"); } } + Metric::Timing { stat, val, tags } => { + if let Err(e) = client.timing(stat, val, tags) { + warn!("emitting metric failed with: {e}"); + } + } } } }); @@ -192,4 +204,21 @@ impl MetricEmitter for DogstatsdClient { }; self.emit(metric) } + + fn timing(&self, stat: S, val: i64, tags: I) -> Result<(), MetricError> + where + S: Into, + I: IntoIterator>, + { + let metric = Metric::Timing { + stat: stat.into(), + val, + tags: tags.into_iter().map(Into::into).collect(), + }; + self.tx + .send(metric) + .map_err(|_| eyre::eyre!("metrics worker has died"))?; + + Ok(()) + } } diff --git a/orb-dogd/src/lib.rs b/orb-dogd/src/lib.rs index d6798ec7..46d73350 100644 --- a/orb-dogd/src/lib.rs +++ b/orb-dogd/src/lib.rs @@ -51,4 +51,11 @@ pub trait MetricEmitter: Send + Sync + 'static { where S: Into, I: IntoIterator>; + + /// Latency in milliseconds; emits Datadog's `|ms` type, which the + /// backend treats as a timing-flavored histogram. + fn timing(&self, stat: S, val: i64, tags: I) -> Result<(), MetricError> + where + S: Into, + I: IntoIterator>; } diff --git a/orb-dogd/src/test.rs b/orb-dogd/src/test.rs index c83922f3..f718f419 100644 --- a/orb-dogd/src/test.rs +++ b/orb-dogd/src/test.rs @@ -107,6 +107,20 @@ impl MetricEmitter for MetricRecorder { self.records.lock().expect("mutex poisoned").push(metric); Ok(()) } + + fn timing(&self, stat: S, val: i64, tags: I) -> Result<(), MetricError> + where + S: Into, + I: IntoIterator>, + { + let metric = Metric::Timing { + stat: stat.into(), + val, + tags: tags.into_iter().map(Into::into).collect(), + }; + self.records.lock().expect("mutex poisoned").push(metric); + Ok(()) + } } /// [`MetricEmitter`] that drops every metric on the floor. Useful when test @@ -153,6 +167,14 @@ impl MetricEmitter for MetricSinkhole { { Ok(()) } + + fn timing(&self, _: S, _: i64, _: I) -> Result<(), MetricError> + where + S: Into, + I: IntoIterator>, + { + Ok(()) + } } #[cfg(test)]