Skip to content

Commit 48c5637

Browse files
authored
docs: start doc for distributed tracing and logs guidance (#3122)
1 parent d53e6fe commit 48c5637

3 files changed

Lines changed: 246 additions & 0 deletions

File tree

docs/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# OpenTelemetry Rust Guidance
2+
3+
Guidance documents for using OpenTelemetry in Rust applications.
4+
5+
- [logs.md](logs.md) — Logs and Events
6+
- [traces.md](traces.md) — Distributed Traces
7+
- [metrics.md](metrics.md) — Metrics
8+
9+
## Why this guidance exists
10+
11+
Rust had a mature observability ecosystem before OpenTelemetry Rust matured.
12+
The [`tracing`] crate was created by the Tokio project for structured logging
13+
and in-process context propagation in async Rust, with deep integration into
14+
the async runtime. It was never designed around the OpenTelemetry data model.
15+
16+
OpenTelemetry came later with a different scope: a vendor-neutral standard
17+
for **distributed** tracing — spans that cross process boundaries — adopting
18+
[W3C Trace Context] for propagation, with first-class concepts like span
19+
kind, links, and remote parents. The OpenTelemetry Tracing API in this repo
20+
is built around that data model.
21+
22+
The third-party [`tracing-opentelemetry`] crate bridges `tracing` spans into
23+
OpenTelemetry spans. It predates parts of OpenTelemetry's evolution, and
24+
because `tracing` itself has no first-class notion of OpenTelemetry-specific
25+
span concepts, the bridge cannot fully express the OpenTelemetry model on
26+
its own.
27+
28+
These docs reflect that history: we recommend `tracing` for logs and events
29+
(where it excels), and the OpenTelemetry Tracing API for spans (where it is
30+
the spec-aligned choice). For users invested in `tracing::span!`, the
31+
bridge remains a viable option, with the caveats noted in
32+
[traces.md](traces.md).
33+
34+
## A note on guidance
35+
36+
This is guidance, not policy. Rust users have a strong, established
37+
ecosystem and the freedom to combine these libraries in ways that fit their
38+
applications. Where we make a firm recommendation, it reflects what we
39+
believe gives the best alignment with the OpenTelemetry specification and
40+
the broadest compatibility — but the choice remains yours.
41+
42+
[`tracing`]: https://crates.io/crates/tracing
43+
[`tracing-opentelemetry`]: https://crates.io/crates/tracing-opentelemetry
44+
[W3C Trace Context]: https://www.w3.org/TR/trace-context/

docs/logs.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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

docs/traces.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# OpenTelemetry Rust Traces
2+
3+
Status: **Work-In-Progress**
4+
5+
## Introduction
6+
7+
This document provides guidance on leveraging OpenTelemetry traces in Rust
8+
applications.
9+
10+
In short: prefer instrumentation libraries that use the OpenTelemetry Tracing
11+
API for framework-level spans, and use the OpenTelemetry Tracing API
12+
directly to create your own custom spans. [`tracing`] should be used for
13+
logs and events, not for OpenTelemetry spans. See [logs.md](logs.md) for
14+
log guidance.
15+
16+
## Instrumentation Guidance
17+
18+
1. **Prefer instrumentation libraries.** For framework-level spans (HTTP
19+
servers/clients, database drivers, messaging), prefer instrumentation
20+
libraries that use the OpenTelemetry Tracing API directly. Most
21+
applications start by plugging these in to capture the
22+
request/response/downstream shape, then add custom spans for in-process
23+
work as needed. No stable instrumentation libraries exist yet in the
24+
OpenTelemetry Rust ecosystem, but in-progress ones for Tower and
25+
Actix-Web exist in the [opentelemetry-rust-contrib] repository:
26+
[`opentelemetry-instrumentation-tower`] and
27+
[`opentelemetry-instrumentation-actix-web`].
28+
29+
2. **Use the OpenTelemetry Tracing API to create custom spans.** The
30+
`opentelemetry::trace` API is designed around the OpenTelemetry
31+
specification, with first-class support for span kind
32+
(server/client/producer/consumer/internal), links, remote parents, and
33+
context propagation across process boundaries.
34+
35+
3. **[`tracing`] is designed to collect structured, event-based diagnostic
36+
information, and is not a complete substitute for the OpenTelemetry
37+
Tracing API, which focuses on distributed tracing.** The `tracing` crate
38+
does not have a first-class notion of an OpenTelemetry Span. It cannot,
39+
on its own, set span kind, attach links, or set a remote parent —
40+
concepts central to the OpenTelemetry specification, particularly for
41+
*edge* spans (see #4 below for nuance). Use it primarily for logs and
42+
events (see [logs.md](logs.md)).
43+
44+
4. **Bridging from `tracing::span!` to OpenTelemetry spans.** **For new
45+
code, prefer the OpenTelemetry Tracing API directly (item 2).** If you
46+
have an existing `tracing::span!`-heavy codebase, the third-party
47+
[`tracing-opentelemetry`] crate provides a bridge. It is maintained
48+
outside the OpenTelemetry project and is not part of this repo.
49+
50+
For *internal* spans (spans that represent in-process work and never cross
51+
a process boundary), `tracing::span!` through this bridge produces a
52+
result nearly identical to using the OpenTelemetry Tracing API directly —
53+
span kind and remote parent are not applicable to internal spans, and
54+
links, while still possible, are less common there. The `tracing`
55+
limitations matter primarily for *edge* spans (e.g., incoming/outgoing
56+
HTTP, messaging), where span kind, links, and remote parents are central
57+
to the OpenTelemetry data model. The bridge offers extension APIs to
58+
express these concepts, but these are a workaround, not the recommended
59+
path for edge spans.
60+
61+
## See Also
62+
63+
- [OpenTelemetry Traces Specification](https://opentelemetry.io/docs/specs/otel/trace/)
64+
- [Main README](../README.md)
65+
- [logs.md](logs.md) — guidance for logs/events
66+
- [examples/tracing-http-propagator](../examples/tracing-http-propagator/) — end-to-end span creation and W3C context propagation
67+
- [examples/tracing-grpc](../examples/tracing-grpc/) — span creation and propagation over gRPC
68+
69+
## TODO
70+
71+
This document is intentionally high-level. Areas to expand over time, similar
72+
to the depth in [metrics.md](metrics.md):
73+
74+
- Best practices, with links to runnable examples
75+
- `TracerProvider` lifecycle and shutdown
76+
- Sampling strategies and configuration
77+
- Context propagation: W3C Trace Context, Baggage, custom propagators
78+
- Span attribute modelling and semantic conventions
79+
- Performance considerations (allocation, attribute cost, span overhead)
80+
- Common pitfalls (broken context, missed parents, mis-set span kind)
81+
- Batching, exporter configuration, and back-pressure
82+
83+
[`tracing`]: https://crates.io/crates/tracing
84+
[`tracing-opentelemetry`]: https://crates.io/crates/tracing-opentelemetry
85+
[opentelemetry-rust-contrib]: https://github.com/open-telemetry/opentelemetry-rust-contrib
86+
[`opentelemetry-instrumentation-tower`]: https://github.com/open-telemetry/opentelemetry-rust-contrib/tree/main/opentelemetry-instrumentation-tower
87+
[`opentelemetry-instrumentation-actix-web`]: https://github.com/open-telemetry/opentelemetry-rust-contrib/tree/main/opentelemetry-instrumentation-actix-web

0 commit comments

Comments
 (0)