|
| 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.28", features = ["logs"] } |
| 34 | +//! opentelemetry-sdk = { version = "0.28", features = ["logs"] } |
| 35 | +//! opentelemetry-appender-tracing = { version = "0.28.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 | +//! ```rust |
| 58 | +//! # use opentelemetry_sdk::logs::SdkLoggerProvider; |
| 59 | +//! # use opentelemetry_stdout::LogExporter; |
| 60 | +//! # use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge; |
| 61 | +//! # let exporter = LogExporter::default(); |
| 62 | +//! # let provider = SdkLoggerProvider::builder() |
| 63 | +//! .with_simple_exporter(exporter) |
| 64 | +//! .build(); |
| 65 | +//! let otel_layer = OpenTelemetryTracingBridge::new(&provider); |
| 66 | +//! ``` |
| 67 | +//! |
| 68 | +//! ### 4. Register the `tracing` Subscriber |
| 69 | +//! |
| 70 | +//! Since this crate provides a `Layer` for `tracing`, you can register it with the `tracing` subscriber as shown below. |
| 71 | +//! |
| 72 | +//! ```rust |
| 73 | +//! # use opentelemetry_sdk::logs::SdkLoggerProvider; |
| 74 | +//! # use opentelemetry_stdout::LogExporter; |
| 75 | +//! # let exporter = LogExporter::default(); |
| 76 | +//! # let provider = SdkLoggerProvider::builder().with_simple_exporter(exporter).build(); |
| 77 | +//! # use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge; |
| 78 | +//! # let otel_layer = OpenTelemetryTracingBridge::new(&provider); |
| 79 | +//! use tracing_subscriber::prelude::*; |
| 80 | +//! |
| 81 | +//! tracing_subscriber::registry() |
| 82 | +//! .with(otel_layer) |
| 83 | +//! .with(tracing_subscriber::fmt::layer()) |
| 84 | +//! .init(); |
| 85 | +//! ``` |
| 86 | +//! |
| 87 | +//! ### 5. Log Events Using `tracing` |
| 88 | +//! |
| 89 | +//! ```rust |
| 90 | +//! use tracing::error; |
| 91 | +//! error!(name: "my-event-name1", target: "my-system", event_id = 10, user_name = "otel", user_email = "[email protected]", message = "This is an example message"); |
| 92 | +//! ``` |
| 93 | +//! |
| 94 | +//! |
| 95 | +//! ## Mapping details |
| 96 | +//! |
| 97 | +//! Since OpenTelemetry and `tracing` have their own data models, this bridge performs the following mappings: |
| 98 | +//! |
| 99 | +//! | `tracing` | OpenTelemetry | Notes | |
| 100 | +//! |-----------------------|-------------------------|-----------------------------------------------------------------------------------------| |
| 101 | +//! | name of the event | `EventName` | OpenTelemetry defines logs with name as Events, so every `tracing` Event is actually an OTel Event | |
| 102 | +//! | 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` | |
| 103 | +//! | level of the event | `Severity`, `SeverityText` | | |
| 104 | +//! | Fields | `Attributes` | Converted into OpenTelemetry log attributes. Field with "message" as key is specially treated and stored as `LogRecord::Body` | |
| 105 | +//! | Message | `Body` | The body/message of the log. This is done only if body was not already populated from "message" field above | |
| 106 | +//! |
| 107 | +//! ### Data Type Mapping |
| 108 | +//! |
| 109 | +//! The data types supported by `tracing` and OpenTelemetry are different and the following conversions are applied: |
| 110 | +//! |
| 111 | +//! | `tracing` Type | OpenTelemetry `AnyValue` Type | |
| 112 | +//! |----------------|-------------------------------| |
| 113 | +//! | `i64` | `Int` | |
| 114 | +//! | `f32`, `f64` | `Double` | |
| 115 | +//! | `u64` | `Int` (if convertible without loss) else `String` | |
| 116 | +//! | `&str` | `String` | |
| 117 | +//! | `bool` | `Bool` | |
| 118 | +//! | `&[u8]` | `Bytes` | |
| 119 | +//! | `&dyn Debug` | `String` (via `Debug` formatting) | |
| 120 | +//! | `&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/) | |
| 121 | +//! |
| 122 | +//! In future, additional types may be supported. |
| 123 | +//! |
| 124 | +//! > **Note:** This crate does not support `tracing` Spans. One may use [`tracing-opentelemetry`](https://docs.rs/tracing-opentelemetry/latest/tracing_opentelemetry/) to |
| 125 | +//! > convert `tracing` spans into OpenTelemetry spans. This is a third-party crate |
| 126 | +//! > that is not maintained by the OpenTelemetry project. |
| 127 | +//! > `tracing-opentelemetry`: |
| 128 | +//! > - Converts `tracing` spans into OpenTelemetry spans |
| 129 | +//! > - Converts `tracing` events into OpenTelemetry `SpanEvents` rather than logs |
| 130 | +//! > Depending on the outcome of the |
| 131 | +//! > [discussion](https://github.com/open-telemetry/opentelemetry-rust/issues/1571), |
| 132 | +//! > the OpenTelemetry project may provide direct support to map `tracing` |
| 133 | +//! > spans to OpenTelemetry in the future. |
| 134 | +//! |
| 135 | +//! ## Feature Flags |
| 136 | +//! `spec_unstable_logs_enabled`: TODO |
| 137 | +//! |
| 138 | +//! `experimental_metadata_attributes`: TODO |
| 139 | +//! |
| 140 | +//! `experimental_use_tracing_span_context`: TODO |
| 141 | +//! |
| 142 | +//! ## Limitations |
| 143 | +//! 1. There is no support for `Valuable` crate. [2819](https://github.com/open-telemetry/opentelemetry-rust/issues/2819) |
| 144 | +//! |
| 145 | +//! ## Stability Guarantees |
| 146 | +//! // TODO |
| 147 | +//! |
| 148 | +//! ## Further Reading |
| 149 | +//! |
| 150 | +//! - OpenTelemetry Rust: [opentelemetry-rust](https://github.com/open-telemetry/opentelemetry-rust) |
| 151 | +//! - Tracing: [tracing](https://docs.rs/tracing/) |
| 152 | +//! - OpenTelemetry Logs: [OpenTelemetry Logging Specification](https://opentelemetry.io/docs/specs/otel/logs/) |
1 | 153 | pub mod layer;
|
0 commit comments