Skip to content

Commit dc580ff

Browse files
cijothomasgruebelutpilla
authored
fix: Report error using OTel convention (#2808)
Co-authored-by: Anton Grübel <[email protected]> Co-authored-by: Utkarsh Umesan Pillai <[email protected]>
1 parent bece03b commit dc580ff

File tree

3 files changed

+84
-9
lines changed

3 files changed

+84
-9
lines changed

opentelemetry-appender-tracing/CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,16 @@ transparent to most users.
4242
implementations (SDK, processor, exporters) to leverage this additional
4343
information to determine if an event is enabled.
4444

45-
- `u64` and `usize` values are stored as `opentelemetry::logs::AnyValue::Int`
45+
- `u64`, `i128`, `u128` and `usize` values are stored as `opentelemetry::logs::AnyValue::Int`
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.
4949
- Byte arrays are stored as `opentelemetry::logs::AnyValue::Bytes` instead
5050
of string.
51+
- `Error` fields are reported using attribute named "exception.message". For
52+
example, the below will now report an attribute named "exception.message",
53+
instead of previously reporting the user provided attribute "error".
54+
`error!(....error = &OTelSdkError::AlreadyShutdown as &dyn std::error::Error...)`
5155
- perf - small perf improvement by avoiding string allocation of `target`
5256

5357
## 0.28.1

opentelemetry-appender-tracing/src/layer.rs

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

83+
fn record_error(
84+
&mut self,
85+
_field: &tracing_core::Field,
86+
value: &(dyn std::error::Error + 'static),
87+
) {
88+
self.log_record.add_attribute(
89+
Key::new("exception.message"),
90+
AnyValue::from(value.to_string()),
91+
);
92+
// No ability to get exception.stacktrace or exception.type from the error today.
93+
}
94+
8395
fn record_bytes(&mut self, field: &tracing_core::Field, value: &[u8]) {
8496
self.log_record
8597
.add_attribute(Key::new(field.name()), AnyValue::from(value));
@@ -135,6 +147,34 @@ impl<LR: LogRecord> tracing::field::Visit for EventVisitor<'_, LR> {
135147
}
136148
}
137149

150+
fn record_i128(&mut self, field: &tracing::field::Field, value: i128) {
151+
#[cfg(feature = "experimental_metadata_attributes")]
152+
if is_duplicated_metadata(field.name()) {
153+
return;
154+
}
155+
if let Ok(signed) = i64::try_from(value) {
156+
self.log_record
157+
.add_attribute(Key::new(field.name()), AnyValue::from(signed));
158+
} else {
159+
self.log_record
160+
.add_attribute(Key::new(field.name()), AnyValue::from(format!("{value:?}")));
161+
}
162+
}
163+
164+
fn record_u128(&mut self, field: &tracing::field::Field, value: u128) {
165+
#[cfg(feature = "experimental_metadata_attributes")]
166+
if is_duplicated_metadata(field.name()) {
167+
return;
168+
}
169+
if let Ok(signed) = i64::try_from(value) {
170+
self.log_record
171+
.add_attribute(Key::new(field.name()), AnyValue::from(signed));
172+
} else {
173+
self.log_record
174+
.add_attribute(Key::new(field.name()), AnyValue::from(format!("{value:?}")));
175+
}
176+
}
177+
138178
// TODO: Remaining field types from AnyValue : Bytes, ListAny, Boolean
139179
}
140180

