Skip to content

Commit c8cc66a

Browse files
authored
Merge branch 'main' into validate-baggage
2 parents 2ffc5bb + d2859dc commit c8cc66a

File tree

36 files changed

+543
-484
lines changed

36 files changed

+543
-484
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ It's important to regularly review and remove the `otel_unstable` flag from the
172172

173173
The potential features include:
174174

175-
- Stable and non-experimental features that compliant to specification, and have a feature flag to minimize compilation size. Example: feature flags for signals (like `logs`, `traces`, `metrics`) and runtimes (`rt-tokio`, `rt-tokio-current-thread`, `rt-async-std`).
175+
- Stable and non-experimental features that are compliant with the specification and have a feature flag to minimize compilation size. Example: feature flags for signals (like `logs`, `traces`, `metrics`) and runtimes (`rt-tokio`, `rt-tokio-current-thread`).
176176
- Stable and non-experimental features, although not part of the specification, are crucial for enhancing the tracing/log crate's functionality or boosting performance. These features are also subject to discussion and approval by the OpenTelemetry Rust Maintainers.
177177

178178
All such features should adhere to naming convention `<signal>_<feature_name>`

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,6 @@ you're more than welcome to participate!
181181

182182
* [Cijo Thomas](https://github.com/cijothomas)
183183
* [Harold Dost](https://github.com/hdost)
184-
* [Julian Tescher](https://github.com/jtescher)
185184
* [Lalit Kumar Bhasin](https://github.com/lalitb)
186185
* [Utkarsh Umesan Pillai](https://github.com/utpilla)
187186
* [Zhongyang Wu](https://github.com/TommyCpp)
@@ -195,6 +194,7 @@ you're more than welcome to participate!
195194

196195
* [Dirkjan Ochtman](https://github.com/djc)
197196
* [Jan Kühle](https://github.com/frigus02)
197+
* [Julian Tescher](https://github.com/jtescher)
198198
* [Isobel Redelmeier](https://github.com/iredelmeier)
199199
* [Mike Goldsmith](https://github.com/MikeGoldsmith)
200200

docs/design/logs.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,13 @@ They get called in the order of registration. Log records are passed to the
195195
records, enrich them, filter them, and export to destinations by leveraging
196196
LogRecord Exporters.
197197

198+
Similar to [LoggerProvider](#sdkloggerprovider), methods on the `LogProcessor`
199+
trait also takes a immutable self (`&self`) only, forcing the need to use
200+
interior mutability, if any mutation is required. The exception to this is
201+
`set_resource`, which takes a `&mut self`. This is acceptable as `set_resource`
202+
is called by the `SdkLoggerProvider` during build() method only, and is not
203+
required after that.
204+
198205
Following built-in Log processors are provided in the Log SDK:
199206

200207
##### SimpleLogProcessor
@@ -232,8 +239,13 @@ other words, that many logs can be lost if the app crashes in the middle.
232239

233240
## LogExporters
234241

235-
LogExporters are responsible for exporting logs to a destination. Some of them
236-
include:
242+
LogExporters are responsible for exporting logs to a destination.
243+
`SdkLoggerProvider` does not have a direct knowledge of the `LogExporter`, as it
244+
only deals with `LogProcessors`. It is the `LogProcessor`s that invokes
245+
`LogExporter` methods. Most methods on `LogExporter` trait also only takes
246+
`&self`, following the same reasoning as [LogProcessors](#logrecord-processors)
247+
248+
Some of the exporters are:
237249

238250
1. **InMemoryExporter** - exports to an in-memory list, primarily for
239251
unit-testing. This is used extensively in the repo itself, and external users

examples/tracing-jaeger/Cargo.toml

Lines changed: 0 additions & 12 deletions
This file was deleted.

examples/tracing-jaeger/README.md

Lines changed: 0 additions & 21 deletions
This file was deleted.

examples/tracing-jaeger/jaeger.png

-165 KB
Binary file not shown.

examples/tracing-jaeger/src/main.rs

Lines changed: 0 additions & 50 deletions
This file was deleted.

opentelemetry-appender-tracing/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ transparent to most users.
4646
when conversion is feasible. Otherwise stored as
4747
`opentelemetry::logs::AnyValue::String`. This avoids unnecessary string
4848
allocation when values can be represented in their original types.
49-
49+
- Byte arrays are stored as `opentelemetry::logs::AnyValue::Bytes` instead
50+
of string.
5051
- perf - small perf improvement by avoiding string allocation of `target`
5152

5253
## 0.28.1

opentelemetry-appender-tracing/src/layer.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ impl<LR: LogRecord> tracing::field::Visit for EventVisitor<'_, LR> {
8080
}
8181
}
8282

83+
fn record_bytes(&mut self, field: &tracing_core::Field, value: &[u8]) {
84+
self.log_record
85+
.add_attribute(Key::new(field.name()), AnyValue::from(value));
86+
}
87+
8388
fn record_str(&mut self, field: &tracing_core::Field, value: &str) {
8489
#[cfg(feature = "experimental_metadata_attributes")]
8590
if is_duplicated_metadata(field.name()) {
@@ -350,7 +355,7 @@ mod tests {
350355
let big_u64value: u64 = u64::MAX;
351356
let small_usizevalue: usize = 42;
352357
let big_usizevalue: usize = usize::MAX;
353-
error!(name: "my-event-name", target: "my-system", event_id = 20, small_u64value, big_u64value, small_usizevalue, big_usizevalue, user_name = "otel", user_email = "[email protected]");
358+
error!(name: "my-event-name", target: "my-system", event_id = 20, bytes = &b"abc"[..], small_u64value, big_u64value, small_usizevalue, big_usizevalue, user_name = "otel", user_email = "[email protected]");
354359
assert!(logger_provider.force_flush().is_ok());
355360

356361
// Assert TODO: move to helper methods
@@ -381,9 +386,9 @@ mod tests {
381386

382387
// Validate attributes
383388
#[cfg(not(feature = "experimental_metadata_attributes"))]
384-
assert_eq!(log.record.attributes_iter().count(), 7);
389+
assert_eq!(log.record.attributes_iter().count(), 8);
385390
#[cfg(feature = "experimental_metadata_attributes")]
386-
assert_eq!(log.record.attributes_iter().count(), 11);
391+
assert_eq!(log.record.attributes_iter().count(), 12);
387392
assert!(attributes_contains(
388393
&log.record,
389394
&Key::new("event_id"),
@@ -419,6 +424,11 @@ mod tests {
419424
&Key::new("big_usizevalue"),
420425
&AnyValue::String(format!("{}", u64::MAX).into())
421426
));
427+
assert!(attributes_contains(
428+
&log.record,
429+
&Key::new("bytes"),
430+
&AnyValue::Bytes(Box::new(b"abc".to_vec()))
431+
));
422432
#[cfg(feature = "experimental_metadata_attributes")]
423433
{
424434
assert!(attributes_contains(
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,153 @@
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/)
1153
pub mod layer;

0 commit comments

Comments
 (0)