opentelemetry_appender_tracing/
lib.rs

1//! # OpenTelemetry-Appender-Tracing
2//!
3//! This crate provides a bridge between the [`tracing`](https://docs.rs/tracing/latest/tracing/) crate and OpenTelemetry logs.
4//! It converts `tracing` events into OpenTelemetry `LogRecords`, allowing applications using `tracing` to seamlessly integrate
5//! with OpenTelemetry logging backends.
6//!
7//! ## Background
8//!
9//! Unlike traces and metrics, OpenTelemetry does not provide a dedicated logging API for end-users. Instead, it recommends using
10//! existing logging libraries and bridging them to OpenTelemetry logs. This crate serves as such a bridge for `tracing` users.
11//!
12//! ## Features
13//!
14//! - Converts `tracing` events into OpenTelemetry [`LogRecords`](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#log-and-event-record-definition)
15//! - Integrates as a [`Layer`](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/trait.Layer.html)
16//!   from [`tracing-subscriber`](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/), allowing
17//!   to be used alongside other `tracing` layers, such as `fmt`
18//! - Automatically attaches OpenTelemetry trace context (`TraceId`, `SpanId`, `TraceFlags`) to logs
19//! - Automatically associates OpenTelemetry Resource to logs
20//! - Supports exporting logs to OpenTelemetry-compatible backends (OTLP, stdout, etc.)
21//!
22//! ## Getting Started
23//!
24//! ### 1. Install Dependencies
25//!
26//! Add the following dependencies to your `Cargo.toml`:
27//!
28//! ```toml
29//! [dependencies]
30//! tracing = ">=0.1.40"
31//! tracing-core = { version = ">=0.1.33" }
32//! tracing-subscriber = { version = "0.3", features = ["registry", "std", "fmt"] }
33//! opentelemetry = { version = "0.31", features = ["logs"] }
34//! opentelemetry-sdk = { version = "0.31", features = ["logs"] }
35//! opentelemetry-appender-tracing = { version = "0.31.1" }
36//! ```
37//!
38//! ### 2. Set Up the OpenTelemetry Logger Provider
39//!
40//! Before integrating with `tracing`, create an OpenTelemetry [`SdkLoggerProvider`](https://docs.rs/opentelemetry_sdk/latest/opentelemetry_sdk/logs/struct.SdkLoggerProvider.html):
41//!
42//! ```rust
43//! use opentelemetry_sdk::logs::SdkLoggerProvider;
44//! use opentelemetry_stdout::LogExporter;
45//!
46//! let exporter = LogExporter::default();
47//! let provider = SdkLoggerProvider::builder()
48//!     .with_simple_exporter(exporter)
49//!     .build();
50//! ```
51//!
52//! In this example, `SdkLoggerProvider` is configured to use the `opentelemetry_stdout` crate to export logs to stdout. You can replace it with any other OpenTelemetry-compatible exporter.
53//! Any additional OpenTelemetry configuration (e.g., setting up a resource, additional processors etc.) can be done at this stage.
54//!
55//! ### 3. Create the OpenTelemetry-Tracing Bridge
56//!
57//! Create `OpenTelemetryTracingBridge` layer using the `SdkLoggerProvider` created in the previous step.
58//!
59//! ```rust
60//! # use opentelemetry_sdk::logs::SdkLoggerProvider;
61//! # use opentelemetry_stdout::LogExporter;
62//! # use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
63//! # let exporter = LogExporter::default();
64//! # let provider = SdkLoggerProvider::builder()
65//! #    .with_simple_exporter(exporter)
66//! #    .build();
67//! let otel_layer = OpenTelemetryTracingBridge::new(&provider);
68//! ```
69//!
70//! ### 4. Register the `tracing` Subscriber
71//!
72//! Since this crate provides a `Layer` for `tracing`, you can register it with the `tracing` subscriber as shown below.
73//!
74//! ```rust
75//! # use opentelemetry_sdk::logs::SdkLoggerProvider;
76//! # use opentelemetry_stdout::LogExporter;
77//! # let exporter = LogExporter::default();
78//! # let provider = SdkLoggerProvider::builder().with_simple_exporter(exporter).build();
79//! # use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
80//! # let otel_layer = OpenTelemetryTracingBridge::new(&provider);
81//! use tracing_subscriber::prelude::*;
82//!
83//! tracing_subscriber::registry()
84//!     .with(otel_layer)
85//!     .with(tracing_subscriber::fmt::layer()) // In this example, `fmt` layer is also added.
86//!     .init();
87//! ```
88//!
89//! ### 5. Log Events Using `tracing`
90//!
91//! ```rust
92//! use tracing::error;
93//! error!(name: "my-event-name1", target: "my-system", event_id = 10, user_name = "otel", user_email = "otel@opentelemetry.io", message = "This is an example message");
94//! ```
95//!
96//!
97//! ## Mapping details
98//!
99//! Since OpenTelemetry and `tracing` have their own data models, this bridge performs the following mappings:
100//!
101//! | `tracing`             | OpenTelemetry           | Notes                                                                                   |
102//! |-----------------------|-------------------------|-----------------------------------------------------------------------------------------|
103//! | name of the event     | `EventName`             | OpenTelemetry defines logs with name as Events, so every `tracing` Event is actually an OTel Event |
104//! | target                | `target`                | Groups logs from the same module/crate. At recording time, `target` is stored in a top-level field. But exporters treat this information as OpenTelemetry `InstrumentationScope` |
105//! | level of the event    | `Severity`, `SeverityText` |                                                                                         |
106//! | Fields                | `Attributes`            | Converted into OpenTelemetry log attributes. Field with "message" as key is specially treated and stored as `LogRecord::Body` |
107//! | Message               | `Body`                  | The body/message of the log. This is done only if body was not already populated from "message" field above |
108//!
109//! ### Data Type Mapping
110//!
111//! The data types supported by `tracing` and OpenTelemetry are different and the following conversions are applied:
112//!
113//! | `tracing` Type | OpenTelemetry `AnyValue` Type |
114//! |----------------|-------------------------------|
115//! | `i64`          | `Int`                         |
116//! | `f32`, `f64`   | `Double`                      |
117//! | `u64`,`u128` ,`i128`         | `Int` (if convertible to `i64` without loss) else `String` |
118//! | `&str`         | `String`                      |
119//! | `bool`         | `Bool`                        |
120//! | `&[u8]`        | `Bytes`                       |
121//! | `&dyn Debug`   | `String` (via `Debug` formatting) |
122//! | `&dyn Error`   | `String` (via `Debug` formatting). This is stored into an attribute with key "exception.message", following [OTel conventions](https://opentelemetry.io/docs/specs/semconv/attributes-registry/exception/) |
123//!
124//! In future, additional types may be supported.
125//!
126//! > **Note:** This crate does not support `tracing` Spans. One may use [`tracing-opentelemetry`](https://docs.rs/tracing-opentelemetry/latest/tracing_opentelemetry/) to
127//! > convert `tracing` spans into OpenTelemetry spans. This is a third-party crate
128//! > that is not maintained by the OpenTelemetry project.
129//! > `tracing-opentelemetry`:
130//! > - Converts `tracing` spans into OpenTelemetry spans  
131//! > - Converts `tracing` events into OpenTelemetry `SpanEvents` rather than logs
132//! >   Depending on the outcome of the
133//! >   [discussion](https://github.com/open-telemetry/opentelemetry-rust/issues/1571),
134//! >   the OpenTelemetry project may provide direct support to map `tracing`
135//! >   spans to OpenTelemetry in the future.
136//!
137//! ## Feature Flags
138//! `spec_unstable_logs_enabled`: TODO
139//!
140//! `experimental_metadata_attributes`: TODO
141//!
142//! `experimental_use_tracing_span_context`: TODO
143//!
144//! ## Limitations
145//! 1. There is no support for `Valuable` crate. [2819](https://github.com/open-telemetry/opentelemetry-rust/issues/2819)
146//!
147//! ## Stability Guarantees
148//! // TODO
149//!
150//! ## Further Reading
151//!
152//! - OpenTelemetry Rust: [opentelemetry-rust](https://github.com/open-telemetry/opentelemetry-rust)
153//! - Tracing: [tracing](https://docs.rs/tracing/)
154//! - OpenTelemetry Logs: [OpenTelemetry Logging Specification](https://opentelemetry.io/docs/specs/otel/logs/)
155pub mod layer;