@@ -247,7 +287,7 @@ mod tests {
247287
use opentelemetry::trace::{TraceContextExt, TraceFlags, Tracer};
248288
use opentelemetry::InstrumentationScope;
249289
use opentelemetry::{logs::AnyValue, Key};
250-
use opentelemetry_sdk::error::OTelSdkResult;
290+
use opentelemetry_sdk::error::{OTelSdkError, OTelSdkResult};
251291
use opentelemetry_sdk::logs::{InMemoryLogExporter, LogProcessor};
252292
use opentelemetry_sdk::logs::{LogBatch, LogExporter};
253293
use opentelemetry_sdk::logs::{SdkLogRecord, SdkLoggerProvider};
@@ -355,7 +395,11 @@ mod tests {
355395
let big_u64value: u64 = u64::MAX;
356396
let small_usizevalue: usize = 42;
357397
let big_usizevalue: usize = usize::MAX;
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]");
398+
let small_u128value: u128 = 42;
399+
let big_u128value: u128 = u128::MAX;
400+
let small_i128value: i128 = 42;
401+
let big_i128value: i128 = i128::MAX;
402+
error!(name: "my-event-name", target: "my-system", event_id = 20, bytes = &b"abc"[..], error = &OTelSdkError::AlreadyShutdown as &dyn std::error::Error, small_u64value, big_u64value, small_usizevalue, big_usizevalue, small_u128value, big_u128value, small_i128value, big_i128value, user_name = "otel", user_email = "[email protected]");
359403
assert!(logger_provider.force_flush().is_ok());
360404

361405
// Assert TODO: move to helper methods
@@ -386,9 +430,9 @@ mod tests {
386430

387431
// Validate attributes
388432
#[cfg(not(feature = "experimental_metadata_attributes"))]
389-
assert_eq!(log.record.attributes_iter().count(), 8);
433+
assert_eq!(log.record.attributes_iter().count(), 13);
390434
#[cfg(feature = "experimental_metadata_attributes")]
391-
assert_eq!(log.record.attributes_iter().count(), 12);
435+
assert_eq!(log.record.attributes_iter().count(), 17);
392436
assert!(attributes_contains(
393437
&log.record,
394438
&Key::new("event_id"),
@@ -404,6 +448,11 @@ mod tests {
404448
&Key::new("user_email"),
405449
&AnyValue::String("[email protected]".into())
406450
));
451+
assert!(attributes_contains(
452+
&log.record,
453+
&Key::new("exception.message"),
454+
&AnyValue::String(OTelSdkError::AlreadyShutdown.to_string().into())
455+
));
407456
assert!(attributes_contains(
408457
&log.record,
409458
&Key::new("small_u64value"),
@@ -424,6 +473,26 @@ mod tests {
424473
&Key::new("big_usizevalue"),
425474
&AnyValue::String(format!("{}", u64::MAX).into())
426475
));
476+
assert!(attributes_contains(
477+
&log.record,
478+
&Key::new("small_u128value"),
479+
&AnyValue::Int(42.into())
480+
));
481+
assert!(attributes_contains(
482+
&log.record,
483+
&Key::new("big_u128value"),
484+
&AnyValue::String(format!("{}", u128::MAX).into())
485+
));
486+
assert!(attributes_contains(
487+
&log.record,
488+
&Key::new("small_i128value"),
489+
&AnyValue::Int(42.into())
490+
));
491+
assert!(attributes_contains(
492+
&log.record,
493+
&Key::new("big_i128value"),
494+
&AnyValue::String(format!("{}", i128::MAX).into())
495+
));
427496
assert!(attributes_contains(
428497
&log.record,
429498
&Key::new("bytes"),

opentelemetry-appender-tracing/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,16 @@
5454
//!
5555
//! ### 3. Create the OpenTelemetry-Tracing Bridge
5656
//!
57+
//! Create `OpenTelemetryTracingBridge` layer using the `SdkLoggerProvider` created in the previous step.
58+
//!
5759
//! ```rust
5860
//! # use opentelemetry_sdk::logs::SdkLoggerProvider;
5961
//! # use opentelemetry_stdout::LogExporter;
6062
//! # use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
6163
//! # let exporter = LogExporter::default();
6264
//! # let provider = SdkLoggerProvider::builder()
63-
//! .with_simple_exporter(exporter)
64-
//! .build();
65+
//! # .with_simple_exporter(exporter)
66+
//! # .build();
6567
//! let otel_layer = OpenTelemetryTracingBridge::new(&provider);
6668
//! ```
6769
//!
@@ -80,7 +82,7 @@
8082
//!
8183
//! tracing_subscriber::registry()
8284
//! .with(otel_layer)
83-
//! .with(tracing_subscriber::fmt::layer())
85+
//! .with(tracing_subscriber::fmt::layer()) // In this example, `fmt` layer is also added.
8486
//! .init();
8587
//! ```
8688
//!
@@ -112,7 +114,7 @@
112114
//! |----------------|-------------------------------|
113115
//! | `i64` | `Int` |
114116
//! | `f32`, `f64` | `Double` |
115-
//! | `u64` | `Int` (if convertible without loss) else `String` |
117+
//! | `u64`,`u128` ,`i128` | `Int` (if convertible to `i64` without loss) else `String` |
116118
//! | `&str` | `String` |
117119
//! | `bool` | `Bool` |
118120
//! | `&[u8]` | `Bytes` |

0 commit comments

Comments
 (0)