Module metrics_util::layers
source · Expand description
Layers are composable helpers that can be “layered” on top of an existing Recorder
to enhance
or alter its behavior as desired, without having to change the recorder implementation itself.
As well, Stack
can be used to easily compose multiple layers together and provides a
convenience method for installing it as the global recorder, providing a smooth transition from
working directly with installing exporters to installing stacks.
Here’s an example of a layer that filters out all metrics that start with a specific string:
// A simple layer that denies any metrics that have "stairway" or "heaven" in their name.
#[derive(Default)]
pub struct StairwayDeny<R>(pub(crate) R);
impl<R> StairwayDeny<R> {
fn is_invalid_key(&self, key: &str) -> bool {
key.contains("stairway") || key.contains("heaven")
}
}
impl<R: Recorder> Recorder for StairwayDeny<R> {
fn describe_counter(
&self,
key_name: KeyName,
unit: Option<Unit>,
description: &'static str,
) {
if self.is_invalid_key(key_name.as_str()) {
return;
}
self.0.describe_counter(key_name, unit, description)
}
fn describe_gauge(&self, key_name: KeyName, unit: Option<Unit>, description: &'static str) {
if self.is_invalid_key(key_name.as_str()) {
return;
}
self.0.describe_gauge(key_name, unit, description)
}
fn describe_histogram(
&self,
key_name: KeyName,
unit: Option<Unit>,
description: &'static str,
) {
if self.is_invalid_key(key_name.as_str()) {
return;
}
self.0.describe_histogram(key_name, unit, description)
}
fn register_counter(&self, key: &Key) -> Counter {
if self.is_invalid_key(key.name()) {
return Counter::noop();
}
self.0.register_counter(key)
}
fn register_gauge(&self, key: &Key) -> Gauge {
if self.is_invalid_key(key.name()) {
return Gauge::noop();
}
self.0.register_gauge(key)
}
fn register_histogram(&self, key: &Key) -> Histogram {
if self.is_invalid_key(key.name()) {
return Histogram::noop();
}
self.0.register_histogram(key)
}
}
#[derive(Default)]
pub struct StairwayDenyLayer;
impl<R> Layer<R> for StairwayDenyLayer {
type Output = StairwayDeny<R>;
fn layer(&self, inner: R) -> Self::Output {
StairwayDeny(inner)
}
}
// Now you can construct an instance of it to use it. The layer will be wrapped around
// our base recorder, which is a debugging recorder also supplied by `metrics_util`.
let recorder = BasicRecorder;
let layer = StairwayDenyLayer::default();
let layered = layer.layer(recorder);
metrics::set_boxed_recorder(Box::new(layered)).expect("failed to install recorder");
// Working with layers directly is a bit cumbersome, though, so let's use a `Stack`.
let stack = Stack::new(BasicRecorder);
stack.push(StairwayDenyLayer::default()).install().expect("failed to install stack");
// `Stack` makes it easy to chain layers together, as well.
let stack = Stack::new(BasicRecorder);
stack
.push(PrefixLayer::new("app_name"))
.push(StairwayDenyLayer::default())
.install()
.expect("failed to install stack");
Structs
- Fans out metrics to multiple recorders.
- A layer for fanning out metrics to multiple recorders.
- Applies a prefix to every metric key.
- A layer for applying a prefix to every metric key.
- Builder for composing layers together in a top-down/inside-out order.
Traits
- Decorates an object by wrapping it within another type.