|
| 1 | +# OpenTelemetry Rust Logs |
| 2 | + |
| 3 | +Status: **Stable** |
| 4 | + |
| 5 | +## Introduction |
| 6 | + |
| 7 | +This document provides guidance on leveraging OpenTelemetry logs in Rust |
| 8 | +applications. |
| 9 | + |
| 10 | +In short: for application logging, use [`tracing`] with the |
| 11 | +[`opentelemetry-appender-tracing`] appender (not [`tracing-opentelemetry`], |
| 12 | +which bridges *spans*, not logs — see [traces.md](traces.md)). If you have |
| 13 | +an existing codebase using the [`log`] crate, keep using it and bridge to |
| 14 | +OpenTelemetry via [`opentelemetry-appender-log`]; but for **new code, use |
| 15 | +`tracing`**, which supports structured logging and is what OpenTelemetry |
| 16 | +itself uses internally. Adopting OpenTelemetry for logs is primarily a setup |
| 17 | +change, not a code rewrite. For span guidance, see [traces.md](traces.md). |
| 18 | + |
| 19 | +[`tracing`]: https://crates.io/crates/tracing |
| 20 | +[`tracing-opentelemetry`]: https://crates.io/crates/tracing-opentelemetry |
| 21 | +[`log`]: https://crates.io/crates/log |
| 22 | +[`opentelemetry-appender-tracing`]: ../opentelemetry-appender-tracing/README.md |
| 23 | +[`opentelemetry-appender-log`]: ../opentelemetry-appender-log/README.md |
| 24 | + |
| 25 | +## OpenTelemetry Log Bridge API |
| 26 | + |
| 27 | +Do **not** use the OpenTelemetry Log Bridge API (part of the `opentelemetry` |
| 28 | +crate) directly in application code. It is public only to allow authoring |
| 29 | +appenders that bridge existing logging frameworks into OpenTelemetry, and is |
| 30 | +not intended as an end-user logging API. Bridges for the |
| 31 | +[`tracing`](https://docs.rs/opentelemetry-appender-tracing/) and |
| 32 | +[`log`](https://docs.rs/opentelemetry-appender-log/) crates are already |
| 33 | +available; application code should emit logs via those crates. |
| 34 | + |
| 35 | +## Instrumentation Guidance |
| 36 | + |
| 37 | +1. **Use the `tracing` crate**: We strongly recommend using the |
| 38 | + [`tracing`](https://crates.io/crates/tracing) crate for structured logging in |
| 39 | + Rust applications. |
| 40 | + |
| 41 | +2. **Lean on the `tracing` ecosystem**: OpenTelemetry doesn't replace what |
| 42 | + `tracing` already offers. The appender is a standard `tracing-subscriber` |
| 43 | + `Layer`, so it composes with `fmt::Layer`, `EnvFilter`, and any other |
| 44 | + existing layer — for example, sending logs to stdout via `tracing`'s |
| 45 | + `fmt::Layer` while exporting the same logs to an OTLP endpoint via |
| 46 | + OpenTelemetry, or filtering what reaches the OpenTelemetry pipeline. Use |
| 47 | + `tracing`'s ecosystem directly; OpenTelemetry just plugs into it. |
| 48 | + |
| 49 | +3. **Explicitly provide `name` and `target` fields**: These map to OpenTelemetry's |
| 50 | + EventName and Instrumentation Scope respectively. Without them, `tracing` |
| 51 | + synthesizes a `name` from the source location (e.g. `event src/foo.rs:42`) |
| 52 | + and uses the module path as `target`, neither of which is meaningful as an |
| 53 | + EventName or Instrumentation Scope. |
| 54 | + |
| 55 | +4. **Trace correlation is automatic**: When a log is emitted inside an active |
| 56 | + OpenTelemetry span, the appender attaches the current `TraceId` and `SpanId` |
| 57 | + to the resulting `LogRecord`. No extra wiring is required. |
| 58 | + |
| 59 | +5. **In-proc contextual enrichment via `tracing::span!`**: Use `tracing::span!` |
| 60 | + to attach contextual attributes (e.g. `session.id`, `request.id`) that |
| 61 | + should apply to every log inside that scope. This is the recommended |
| 62 | + pattern. The appender supports copying these span attributes onto each |
| 63 | + emitted `LogRecord` via the `experimental_span_attributes` cargo feature; |
| 64 | + the feature is experimental because the implementation may evolve, not |
| 65 | + the pattern itself. See the |
| 66 | + [appender README](../opentelemetry-appender-tracing/README.md) for usage. |
| 67 | + |
| 68 | +### Example |
| 69 | + |
| 70 | +```rust |
| 71 | +use tracing::error; |
| 72 | +error!( |
| 73 | + name: "db.client.connection.failed", |
| 74 | + target: "myapp.db", |
| 75 | + db.system.name = "postgresql", |
| 76 | + db.namespace = "orders", |
| 77 | + error.type = "connection_timeout", |
| 78 | + retry_count = 3, |
| 79 | + message = "Failed to connect to database after retries" |
| 80 | +); |
| 81 | +``` |
| 82 | + |
| 83 | +## Terminology |
| 84 | + |
| 85 | +OpenTelemetry defines Events as Logs with an EventName. When you follow the guidance |
| 86 | +above and explicitly set the `name` field on every `tracing` log, each log maps to |
| 87 | +an OpenTelemetry Event. (Without an explicit `name`, the synthesized source-location |
| 88 | +string is technically present but is not a meaningful EventName.) |
| 89 | + |
| 90 | +**Note**: These are **not** mapped to Span Events. Prefer Events |
| 91 | +(Logs with an EventName) as described above. [OTEP-4430] proposes deprecating |
| 92 | +the *Span Events API* in favor of Events. |
| 93 | + |
| 94 | +[OTEP-4430]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/oteps/4430-span-event-api-deprecation-plan.md |
| 95 | + |
| 96 | +## See Also |
| 97 | + |
| 98 | +- [Main README](../README.md) — setup guidance for logging libraries and appenders |
| 99 | +- [OpenTelemetry Logs |
| 100 | + Specification](https://opentelemetry.io/docs/specs/otel/logs/) |
| 101 | +- [`tracing` Documentation](https://docs.rs/tracing/) |
| 102 | +- [`opentelemetry-appender-tracing` |
| 103 | + Documentation](https://docs.rs/opentelemetry-appender-tracing/) |
| 104 | + |
| 105 | +## TODO |
| 106 | + |
| 107 | +This document is intentionally high-level. Areas to expand over time, similar |
| 108 | +to the depth in [metrics.md](metrics.md): |
| 109 | + |
| 110 | +- Best practices, with links to runnable examples |
| 111 | +- `LoggerProvider` lifecycle and shutdown |
| 112 | +- Performance considerations (allocation, attribute cost) |
| 113 | +- Attribute modelling and semantic conventions |
| 114 | +- Common pitfalls (lost logs, missing correlation, mis-set `target`) |
| 115 | +- Batching, exporter configuration, and back-pressure |
0 commit comments