Crate metrics_tracing_context[−][src]
Expand description
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.
Usage
First, set up tracing
and metrics
crates:
use metrics_util::layers::Layer; use tracing_subscriber::layer::SubscriberExt; use metrics_tracing_context::{MetricsLayer, TracingContextLayer}; // Prepare tracing. let subscriber = my_subscriber.with(MetricsLayer::new()); tracing::subscriber::set_global_default(subscriber).unwrap(); // Prepare metrics. let recorder = TracingContextLayer::all().layer(my_recorder); metrics::set_boxed_recorder(Box::new(recorder)).unwrap();
Then emit some metrics within spans and see the labels being injected!
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
Implementation
The integration layer works by capturing all fields present when a span is created and storing them as an extension to the span. If a metric is emitted while a span is entered, we check that span to see if it has any fields in the extension data, and if it does, we add those fields as labels to the metric key.
There are two important behaviors to be aware of:
- we only capture the fields present when the span is created
- we store all fields that a span has, including the fields of its parent span(s)
Lack of dynamism
This means that if you use Span::record
to add fields to a span after
it has been created, those fields will not be captured and added to your metric key.
Span fields and ancestry
Likewise, we capture the sum of all fields for a span and its parent span(s), meaning that if you have the following span stack:
root span (fieldA => valueA) ⤷ mid-tier span (fieldB => valueB) ⤷ leaf span (fieldC => valueC)
Then a metric emitted while within the leaf span would get, as labels, all three fields: A, B, and C. As well, this layer does not deduplicate the fields. If you have two instance of the same field name, both versions will be included in your metric labels. Whether or not those are deduplicated, and how they’re deduplicated, is an exporter-specific implementation detail.
In addition, for performance purposes, span fields are held in pooled storage, and additionally will copy the fields of parent spans. Following the example span stack from above, the mid-tier span would hold both field A and B, while the leaf span would hold fields A, B, and C.
In practice, these extra memory consumption used by these techniques should not matter for modern systems, but may represent an unacceptable amount of memory usage on constrained systems such as embedded platforms, etc.
Re-exports
pub use label_filter::LabelFilter;
Modules
Label filtering.
Structs
MetricsLayer
is a tracing_subscriber::Layer
that captures the span
fields and allows them to be later on used as metrics labels.
TracingContext
is a metrics::Recorder
that injects labels from tracing::Span
s.
TracingContextLayer
provides an implementation of a Layer
for TracingContext
.