### Minimal Setup for Tracing Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Sets up the minimal OpenTelemetry tracing layer with a registry and a tracer. This is the basic configuration required to start emitting traces. ```rust use tracing_opentelemetry::layer; use tracing_subscriber::Registry; let tracer = /* create OpenTelemetry tracer */; let telemetry = layer().with_tracer(tracer); let subscriber = Registry::default().with(telemetry); tracing::subscriber::set_global_default(subscriber).unwrap(); ``` -------------------------------- ### Run Jaeger Collector and Example Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/README.md Instructions to run a Jaeger collector using Docker and then execute an example to produce spans. View the collected traces in the Jaeger UI. ```bash # Run a supported collector like jaeger in the background $ docker run -d -p4317:4317 -p16686:16686 jaegertracing/all-in-one:latest # Run example to produce spans (from parent examples directory) $ cargo run --example opentelemetry-otlp # View spans (see the image below) $ firefox http://localhost:16686/ ``` -------------------------------- ### OTLP/gRPC Exporter Setup Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Configure a tracer for OTLP/gRPC export. Specify the endpoint for the collector. ```rust use opentelemetry_otlp::WithExportConfig; let tracer = opentelemetry_otlp::new_pipeline() .trace() .with_exporter( opentelemetry_otlp::new_exporter() .tonic() .with_endpoint("http://localhost:4317") ) .install_simple() .unwrap(); ``` -------------------------------- ### Quick Start: Initialize OpenTelemetry Layer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/README.md Demonstrates how to set up the OpenTelemetryLayer with a tracer and integrate it into the tracing subscriber. This is the primary method for enabling OpenTelemetry span export. ```rust use tracing_opentelemetry::layer; use tracing_subscriber::Registry; use opentelemetry_sdk::trace::SdkTracerProvider; // Create OpenTelemetry tracer let provider = SdkTracerProvider::builder() .with_simple_exporter(exporter) .build(); let tracer = provider.tracer("my_service"); // Create and configure the layer let telemetry = layer().with_tracer(tracer); // Add to subscriber let subscriber = Registry::default().with(telemetry); tracing::subscriber::set_global_default(subscriber).unwrap(); // Now tracing spans are automatically sent to OpenTelemetry tracing::info_span!("operation").in_scope(|| { // Span sent to OpenTelemetry exporter }); ``` -------------------------------- ### Tracing Setup with Metrics Layer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Integrates a MetricsLayer for collecting metrics alongside tracing data. This requires a meter provider to be set up. ```rust use tracing_opentelemetry::MetricsLayer; let metrics = MetricsLayer::new(meter_provider); let subscriber = Registry::default() .with(layer().with_tracer(tracer)) .with(metrics); ``` -------------------------------- ### Jaeger Exporter Setup Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Set up a tracer using the Jaeger exporter. Ensure the opentelemetry-jaeger crate is included. ```rust use opentelemetry_jaeger; let tracer = opentelemetry_jaeger::new_pipeline() .install_simple() .unwrap(); let telemetry = layer().with_tracer(tracer); ``` -------------------------------- ### Create and Configure OpenTelemetryLayer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Creates a new OpenTelemetryLayer with a configured tracer and integrates it into a tracing subscriber. Requires OpenTelemetry SDK and tracing subscriber setup. ```rust use opentelemetry_sdk::trace::SdkTracerProvider; use opentelemetry::trace::{Tracer, TracerProvider as _}; use tracing_opentelemetry::OpenTelemetryLayer; use tracing_subscriber::Registry; let provider = SdkTracerProvider::builder() .with_simple_exporter(opentelemetry_stdout::SpanExporter::default()) .build(); let tracer = provider.tracer("my_service"); let layer = OpenTelemetryLayer::new(tracer); let subscriber = Registry::default().with(layer); ``` -------------------------------- ### Stdout Exporter Setup for Testing Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Use the stdout exporter for testing purposes. This requires the opentelemetry-sdk crate. ```rust use opentelemetry_sdk::trace::SdkTracerProvider; let provider = SdkTracerProvider::builder() .with_simple_exporter(opentelemetry_stdout::SpanExporter::default()) .build(); let tracer = provider.tracer("test"); ``` -------------------------------- ### Integrate MetricsLayer with Tracing Subscriber Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md This example demonstrates how to set up the MetricsLayer with a global tracing subscriber. It requires creating an SdkMeterProvider and then combining the MetricsLayer with a Registry. Metrics are emitted using tracing events with metric-prefixed fields. ```rust use opentelemetry_sdk::metrics::SdkMeterProvider; use tracing_opentelemetry::MetricsLayer; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::Registry; fn main() { // Create a meter provider with appropriate exporter let meter_provider = SdkMeterProvider::builder() .with_reader(/* configure exporter */) .build(); // Create and register the metrics layer let metrics_layer = MetricsLayer::new(meter_provider); let subscriber = Registry::default().with(metrics_layer); tracing::subscriber::set_global_default(subscriber).unwrap(); // Emit metrics through tracing events tracing::info!( monotonic_counter.requests_total = 1u64, method = "GET", status = 200i64 ); tracing::info!( histogram.request_duration_ms = 125u64, endpoint = "/api/data" ); tracing::info!( gauge.active_connections = 42i64 ); } ``` -------------------------------- ### Multi-Dispatch Scenario with get_otel_context Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/get-otel-context.md Illustrates using get_otel_context in a scenario with multiple subscriber configurations. This example shows how to obtain the default dispatcher and use it within a `with_default` block. ```rust use tracing_opentelemetry::get_otel_context; use tracing::Dispatch; fn handle_multi_dispatch_span() { let dispatch = tracing::dispatcher::get_default(|d| d.clone()); tracing::subscriber::with_default(dispatch, || { let span = tracing::info_span!("operation"); let _guard = span.enter(); // Get the span ID from within the span context span.with_subscriber(|(id, _)| { if let Some(otel_ctx) = get_otel_context(id, &tracing::Dispatch::default()) { // Work with the OpenTelemetry context let otel_span = otel_ctx.span(); println!("Current span context: {:?}", otel_span.span_context()); } }); }); } ``` -------------------------------- ### Tracing Setup with Configuration Options Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Configures the OpenTelemetry tracing layer with additional options like location, level, and tracked inactivity. Use this to customize the detail level of your traces. ```rust let telemetry = layer() .with_tracer(tracer) .with_location(true) .with_level(true) .with_tracked_inactivity(true); ``` -------------------------------- ### OpenTelemetryLayer::layer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Creates a new layer with a no-op tracer that must be configured with `with_tracer()`. This is a convenient factory method for starting layer configuration. ```APIDOC ## OpenTelemetryLayer::layer ### Description Creates a new layer with a no-op tracer that must be configured with `with_tracer()`. ### Returns `OpenTelemetryLayer` ### Example ```rust use tracing_opentelemetry::layer; let layer = layer().with_tracer(my_tracer); ``` ``` -------------------------------- ### Usage Example for SetParentError Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/types.md Demonstrates how to handle `SetParentError` when attempting to set a parent context for a span using `OpenTelemetrySpanExt::set_parent`. ```rust use tracing_opentelemetry::OpenTelemetrySpanExt; let span = tracing::span!(tracing::Level::INFO, "request"); match span.set_parent(parent_context) { Ok(_) => println!("Parent set successfully"), Err(SetParentError::LayerNotFound) => { eprintln!("OpenTelemetry layer not configured"); } Err(SetParentError::AlreadyStarted) => { eprintln!("Cannot set parent after span has started"); } Err(SetParentError::SpanDisabled) => { eprintln!("Span was filtered out"); } } ``` -------------------------------- ### Event Counting and Filtering Example Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/filtered-layer.md Demonstrates how FilteredOpenTelemetryLayer counts all events and selectively records filtered events. All events are counted towards `otel.tracing_event_count`, while only INFO level and above are recorded as OpenTelemetry events. ```rust use tracing_core::LevelFilter; let layer = tracing_opentelemetry::layer() .with_tracer(tracer) .with_counting_event_filter(LevelFilter::INFO); tracing::subscriber::with_default(subscriber, || { let _span = tracing::debug_span!("work"); tracing::trace!("1"); // Filtered out tracing::debug!("2"); // Filtered out tracing::info!("3"); // Recorded tracing::warn!("4"); // Recorded tracing::error!("5"); // Recorded // span will have otel.tracing_event_count = 5 }); ``` -------------------------------- ### Unit Tests for Error Conditions Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/errors.md These are placeholder unit tests for specific error conditions within the crate, such as attempting to set a parent on an already started span or extracting context without a configured layer. ```rust #[test] fn test_set_parent_already_started() { // Tests SetParentError::AlreadyStarted condition } #[test] fn test_context_extraction_without_layer() { // Tests behavior when layer not configured } ``` -------------------------------- ### Extract Context from Current Span Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Gets the OpenTelemetry context from the currently active span. This is a convenient way to access trace information for the span that is currently being executed. ```rust use tracing_opentelemetry::OpenTelemetrySpanExt; let context = tracing::Span::current().context(); ``` -------------------------------- ### Handle Set Parent Span Errors Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Provides a detailed match statement for handling potential errors when setting a span's parent context. This includes cases like the layer not being found or the span already starting. ```rust use tracing_opentelemetry::{OpenTelemetrySpanExt, SetParentError}; match span.set_parent(parent_cx) { Ok(_) => { /* success */ } // Err(SetParentError::LayerNotFound) => { eprintln!("OpenTelemetry layer not configured"); } Err(SetParentError::AlreadyStarted) => { eprintln!("Cannot set parent after span started"); } Err(SetParentError::SpanDisabled) => { eprintln!("Span was filtered out"); } } ``` -------------------------------- ### Create and Configure MetricsLayer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Demonstrates how to create a new MetricsLayer with a meter provider and integrate it into a tracing subscriber. Requires `tracing-opentelemetry` and `tracing-subscriber` crates. ```rust use tracing_opentelemetry::MetricsLayer; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::Registry; use opentelemetry_sdk::metrics::SdkMeterProvider; // Create a meter provider (configuration omitted) let meter_provider = SdkMeterProvider::builder() .with_reader(/* reader configuration */) .build(); let metrics_layer = MetricsLayer::new(meter_provider); let subscriber = Registry::default().with(metrics_layer); tracing::subscriber::set_global_default(subscriber).unwrap(); ``` -------------------------------- ### Initialize MetricsLayer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/configuration.md Demonstrates the initialization of the MetricsLayer when the `metrics` feature is enabled. The layer automatically handles metric creation without requiring explicit configuration options. ```rust let metrics_layer = MetricsLayer::new(meter_provider); ``` -------------------------------- ### Configure Tracing Layer with Builder Pattern Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/configuration.md Demonstrates how to use the builder pattern to configure the tracing-opentelemetry layer with various options. Methods can be called in any order and are chainable. ```rust let layer = tracing_opentelemetry::layer() .with_tracer(tracer) .with_location(true) .with_level(true) .with_tracked_inactivity(true) .with_context_activation(true) .with_error_fields_to_exceptions(true); let subscriber = Registry::default().with(layer); ``` -------------------------------- ### OpenTelemetryLayer::new Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Creates a new OpenTelemetryLayer with a configured tracer. This is the primary constructor for initializing the layer with an OpenTelemetry tracer instance. ```APIDOC ## OpenTelemetryLayer::new ### Description Creates a new OpenTelemetryLayer with a configured tracer. ### Parameters #### Path Parameters - **tracer** (T: Tracer) - Required - The OpenTelemetry tracer instance to use for span creation ### Returns `OpenTelemetryLayer` ### Example ```rust use opentelemetry_sdk::trace::SdkTracerProvider; use opentelemetry::trace::{Tracer, TracerProvider as _}; use tracing_opentelemetry::OpenTelemetryLayer; use tracing_subscriber::Registry; let provider = SdkTracerProvider::builder() .with_simple_exporter(opentelemetry_stdout::SpanExporter::default()) .build(); let tracer = provider.tracer("my_service"); let layer = OpenTelemetryLayer::new(tracer); let subscriber = Registry::default().with(layer); ``` ``` -------------------------------- ### Basic Tracing to Jaeger Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/README.md Set up a global tracing subscriber with a Jaeger tracer. This is useful for basic integration with Jaeger for distributed tracing. ```rust use opentelemetry_jaeger; use tracing_opentelemetry::layer; use tracing_subscriber::Registry; let tracer = opentelemetry_jaeger::new_pipeline() .install_simple() .unwrap(); let telemetry = layer().with_tracer(tracer); let subscriber = Registry::default().with(telemetry); tracing::subscriber::set_global_default(subscriber).unwrap(); ``` -------------------------------- ### Set Parent Early Best Practice Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/errors.md Demonstrates the best practice of setting the parent context for a span immediately after its creation and before entering the span. ```rust let span = tracing::span!(tracing::Level::INFO, "operation"); let _ = span.set_parent(parent_cx); // Immediately after creation let _guard = span.enter(); // Then enter the span ``` -------------------------------- ### Integer Type Handling and Conversion for Metrics Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Shows how integers are handled for metrics, including automatic `i64` conversion and explicit `u64` casting. Demonstrates potential overflow issues when `u64` exceeds `i64::MAX`. ```rust // Automatic i64 handling info!(counter.value = 1); // Received as i64 info!(counter.value = -1); // Received as i64 // Explicit u64 conversion info!(counter.value = 1_u64); // Received as u64, converted to i64 // Overflow handling info!(counter.value = (i64::MAX as u64) + 1); // Error: value too large ``` -------------------------------- ### Create OpenTelemetryLayer with No-Op Tracer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Creates a new OpenTelemetryLayer using a no-op tracer. The tracer must be configured later using the `with_tracer()` method. ```rust use tracing_opentelemetry::layer; let layer = layer().with_tracer(my_tracer); ``` -------------------------------- ### Configure Span with Special Fields Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/configuration.md Shows how to configure individual spans using special fields like `otel.name`, `otel.kind`, `otel.status_code`, and `otel.status_description` for OpenTelemetry integration. ```rust use tracing::span; let _span = span!( tracing::Level::INFO, "http_request", otel.kind = "server", otel.name = format!("{} {}", method, path).as_str(), ); ``` -------------------------------- ### Emitting Metrics with Prefixes Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Demonstrates how to emit different types of OpenTelemetry metrics using tracing events by applying specific prefixes to field names. ```APIDOC ## Metric Types Metrics are emitted by adding specially-prefixed fields to tracing events. The layer recognizes four metric prefixes: ### Monotonic Counter (`monotonic_counter.`) Non-negative integers that only increase. **Type Requirements:** `u64` or `f64` **Example:** ```rust use tracing::info; info!(monotonic_counter.requests_total = 1u64); info!(monotonic_counter.bytes_processed = 1024.5_f64); ``` ### Counter (`counter.`) Values that can increase or decrease. **Type Requirements:** `i64` or `f64` **Example:** ```rust use tracing::info; info!(counter.active_connections = 5i64); info!(counter.temperature = 72.5_f64); ``` ### Histogram (`histogram.`) Arbitrary values for statistical analysis. **Type Requirements:** `u64` or `f64` **Example:** ```rust use tracing::info; info!(histogram.response_time_ms = 250u64); info!(histogram.latency = 0.125_f64); ``` ### Gauge (`gauge.`) Instantaneous values that can go up or down. **Type Requirements:** `u64`, `i64`, or `f64` **Example:** ```rust use tracing::info; info!(gauge.memory_usage = 512_000_000u64); info!(gauge.cpu_percent = 45.2_f64); info!(gauge.queue_depth = 10i64); ``` ``` -------------------------------- ### OTLP Tracing with gRPC Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/README.md Configure tracing to export data using OTLP over gRPC to a specified endpoint. This is suitable for modern observability backends. ```rust use opentelemetry_otlp::WithExportConfig; use tracing_opentelemetry::layer; let tracer = opentelemetry_otlp::new_pipeline() .trace() .with_exporter( opentelemetry_otlp::new_exporter() .tonic() .with_endpoint("http://localhost:4317") ) .install_simple() .unwrap(); let telemetry = layer().with_tracer(tracer); ``` -------------------------------- ### Metrics Export with MetricsLayer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/README.md Set up a tracing subscriber with MetricsLayer to export metrics using an OpenTelemetry meter provider. This allows collecting and exporting application metrics. ```rust use tracing_opentelemetry::MetricsLayer; let meter_provider = opentelemetry_sdk::metrics::SdkMeterProvider::builder() .build(); let metrics = MetricsLayer::new(meter_provider); let subscriber = Registry::default().with(metrics); tracing::info!(monotonic_counter.requests = 1u64, method = "GET"); ``` -------------------------------- ### Correct Floating-Point Type Handling for Metrics Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Illustrates the correct way to handle floating-point numbers for metrics, ensuring consistency by casting all values to the same floating-point type (e.g., `f64`) to avoid type mismatches. ```rust info!(monotonic_counter.foo = 1_f64); info!(monotonic_counter.foo = 1.5); ``` -------------------------------- ### MetricsLayer Constructor Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Creates a new MetricsLayer with a configured OpenTelemetry meter provider. This layer enables the emission of metrics from tracing events. ```APIDOC ## `fn new(meter_provider: M) -> MetricsLayer` ### Description Creates a new MetricsLayer with a configured meter provider. The layer internally creates a meter with the instrumentation scope `tracing/tracing-opentelemetry` and the crate version. Metrics are created lazily when first emitted. ### Parameters #### Path Parameters * None #### Query Parameters * None #### Request Body * None ### Parameters - **meter_provider** (`M: MeterProvider`) - Required - The OpenTelemetry meter provider to use for metric creation ### Returns - `MetricsLayer` ### Example ```rust use tracing_opentelemetry::MetricsLayer; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::Registry; use opentelemetry_sdk::metrics::SdkMeterProvider; // Create a meter provider (configuration omitted) let meter_provider = SdkMeterProvider::builder() .with_reader(/* reader configuration */) .build(); let metrics_layer = MetricsLayer::new(meter_provider); let subscriber = Registry::default().with(metrics_layer); tracing::subscriber::set_global_default(subscriber).unwrap(); ``` ``` -------------------------------- ### Configure Tracer for OpenTelemetryLayer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Sets a specific OpenTelemetry tracer instance for the OpenTelemetryLayer. This is used after creating a layer with a no-op tracer. ```rust let layer = tracing_opentelemetry::layer() .with_tracer(my_configured_tracer); ``` -------------------------------- ### Integer Handling for Counters Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Shows how to handle integer values for counters, including negative values and potential overflows. Uses checked_add for safety. ```rust // All these work for counter (values can be negative) info!(counter.delta = 1); // i64 info!(counter.delta = -1); // i64 info!(counter.delta = 1_u64); // u64 -> i64 // Overflow handling if let Some(val) = (i64::MAX as u64).checked_add(1) { // Metric dropped with stderr message info!(counter.big = val); } ``` -------------------------------- ### Configure Production Layer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md This configuration is suitable for production, including error field and event settings. ```rust let layer = layer() .with_tracer(tracer) .with_location(true) .with_threads(true) .with_error_fields_to_exceptions(true) .with_error_events_to_status(true); ``` -------------------------------- ### Basic Usage of get_otel_context Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/get-otel-context.md Demonstrates how to retrieve and use the OpenTelemetry context for a given span ID. Ensure the OpenTelemetryLayer is configured and avoid holding mutable span extensions when calling this function. ```rust use tracing_opentelemetry::get_otel_context; use tracing::dispatcher::WeakDispatch; use tracing_subscriber::registry::LookupSpan; use opentelemetry::trace::TraceContextExt; fn process_span_context<'a, D>( span_ref: &tracing_subscriber::registry::SpanRef<'a, D>, weak_dispatch: &WeakDispatch, ) where D: LookupSpan<'a>, { if let Some(dispatch) = weak_dispatch.upgrade() { // Do NOT hold ExtensionsMut when calling this if let Some(otel_context) = get_otel_context(&span_ref.id(), &dispatch) { let span = otel_context.span(); let span_context = span.span_context(); if span_context.is_valid() { println!( "Trace ID: {}, Span ID: 123", span_context.trace_id(), span_context.span_id() ); } } } } ``` -------------------------------- ### Silent No-Op for Missing OpenTelemetryLayer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/errors.md Illustrates how OpenTelemetrySpanExt methods silently succeed (no-op) when the OpenTelemetryLayer is not configured in the subscriber. This prevents panics and allows graceful degradation. ```rust self.with_subscriber(|(id, subscriber)| { let Some(get_context) = subscriber.downcast_ref::() else { return; // Silent no-op if layer not found }; // ... proceed with operation }); ``` -------------------------------- ### Emit Gauge Metric Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Shows how to emit a gauge metric with the `gauge.` prefix, representing instantaneous values. Supports `u64`, `i64`, or `f64` types. ```rust use tracing::info; info!(gauge.memory_usage = 512_000_000u64); info!(gauge.cpu_percent = 45.2_f64); info!(gauge.queue_depth = 10i64); ``` -------------------------------- ### Type Handling for Metrics Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Provides guidance on handling floating-point and integer types when emitting metrics to avoid type mismatches and understand overflow behavior. ```APIDOC ## Type Handling ### Floating-Point Numbers Do not mix floating-point and non-floating-point numbers for the same metric name. If a metric uses floating-point, cast all values to the same floating-point type. **Correct:** ```rust info!(monotonic_counter.foo = 1_f64); info!(monotonic_counter.foo = 1.5); ``` **Incorrect:** ```rust info!(monotonic_counter.foo = 1); // i64 info!(monotonic_counter.foo = 1.5); // f64 - type mismatch! ``` ### Integers Positive and negative integers can be mixed freely. All integers are `i64` by default unless explicitly cast to `u64`. **Type Conversion Example:** ```rust // Automatic i64 handling info!(counter.value = 1); // Received as i64 info!(counter.value = -1); // Received as i64 // Explicit u64 conversion info!(counter.value = 1_u64); // Received as u64, converted to i64 // Overflow handling info!(counter.value = (i64::MAX as u64) + 1); // Error: value too large ``` When a `u64` value exceeds `i64::MAX`, an error is printed to stderr and the metric is discarded. ``` -------------------------------- ### Emit Counter Metric Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Demonstrates emitting a counter metric with the `counter.` prefix. Supports `i64` or `f64` types, allowing for both positive and negative values. ```rust use tracing::info; info!(counter.active_connections = 5i64); info!(counter.temperature = 72.5_f64); ``` -------------------------------- ### Full Diagnostic Configuration Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/configuration.md Enables all available diagnostic features for maximum detail, including location, level, target, timing, threads, and comprehensive error handling. ```rust let layer = layer() .with_tracer(tracer) .with_location(true) .with_level(true) .with_target(true) .with_tracked_inactivity(true) .with_threads(true) .with_error_fields_to_exceptions(true) .with_error_records_to_exceptions(true) .with_error_events_to_exceptions(true) .with_error_events_to_status(true); ``` -------------------------------- ### WithContext Struct Definition Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/types.md Internal callback interface for downcasting to the OpenTelemetryLayer, enabling extension traits to interact with the layer. ```rust pub(crate) struct WithContext { pub(crate) with_context: fn(&tracing::Dispatch, &span::Id, f: &mut dyn FnMut(&mut OtelData)), pub(crate) with_activated_context: fn(&tracing::Dispatch, &span::Id, f: &mut dyn FnMut(&mut OtelData)), pub(crate) with_activated_otel_context: fn(&tracing::Dispatch, &span::Id, f: &mut dyn FnMut(&OtelContext)), } ``` -------------------------------- ### Configure High-Volume Logging Layer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Optimize for high-volume logging by using a counting event filter with a specified level. ```rust use tracing_core::LevelFilter; let layer = layer() .with_tracer(tracer) .with_counting_event_filter(LevelFilter::INFO); ``` -------------------------------- ### Emit Monotonic Counter Metric Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Shows how to emit a monotonic counter metric using the `monotonic_counter.` prefix in a tracing event. Supports `u64` or `f64` types. ```rust use tracing::info; info!(monotonic_counter.requests_total = 1u64); info!(monotonic_counter.bytes_processed = 1024.5_f64); ``` -------------------------------- ### Emit Metrics with Attributes Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Demonstrates adding attributes (like method, status, endpoint) to tracing events to enrich emitted metrics. These attributes become dimensions on the OpenTelemetry metrics. ```rust use tracing::info; // Metrics with attributes info!( monotonic_counter.http_requests = 1u64, method = "GET", status = 200i64, endpoint = "/api/users" ); info!( histogram.request_duration_ms = 125u64, service = "auth-service", operation = "login" ); ``` -------------------------------- ### Handling AlreadyStarted Error during set_parent Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/errors.md Demonstrates scenarios that lead to the AlreadyStarted error when calling set_parent, such as entering the span or accessing its context first. Always set the parent immediately upon span creation to avoid this. ```rust use tracing_opentelemetry::OpenTelemetrySpanExt; let span = tracing::span!(tracing::Level::INFO, "request"); // Good: set parent immediately span.set_parent(parent_cx)?; // Bad: enter first, then set parent let _guard = span.enter(); span.set_parent(parent_cx)?; // Returns AlreadyStarted // Also bad: access context first let ctx = span.context(); span.set_parent(parent_cx)?; // Returns AlreadyStarted ``` ```rust let span = tracing::span!(tracing::Level::INFO, "request"); // Set parent immediately upon span creation if let Err(e) = span.set_parent(parent_cx) { eprintln!("Failed to set parent: {}", e); // Continue with no parent context } // Now safe to use the span let _guard = span.enter(); ``` -------------------------------- ### OpenTelemetryLayer::with_tracer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Sets the tracer for this layer. This builder method is used to provide the OpenTelemetry tracer instance to the layer. ```APIDOC ## OpenTelemetryLayer::with_tracer ### Description Sets the tracer for this layer. ### Parameters #### Path Parameters - **tracer** (Tracer: Tracer) - Required - The OpenTelemetry tracer instance ### Returns `OpenTelemetryLayer` - New layer with the provided tracer ### Example ```rust let layer = tracing_opentelemetry::layer() .with_tracer(my_configured_tracer); ``` ``` -------------------------------- ### Configure Context Activation Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Control whether OpenTelemetry context is activated upon entering a span. This is crucial for ensuring proper context propagation across different instrumentation. ```rust let layer = tracing_opentelemetry::layer() .with_tracer(tracer) .with_context_activation(true); ``` -------------------------------- ### Avoid Deadlocks When Accessing Span Extensions Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/get-otel-context.md Demonstrates the correct way to access span extensions before calling `get_otel_context` to prevent deadlocks. Ensure any mutable access to extensions is dropped before calling the function. ```rust // BAD - Will deadlock let mut ext = span.extensions_mut(); let ctx = get_otel_context(&span_id, &dispatch); // Deadlock! // GOOD - Drop the lock first { let mut ext = span.extensions_mut(); // ... use ext ... } let ctx = get_otel_context(&span_id, &dispatch); // Safe ``` -------------------------------- ### with_context_activation Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Controls whether OpenTelemetry context is activated when entering a span. When enabled, entering a span will activate its OpenTelemetry context, making it available to other OpenTelemetry instrumentation for proper context propagation. ```APIDOC ## with_context_activation ### Description Controls whether OpenTelemetry context is activated when entering a span. ### Method `fn with_context_activation(self, context_activation: bool) -> Self` ### Parameters #### Path Parameters - **context_activation** (bool) - Required - Activate OTel context on span entry ### Returns `Self` ### Details When enabled, entering a span will activate its OpenTelemetry context, making it available to other OpenTelemetry instrumentation for proper context propagation. ### Example ```rust let layer = tracing_opentelemetry::layer() .with_tracer(tracer) .with_context_activation(true); ``` ``` -------------------------------- ### Configure Debugging Layer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Use this configuration for debugging purposes, enabling location, level, and tracked inactivity. ```rust let layer = layer() .with_tracer(tracer) .with_location(true) .with_level(true) .with_tracked_inactivity(true) .with_threads(true); ``` -------------------------------- ### Handle Metric Value Overflow Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/errors.md This snippet demonstrates how the crate handles `u64` metric values that exceed `i64::MAX`. Metrics exceeding this limit are dropped, and an error message is printed to stderr. ```rust if value <= I64_MAX { self.visited_metrics .push((metric_name, InstrumentType::UpDownCounterI64(value as i64))); } else { eprintln!( "[tracing-opentelemetry]: Received Counter metric, but " "provided u64: {value} is greater than i64::MAX. Ignoring " "this metric." ); } ``` -------------------------------- ### Combine Filtered Layer with Console Layer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/filtered-layer.md This snippet shows how to combine the filtered OpenTelemetry layer with a console formatting layer using `tracing_subscriber`'s `prelude`. This allows for both OpenTelemetry export and local console logging. ```rust use tracing_subscriber::prelude::*; use tracing_subscriber::fmt; let subscriber = tracing_subscriber::registry() .with( tracing_opentelemetry::layer() .with_tracer(tracer) .with_counting_event_filter(LevelFilter::INFO) ) .with(fmt::layer()); // Also output to console tracing::subscriber::set_global_default(subscriber).unwrap(); ``` -------------------------------- ### Async Task Tracking Pattern Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Tracks asynchronous background tasks by setting the parent context of a new span. Requires OpenTelemetrySpanExt. ```rust use tracing_opentelemetry::OpenTelemetrySpanExt; async fn background_task(parent_ctx: opentelemetry::Context) { let span = tracing::info_span!("background_task"); let _ = span.set_parent(parent_ctx); span.in_scope(|| { // Task execution with proper tracing }).await; } ``` -------------------------------- ### Distributed Tracing with Parent Context Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/README.md Extract a parent OpenTelemetry context from request headers and set it on a new span. This enables distributed tracing across services. ```rust use opentelemetry::propagation::TextMapPropagator; use tracing_opentelemetry::OpenTelemetrySpanExt; // Extract parent context from request headers let propagator = opentelemetry_jaeger::Propagator::new(); let parent_ctx = propagator.extract(&request_headers); // Create span and set parent let span = tracing::info_span!("request_handler"); let _ = span.set_parent(parent_ctx); span.in_scope(|| { // Request handling }); ``` -------------------------------- ### High Performance Tracing Configuration Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Configures the tracing layer for high performance by disabling location, tracked inactivity, threads, and target information. Use this when performance is critical and detailed metadata is not required. ```rust let layer = layer() .with_tracer(tracer) .with_location(false) .with_tracked_inactivity(false) .with_threads(false) .with_target(false); ``` -------------------------------- ### Create Span with Special OpenTelemetry Fields Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Creates a tracing span and overrides OpenTelemetry-specific attributes like span kind and name using special fields. This allows for fine-grained control over how spans are reported. ```rust use tracing::span; let _span = span!( tracing::Level::INFO, "request", otel.kind = "server", otel.name = format!("GET {}", path).as_str() ); ``` -------------------------------- ### Emit Histogram Metric Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md Illustrates emitting a histogram metric using the `histogram.` prefix. Suitable for statistical analysis and supports `u64` or `f64` types. ```rust use tracing::info; info!(histogram.response_time_ms = 250u64); info!(histogram.latency = 0.125_f64); ``` -------------------------------- ### Error Handling Pattern for SetParentError Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/errors.md Demonstrates a general pattern for handling SetParentError using Rust's Result and the Error trait. This allows for flexible error management. ```rust use tracing_opentelemetry::OpenTelemetrySpanExt; use std::error::Error; fn handle_parent_setting(span: &tracing::Span, parent: opentelemetry::Context) -> Result<(), Box> { span.set_parent(parent)?; Ok(()) } ``` -------------------------------- ### Re-exports from tracing-opentelemetry Crate Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/README.md Shows the main public components re-exported by the crate for external use. This includes layers for tracing and metrics, context extraction, and span extension traits. ```rust pub use layer::{layer, FilteredOpenTelemetryLayer, OpenTelemetryLayer}; pub use metrics::MetricsLayer; // Feature-gated pub use otel_context::get_otel_context; pub use span_ext::{OpenTelemetrySpanExt, SetParentError}; ``` -------------------------------- ### Construct FilteredOpenTelemetryLayer with a Filter Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/filtered-layer.md Use this method to wrap an existing OpenTelemetryLayer with a filter. It counts all events reaching the span and records only those that pass the filter as OpenTelemetry span events. This is useful for managing high-volume logging. ```rust use tracing_core::LevelFilter; use tracing_opentelemetry::layer; use tracing_subscriber::Registry; let layer = layer() .with_tracer(my_tracer) .with_counting_event_filter(LevelFilter::INFO); let subscriber = Registry::default().with(layer); ``` -------------------------------- ### Extract and Inject Span Context Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Extracts the current span's context and demonstrates injecting it into headers using a propagator. This is useful for distributed tracing across services. ```rust use tracing_opentelemetry::OpenTelemetrySpanExt; use opentelemetry::propagation::TextMapPropagator; let span = tracing::span!(tracing::Level::INFO, "request"); let context = span.context(); // Inject into headers let propagator = TraceContextPropagator::new(); let mut headers = HashMap::new(); propagator.inject_context(&context, &mut headers); ``` -------------------------------- ### Avoid Reentrancy in Span Extension Methods Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/errors.md Demonstrates a scenario to avoid: emitting tracing events from within span extension methods. This can lead to deadlocks and events being ignored. ```rust // Bad: reentrancy span.with_subscriber(|(id, _)| { tracing::info!("event"); // Will be ignored to prevent deadlock }); ``` -------------------------------- ### Set OpenTelemetry Tracer Instance Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/configuration.md Sets the OpenTelemetry Tracer instance used to create spans. Defaults to a no-op tracer if the `layer()` constructor is used without this method. ```rust let tracer = provider.tracer("my_service"); let layer = tracing_opentelemetry::layer().with_tracer(tracer); ``` -------------------------------- ### Display Implementation for SetParentError Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/types.md Provides a human-readable string representation for each variant of `SetParentError`. ```rust impl fmt::Display for SetParentError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { SetParentError::LayerNotFound => { write!(f, "OpenTelemetry layer not found") } SetParentError::AlreadyStarted => { write!(f, "Span has already been started, cannot set parent") } SetParentError::SpanDisabled => { write!(f, "Span disabled") } } } } ``` -------------------------------- ### Recovery for SetParentError::LayerNotFound Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/errors.md Handles the case where the OpenTelemetryLayer is not found when calling set_parent. It logs a warning and continues without distributed tracing. ```rust use tracing_opentelemetry::OpenTelemetrySpanExt; match span.set_parent(parent_cx) { Err(SetParentError::LayerNotFound) => { // Warn and continue without parent context eprintln!("OpenTelemetry layer not found, continuing without distributed tracing"); } _ => {} // Handle other potential errors or success } ``` -------------------------------- ### Map Errors to Exceptions on Span Creation Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/opentelemetry-layer.md Configure whether Error values recorded during span creation are mapped to OpenTelemetry exception attributes. This helps in standardizing error reporting. ```rust let layer = tracing_opentelemetry::layer() .with_tracer(tracer) .with_error_fields_to_exceptions(true); ``` -------------------------------- ### Extracting Trace IDs for Logging Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/get-otel-context.md Shows how to extract the trace ID from the current span's OpenTelemetry context to include in log messages. This requires accessing the current dispatcher and span. ```rust use tracing_opentelemetry::get_otel_context; use opentelemetry::trace::TraceContextExt; fn log_with_trace_id(message: &str) { let dispatch = tracing::Dispatch::current(); tracing::Span::current().with_subscriber(|(id, _)| { if let Some(otel_ctx) = get_otel_context(id, &dispatch) { let trace_id = otel_ctx.span().span_context().trace_id(); println!("[trace_id={}] {}", trace_id, message); } }); } ``` -------------------------------- ### Propagate OpenTelemetry Context to Worker Threads Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/get-otel-context.md Injects the current span's OpenTelemetry context into a HashMap for propagation to a worker thread. Ensure the OpenTelemetryLayer is configured in your subscriber. ```rust use tracing_opentelemetry::get_otel_context; use opentelemetry::propagation::TextMapPropagator; fn propagate_context_to_worker(worker_id: u32) { let dispatch = tracing::Dispatch::current(); tracing::Span::current().with_subscriber(|(id, _)| { if let Some(otel_ctx) = get_otel_context(id, &dispatch) { // Inject context for worker thread let propagator = opentelemetry_jaeger::Propagator::new(); let mut headers = std::collections::HashMap::new(); propagator.inject_context(&otel_ctx, &mut headers); // Pass headers to worker submit_work_with_context(worker_id, headers); } }); } fn submit_work_with_context(id: u32, context: std::collections::HashMap) { // Send to worker thread/process println!("Worker {} context: {:?}", id, context); } ``` -------------------------------- ### Emit Metric with Attributes Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/quick-reference.md Emits a metric along with associated attributes to provide context. This allows filtering and grouping metrics by dimensions like HTTP method or status code. ```rust info( monotonic_counter.http_requests = 1u64, method = "GET", status = 200i64, endpoint = "/api/users" ); ``` -------------------------------- ### Maintain Type Consistency for Metrics Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/errors.md Illustrates the importance of using consistent types for the same metric name. Using mixed types (e.g., `u64` and `f64`) for `monotonic_counter.requests` is considered bad practice. ```rust // Good: consistent types tracing::info!(monotonic_counter.requests = 1_f64); tracing::info!(monotonic_counter.requests = 1.5_f64); // Bad: mixed types tracing::info!(monotonic_counter.requests = 1_u64); // u64 tracing::info!(monotonic_counter.requests = 1.5_f64); // f64 ``` -------------------------------- ### Apply Level Filtering to MetricsLayer Source: https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/_autodocs/api-reference/metrics-layer.md This snippet shows how to apply additional filtering to the MetricsLayer using `LevelFilter`. This ensures that only events at the specified level (e.g., INFO) and above are processed by the metrics layer, reducing overhead. ```rust use tracing_core::LevelFilter; use tracing_opentelemetry::MetricsLayer; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::prelude::*; // Required for .with() let metrics_layer = MetricsLayer::new(meter_provider) .with_filter(LevelFilter::INFO); // Only INFO and above let subscriber = Registry::default().with(metrics_layer); ```