Skip to content

Commit

Permalink
Add blanket implementations of Recorder for some pointer-like types
Browse files Browse the repository at this point in the history
`Rc`, `Arc`, and `Box`.

Closes #506.
  • Loading branch information
david-perez authored and tobz committed Sep 5, 2024
1 parent ca453d3 commit 15adb44
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 5 deletions.
47 changes: 46 additions & 1 deletion metrics-util/src/layers/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ mod tests {
predicate::{always, eq},
Sequence,
};
use std::borrow::Cow;
use std::{borrow::Cow, rc::Rc};

use super::RouterBuilder;
use crate::MetricKindMask;
Expand Down Expand Up @@ -265,4 +265,49 @@ mod tests {
let _ = recorder.register_counter(&all_override, &METADATA);
let _ = recorder.register_histogram(&all_override, &METADATA);
}

#[test]
fn test_same_recorder_multiple_routes() {
let default_counter: Key = "default".into();
let foo_counter: Key = "foo.counter".into();
let bar_counter: Key = "bar.counter".into();

let mut default_mock = MockTestRecorder::new();
let mut foo_bar_mock = MockTestRecorder::new();

let mut seq = Sequence::new();

static METADATA: metrics::Metadata =
metrics::Metadata::new(module_path!(), metrics::Level::INFO, Some(module_path!()));

foo_bar_mock
.expect_register_counter()
.times(1)
.in_sequence(&mut seq)
.with(eq(foo_counter.clone()), always())
.returning(|_, _| Counter::noop());
foo_bar_mock
.expect_register_counter()
.times(1)
.in_sequence(&mut seq)
.with(eq(bar_counter.clone()), always())
.returning(|_, _| Counter::noop());
default_mock
.expect_register_counter()
.times(1)
.in_sequence(&mut seq)
.with(eq(default_counter.clone()), always())
.returning(|_, _| Counter::noop());

let foo_bar_mock = Rc::new(foo_bar_mock);

let mut builder = RouterBuilder::from_recorder(default_mock);
builder.add_route(MetricKindMask::COUNTER, "foo", foo_bar_mock.clone());
builder.add_route(MetricKindMask::COUNTER, "bar", foo_bar_mock);
let recorder = builder.build();

let _ = recorder.register_counter(&foo_counter, &METADATA);
let _ = recorder.register_counter(&bar_counter, &METADATA);
let _ = recorder.register_counter(&default_counter, &METADATA);
}
}
112 changes: 108 additions & 4 deletions metrics/src/recorder/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{cell::Cell, ptr::NonNull};
use std::{cell::Cell, ops::Deref, ptr::NonNull, rc::Rc, sync::Arc};

mod cell;
use self::cell::RecorderOnceCell;
Expand Down Expand Up @@ -57,6 +57,95 @@ pub trait Recorder {
fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram;
}

// Blanket implementations.

impl<T> Recorder for Rc<T>
where
T: Recorder,
{
fn describe_counter(&self, key: KeyName, unit: Option<Unit>, description: SharedString) {
Deref::deref(self).describe_counter(key, unit, description)
}

fn describe_gauge(&self, key: KeyName, unit: Option<Unit>, description: SharedString) {
Deref::deref(self).describe_gauge(key, unit, description)
}

fn describe_histogram(&self, key: KeyName, unit: Option<Unit>, description: SharedString) {
Deref::deref(self).describe_histogram(key, unit, description)
}

fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter {
Deref::deref(self).register_counter(key, metadata)
}

fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge {
Deref::deref(self).register_gauge(key, metadata)
}

fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram {
Deref::deref(self).register_histogram(key, metadata)
}
}

impl<T> Recorder for Arc<T>
where
T: Recorder,
{
fn describe_counter(&self, key: KeyName, unit: Option<Unit>, description: SharedString) {
Deref::deref(self).describe_counter(key, unit, description)
}

fn describe_gauge(&self, key: KeyName, unit: Option<Unit>, description: SharedString) {
Deref::deref(self).describe_gauge(key, unit, description)
}

fn describe_histogram(&self, key: KeyName, unit: Option<Unit>, description: SharedString) {
Deref::deref(self).describe_histogram(key, unit, description)
}

fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter {
Deref::deref(self).register_counter(key, metadata)
}

fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge {
Deref::deref(self).register_gauge(key, metadata)
}

fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram {
Deref::deref(self).register_histogram(key, metadata)
}
}

impl<T> Recorder for Box<T>
where
T: Recorder,
{
fn describe_counter(&self, key: KeyName, unit: Option<Unit>, description: SharedString) {
Deref::deref(self).describe_counter(key, unit, description)
}

fn describe_gauge(&self, key: KeyName, unit: Option<Unit>, description: SharedString) {
Deref::deref(self).describe_gauge(key, unit, description)
}

fn describe_histogram(&self, key: KeyName, unit: Option<Unit>, description: SharedString) {
Deref::deref(self).describe_histogram(key, unit, description)
}

fn register_counter(&self, key: &Key, metadata: &Metadata<'_>) -> Counter {
Deref::deref(self).register_counter(key, metadata)
}

fn register_gauge(&self, key: &Key, metadata: &Metadata<'_>) -> Gauge {
Deref::deref(self).register_gauge(key, metadata)
}

fn register_histogram(&self, key: &Key, metadata: &Metadata<'_>) -> Histogram {
Deref::deref(self).register_histogram(key, metadata)
}
}

/// Guard for setting a local recorder.
///
/// When using a local recorder, we take a reference to the recorder and only hold it for as long as
Expand Down Expand Up @@ -142,11 +231,16 @@ pub fn with_recorder<T>(f: impl FnOnce(&dyn Recorder) -> T) -> T {

#[cfg(test)]
mod tests {
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
use std::{
rc::Rc,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
};

use crate::NoopRecorder;

use super::{Recorder, RecorderOnceCell};

#[test]
Expand Down Expand Up @@ -227,4 +321,14 @@ mod tests {
drop(second_set_result);
assert!(was_dropped.load(Ordering::SeqCst));
}

#[test]
fn blanket_implementations() {
fn is_recorder<T: Recorder>(_recorder: T) {}

is_recorder(NoopRecorder);
is_recorder(Rc::new(NoopRecorder));
is_recorder(Arc::new(NoopRecorder));
is_recorder(Box::new(NoopRecorder));
}
}

0 comments on commit 15adb44

Please sign in to comment.