2020-09-26 19:26:39 -07:00
|
|
|
//! Use [`tracing::span!`] fields as [`metrics`] labels.
|
|
|
|
//!
|
|
|
|
//! The `metrics-tracing-context` crate provides tools to enable injecting the
|
|
|
|
//! contextual data maintained via `span!` macro from the [`tracing`] crate
|
|
|
|
//! into the metrics.
|
|
|
|
//!
|
|
|
|
//! # Use
|
|
|
|
//!
|
|
|
|
//! First, set up `tracing` and `metrics` crates:
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! # use metrics_util::DebuggingRecorder;
|
|
|
|
//! # use tracing_subscriber::Registry;
|
|
|
|
//! use metrics_util::layers::Layer;
|
|
|
|
//! use tracing_subscriber::layer::SubscriberExt;
|
|
|
|
//! use metrics_tracing_context::{MetricsLayer, TracingContextLayer};
|
|
|
|
//!
|
|
|
|
//! // Prepare tracing.
|
|
|
|
//! # let mysubscriber = Registry::default();
|
|
|
|
//! let subscriber = mysubscriber.with(MetricsLayer::new());
|
|
|
|
//! tracing::subscriber::set_global_default(subscriber).unwrap();
|
|
|
|
//!
|
|
|
|
//! // Prepare metrics.
|
|
|
|
//! # let myrecorder = DebuggingRecorder::new();
|
|
|
|
//! let recorder = TracingContextLayer::all().layer(myrecorder);
|
|
|
|
//! metrics::set_boxed_recorder(Box::new(recorder)).unwrap();
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! Then emit some metrics within spans and see the labels being injected!
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! # use metrics_util::{layers::Layer, DebuggingRecorder};
|
|
|
|
//! # use tracing_subscriber::{layer::SubscriberExt, Registry};
|
|
|
|
//! # use metrics_tracing_context::{MetricsLayer, TracingContextLayer};
|
|
|
|
//! # let mysubscriber = Registry::default();
|
|
|
|
//! # let subscriber = mysubscriber.with(MetricsLayer::new());
|
|
|
|
//! # tracing::subscriber::set_global_default(subscriber).unwrap();
|
|
|
|
//! # let myrecorder = DebuggingRecorder::new();
|
|
|
|
//! # let recorder = TracingContextLayer::all().layer(myrecorder);
|
|
|
|
//! # metrics::set_boxed_recorder(Box::new(recorder)).unwrap();
|
|
|
|
//! use tracing::{span, Level};
|
|
|
|
//! use metrics::counter;
|
|
|
|
//!
|
|
|
|
//! let user = "ferris";
|
|
|
|
//! let span = span!(Level::TRACE, "login", user);
|
|
|
|
//! let _guard = span.enter();
|
|
|
|
//!
|
|
|
|
//! counter!("login_attempts", 1, "service" => "login_service");
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! The code above will emit a increment for a `login_attempts` counter with
|
|
|
|
//! the following labels:
|
|
|
|
//! - `service=login_service`
|
|
|
|
//! - `user=ferris`
|
|
|
|
#![deny(missing_docs)]
|
2020-10-28 19:51:27 -07:00
|
|
|
#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))]
|
2020-09-26 19:26:39 -07:00
|
|
|
|
2020-10-17 10:10:28 -07:00
|
|
|
use metrics::{Key, KeyData, Label, Recorder, Unit};
|
2020-09-26 19:26:39 -07:00
|
|
|
use metrics_util::layers::Layer;
|
|
|
|
use tracing::Span;
|
|
|
|
|
|
|
|
pub mod label_filter;
|
|
|
|
mod tracing_integration;
|
|
|
|
|
|
|
|
pub use label_filter::LabelFilter;
|
2020-09-27 12:32:10 -07:00
|
|
|
pub use tracing_integration::{Labels, MetricsLayer, SpanExt};
|
2020-09-26 19:26:39 -07:00
|
|
|
|
2020-10-28 19:51:27 -07:00
|
|
|
/// [`TracingContextLayer`] provides an implementation of a [`Layer`][metrics_util::layers::Layer]
|
2020-09-26 19:26:39 -07:00
|
|
|
/// for [`TracingContext`].
|
|
|
|
pub struct TracingContextLayer<F> {
|
|
|
|
label_filter: F,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> TracingContextLayer<F> {
|
|
|
|
/// Creates a new [`TracingContextLayer`].
|
|
|
|
pub fn new(label_filter: F) -> Self {
|
|
|
|
Self { label_filter }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TracingContextLayer<label_filter::IncludeAll> {
|
|
|
|
/// Creates a new [`TracingContextLayer`].
|
|
|
|
pub fn all() -> Self {
|
|
|
|
Self {
|
|
|
|
label_filter: label_filter::IncludeAll,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<R, F> Layer<R> for TracingContextLayer<F>
|
|
|
|
where
|
|
|
|
F: Clone,
|
|
|
|
{
|
|
|
|
type Output = TracingContext<R, F>;
|
|
|
|
|
|
|
|
fn layer(&self, inner: R) -> Self::Output {
|
|
|
|
TracingContext {
|
|
|
|
inner,
|
|
|
|
label_filter: self.label_filter.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-12 20:23:32 -08:00
|
|
|
/// [`TracingContext`] is a [`metrics::Recorder`] that injects labels from[`tracing::Span`]s.
|
2020-09-26 19:26:39 -07:00
|
|
|
pub struct TracingContext<R, F> {
|
|
|
|
inner: R,
|
|
|
|
label_filter: F,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<R, F> TracingContext<R, F>
|
|
|
|
where
|
|
|
|
F: LabelFilter,
|
|
|
|
{
|
|
|
|
fn enhance_labels(&self, labels: &mut Vec<Label>) {
|
|
|
|
let span = Span::current();
|
|
|
|
span.with_labels(|new_labels| {
|
|
|
|
labels.extend(
|
|
|
|
new_labels
|
|
|
|
.iter()
|
|
|
|
.filter(|&label| self.label_filter.should_include_label(label))
|
|
|
|
.cloned(),
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn enhance_key(&self, key: Key) -> Key {
|
|
|
|
let (name, mut labels) = key.into_owned().into_parts();
|
|
|
|
self.enhance_labels(&mut labels);
|
2020-11-15 12:49:05 -08:00
|
|
|
KeyData::from_parts(name, labels).into()
|
2020-09-26 19:26:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<R, F> Recorder for TracingContext<R, F>
|
|
|
|
where
|
|
|
|
R: Recorder,
|
|
|
|
F: LabelFilter,
|
|
|
|
{
|
2020-10-17 10:10:28 -07:00
|
|
|
fn register_counter(&self, key: Key, unit: Option<Unit>, description: Option<&'static str>) {
|
|
|
|
self.inner.register_counter(key, unit, description)
|
2020-09-26 19:26:39 -07:00
|
|
|
}
|
|
|
|
|
2020-10-17 10:10:28 -07:00
|
|
|
fn register_gauge(&self, key: Key, unit: Option<Unit>, description: Option<&'static str>) {
|
|
|
|
self.inner.register_gauge(key, unit, description)
|
2020-09-26 19:26:39 -07:00
|
|
|
}
|
|
|
|
|
2020-10-17 10:10:28 -07:00
|
|
|
fn register_histogram(&self, key: Key, unit: Option<Unit>, description: Option<&'static str>) {
|
|
|
|
self.inner.register_histogram(key, unit, description)
|
2020-09-26 19:26:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn increment_counter(&self, key: Key, value: u64) {
|
|
|
|
let key = self.enhance_key(key);
|
|
|
|
self.inner.increment_counter(key, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn update_gauge(&self, key: Key, value: f64) {
|
|
|
|
let key = self.enhance_key(key);
|
|
|
|
self.inner.update_gauge(key, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn record_histogram(&self, key: Key, value: u64) {
|
|
|
|
let key = self.enhance_key(key);
|
|
|
|
self.inner.record_histogram(key, value);
|
|
|
|
}
|
|
|
|
}
|