//! 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)] #![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))] use metrics::{Key, KeyData, Label, Recorder, Unit}; use metrics_util::layers::Layer; use tracing::Span; pub mod label_filter; mod tracing_integration; pub use label_filter::LabelFilter; pub use tracing_integration::{Labels, MetricsLayer, SpanExt}; /// [`TracingContextLayer`] provides an implementation of a [`Layer`][metrics_util::layers::Layer] /// for [`TracingContext`]. pub struct TracingContextLayer { label_filter: F, } impl TracingContextLayer { /// Creates a new [`TracingContextLayer`]. pub fn new(label_filter: F) -> Self { Self { label_filter } } } impl TracingContextLayer { /// Creates a new [`TracingContextLayer`]. pub fn all() -> Self { Self { label_filter: label_filter::IncludeAll, } } } impl Layer for TracingContextLayer where F: Clone, { type Output = TracingContext; fn layer(&self, inner: R) -> Self::Output { TracingContext { inner, label_filter: self.label_filter.clone(), } } } /// [`TracingContext`] is a [`metrics::Recorder`] that injects labels from [`tracing::Span`]s. pub struct TracingContext { inner: R, label_filter: F, } impl TracingContext where F: LabelFilter, { fn enhance_labels(&self, labels: &mut Vec