From 6baf3cb6a5759aa9aeb87c0e9b883326c0243b62 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Fri, 14 Mar 2025 19:40:40 -0700 Subject: [PATCH 1/9] fix: Report error using OTel convention --- opentelemetry-appender-tracing/CHANGELOG.md | 4 ++++ opentelemetry-appender-tracing/src/layer.rs | 25 +++++++++++++++++---- opentelemetry-appender-tracing/src/lib.rs | 7 ++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/opentelemetry-appender-tracing/CHANGELOG.md b/opentelemetry-appender-tracing/CHANGELOG.md index 936a7ea6fe..d03d4f4d61 100644 --- a/opentelemetry-appender-tracing/CHANGELOG.md +++ b/opentelemetry-appender-tracing/CHANGELOG.md @@ -48,6 +48,10 @@ when conversion is feasible. Otherwise stored as allocation when values can be represented in their original types. - Byte arrays are stored as `opentelemetry::logs::AnyValue::Bytes` instead of string. +- `Error` fields are reported using attribute named "exception.message". For + example, the below will now report an attribute named "exception.message", + instead of previously reporting the user provided attribute "error". + `error!(....error = &OTelSdkError::AlreadyShutdown as &dyn std::error::Error...)` - perf - small perf improvement by avoiding string allocation of `target` ## 0.28.1 diff --git a/opentelemetry-appender-tracing/src/layer.rs b/opentelemetry-appender-tracing/src/layer.rs index 9adeb803d5..e15dc6e017 100644 --- a/opentelemetry-appender-tracing/src/layer.rs +++ b/opentelemetry-appender-tracing/src/layer.rs @@ -80,6 +80,18 @@ impl tracing::field::Visit for EventVisitor<'_, LR> { } } + fn record_error( + &mut self, + _field: &tracing_core::Field, + value: &(dyn std::error::Error + 'static), + ) { + self.log_record.add_attribute( + Key::new("exception.message"), + AnyValue::from(value.to_string()), + ); + // No ability to get exception.stacktrace or exception.type from the error today. + } + fn record_bytes(&mut self, field: &tracing_core::Field, value: &[u8]) { self.log_record .add_attribute(Key::new(field.name()), AnyValue::from(value)); @@ -247,7 +259,7 @@ mod tests { use opentelemetry::trace::{TraceContextExt, TraceFlags, Tracer}; use opentelemetry::InstrumentationScope; use opentelemetry::{logs::AnyValue, Key}; - use opentelemetry_sdk::error::OTelSdkResult; + use opentelemetry_sdk::error::{OTelSdkError, OTelSdkResult}; use opentelemetry_sdk::logs::{InMemoryLogExporter, LogProcessor}; use opentelemetry_sdk::logs::{LogBatch, LogExporter}; use opentelemetry_sdk::logs::{SdkLogRecord, SdkLoggerProvider}; @@ -355,7 +367,7 @@ mod tests { let big_u64value: u64 = u64::MAX; let small_usizevalue: usize = 42; let big_usizevalue: usize = usize::MAX; - 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 = "otel@opentelemetry.io"); + 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, user_name = "otel", user_email = "otel@opentelemetry.io"); assert!(logger_provider.force_flush().is_ok()); // Assert TODO: move to helper methods @@ -386,9 +398,9 @@ mod tests { // Validate attributes #[cfg(not(feature = "experimental_metadata_attributes"))] - assert_eq!(log.record.attributes_iter().count(), 8); + assert_eq!(log.record.attributes_iter().count(), 9); #[cfg(feature = "experimental_metadata_attributes")] - assert_eq!(log.record.attributes_iter().count(), 12); + assert_eq!(log.record.attributes_iter().count(), 13); assert!(attributes_contains( &log.record, &Key::new("event_id"), @@ -404,6 +416,11 @@ mod tests { &Key::new("user_email"), &AnyValue::String("otel@opentelemetry.io".into()) )); + assert!(attributes_contains( + &log.record, + &Key::new("exception.message"), + &AnyValue::String(OTelSdkError::AlreadyShutdown.to_string().into()) + )); assert!(attributes_contains( &log.record, &Key::new("small_u64value"), diff --git a/opentelemetry-appender-tracing/src/lib.rs b/opentelemetry-appender-tracing/src/lib.rs index b2a0e7dd18..330cd36f1e 100644 --- a/opentelemetry-appender-tracing/src/lib.rs +++ b/opentelemetry-appender-tracing/src/lib.rs @@ -1 +1,8 @@ +/// This module provides integration/bridge between OpenTelemetry and the `tracing` crate. +/// TODO: Fill details +/// 1. How is this different from tracing-opentelemetry crate? +/// 2. How to use this crate? +/// 3. What are the stability guarantees? How are fields mapped? +/// 4. What are the limitations? +/// pub mod layer; From 44db6ecb4b127c30a765dcbf2fcf5bac23a977ef Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Sun, 16 Mar 2025 09:47:18 -0700 Subject: [PATCH 2/9] fmt --- opentelemetry-appender-tracing/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-appender-tracing/src/lib.rs b/opentelemetry-appender-tracing/src/lib.rs index 330cd36f1e..cd68cceae9 100644 --- a/opentelemetry-appender-tracing/src/lib.rs +++ b/opentelemetry-appender-tracing/src/lib.rs @@ -4,5 +4,5 @@ /// 2. How to use this crate? /// 3. What are the stability guarantees? How are fields mapped? /// 4. What are the limitations? -/// +/// pub mod layer; From fe2d6e4790f58a0d785cce666be83f5a1adceb65 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Sun, 16 Mar 2025 09:50:39 -0700 Subject: [PATCH 3/9] removed doc change --- opentelemetry-appender-tracing/src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/opentelemetry-appender-tracing/src/lib.rs b/opentelemetry-appender-tracing/src/lib.rs index cd68cceae9..b2a0e7dd18 100644 --- a/opentelemetry-appender-tracing/src/lib.rs +++ b/opentelemetry-appender-tracing/src/lib.rs @@ -1,8 +1 @@ -/// This module provides integration/bridge between OpenTelemetry and the `tracing` crate. -/// TODO: Fill details -/// 1. How is this different from tracing-opentelemetry crate? -/// 2. How to use this crate? -/// 3. What are the stability guarantees? How are fields mapped? -/// 4. What are the limitations? -/// pub mod layer; From 8d2016b003090a72c202dfcf71a2f72a82f7ff7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Gr=C3=BCbel?= Date: Sun, 16 Mar 2025 02:46:03 +0100 Subject: [PATCH 4/9] test: validate code based config is preferrred over env vars in trace BatchConfig (#2809) --- opentelemetry-sdk/src/trace/span_processor.rs | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/trace/span_processor.rs b/opentelemetry-sdk/src/trace/span_processor.rs index c3d5a52ac7..d2253c1cb9 100644 --- a/opentelemetry-sdk/src/trace/span_processor.rs +++ b/opentelemetry-sdk/src/trace/span_processor.rs @@ -704,6 +704,8 @@ impl Default for BatchConfigBuilder { /// * `OTEL_BSP_MAX_EXPORT_BATCH_SIZE` /// * `OTEL_BSP_EXPORT_TIMEOUT` /// * `OTEL_BSP_MAX_CONCURRENT_EXPORTS` + /// + /// Note: Programmatic configuration overrides any value set via the environment variable. fn default() -> Self { BatchConfigBuilder { max_queue_size: OTEL_BSP_MAX_QUEUE_SIZE_DEFAULT, @@ -720,7 +722,11 @@ impl BatchConfigBuilder { /// Set max_queue_size for [`BatchConfigBuilder`]. /// It's the maximum queue size to buffer spans for delayed processing. /// If the queue gets full it will drops the spans. - /// The default value of is 2048. + /// The default value is 2048. + /// + /// Corresponding environment variable: `OTEL_BSP_MAX_QUEUE_SIZE`. + /// + /// Note: Programmatically setting this will override any value set via the environment variable. pub fn with_max_queue_size(mut self, max_queue_size: usize) -> Self { self.max_queue_size = max_queue_size; self @@ -731,6 +737,10 @@ impl BatchConfigBuilder { /// more than one batch worth of spans then it processes multiple batches /// of spans one batch after the other without any delay. The default value /// is 512. + /// + /// Corresponding environment variable: `OTEL_BSP_MAX_EXPORT_BATCH_SIZE`. + /// + /// Note: Programmatically setting this will override any value set via the environment variable. pub fn with_max_export_batch_size(mut self, max_export_batch_size: usize) -> Self { self.max_export_batch_size = max_export_batch_size; self @@ -743,6 +753,11 @@ impl BatchConfigBuilder { /// The default value is 1. /// If the max_concurrent_exports value is default value, it will cause exports to be performed /// synchronously on the BatchSpanProcessor task. + /// The default value is 1. + /// + /// Corresponding environment variable: `OTEL_BSP_MAX_CONCURRENT_EXPORTS`. + /// + /// Note: Programmatically setting this will override any value set via the environment variable. pub fn with_max_concurrent_exports(mut self, max_concurrent_exports: usize) -> Self { self.max_concurrent_exports = max_concurrent_exports; self @@ -751,6 +766,10 @@ impl BatchConfigBuilder { /// Set scheduled_delay_duration for [`BatchConfigBuilder`]. /// It's the delay interval in milliseconds between two consecutive processing of batches. /// The default value is 5000 milliseconds. + /// + /// Corresponding environment variable: `OTEL_BSP_SCHEDULE_DELAY`. + /// + /// Note: Programmatically setting this will override any value set via the environment variable. pub fn with_scheduled_delay(mut self, scheduled_delay: Duration) -> Self { self.scheduled_delay = scheduled_delay; self @@ -759,6 +778,10 @@ impl BatchConfigBuilder { /// Set max_export_timeout for [`BatchConfigBuilder`]. /// It's the maximum duration to export a batch of data. /// The The default value is 30000 milliseconds. + /// + /// Corresponding environment variable: `OTEL_BSP_EXPORT_TIMEOUT`. + /// + /// Note: Programmatically setting this will override any value set via the environment variable. #[cfg(feature = "experimental_trace_batch_span_processor_with_async_runtime")] pub fn with_max_export_timeout(mut self, max_export_timeout: Duration) -> Self { self.max_export_timeout = max_export_timeout; @@ -932,6 +955,40 @@ mod tests { ); } + #[test] + fn test_code_based_config_overrides_env_vars() { + let env_vars = vec![ + (OTEL_BSP_EXPORT_TIMEOUT, Some("60000")), + (OTEL_BSP_MAX_CONCURRENT_EXPORTS, Some("5")), + (OTEL_BSP_MAX_EXPORT_BATCH_SIZE, Some("1024")), + (OTEL_BSP_MAX_QUEUE_SIZE, Some("4096")), + (OTEL_BSP_SCHEDULE_DELAY, Some("2000")), + ]; + + temp_env::with_vars(env_vars, || { + let config = BatchConfigBuilder::default() + .with_max_export_batch_size(512) + .with_max_queue_size(2048) + .with_scheduled_delay(Duration::from_millis(1000)); + #[cfg(feature = "experimental_trace_batch_span_processor_with_async_runtime")] + let config = { + config + .with_max_concurrent_exports(10) + .with_max_export_timeout(Duration::from_millis(2000)) + }; + let config = config.build(); + + assert_eq!(config.max_export_batch_size, 512); + assert_eq!(config.max_queue_size, 2048); + assert_eq!(config.scheduled_delay, Duration::from_millis(1000)); + #[cfg(feature = "experimental_trace_batch_span_processor_with_async_runtime")] + { + assert_eq!(config.max_concurrent_exports, 10); + assert_eq!(config.max_export_timeout, Duration::from_millis(2000)); + } + }); + } + #[test] fn test_batch_config_configurable_by_env_vars() { let env_vars = vec![ From 162d2f45b3b47e18481de9e8cdd2565b77666d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Gr=C3=BCbel?= Date: Sun, 16 Mar 2025 14:19:40 +0100 Subject: [PATCH 5/9] chore: remove deprecated functions/methods in trace::Config (#2810) --- opentelemetry-otlp/src/lib.rs | 15 ++- opentelemetry-sdk/CHANGELOG.md | 1 + opentelemetry-sdk/src/lib.rs | 1 - opentelemetry-sdk/src/trace/config.rs | 98 ------------------- opentelemetry-sdk/src/trace/mod.rs | 2 +- opentelemetry-sdk/src/trace/provider.rs | 11 +-- .../trace/sampler/jaeger_remote/sampler.rs | 2 +- .../src/resource.rs | 2 +- 8 files changed, 11 insertions(+), 121 deletions(-) diff --git a/opentelemetry-otlp/src/lib.rs b/opentelemetry-otlp/src/lib.rs index b57b5bda45..32d6f3b1f6 100644 --- a/opentelemetry-otlp/src/lib.rs +++ b/opentelemetry-otlp/src/lib.rs @@ -153,15 +153,12 @@ //! //! let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder() //! .with_batch_exporter(exporter) -//! .with_config( -//! trace::Config::default() -//! .with_sampler(Sampler::AlwaysOn) -//! .with_id_generator(RandomIdGenerator::default()) -//! .with_max_events_per_span(64) -//! .with_max_attributes_per_span(16) -//! .with_max_events_per_span(16) -//! .with_resource(Resource::builder_empty().with_attributes([KeyValue::new("service.name", "example")]).build()), -//! ).build(); +//! .with_sampler(Sampler::AlwaysOn) +//! .with_id_generator(RandomIdGenerator::default()) +//! .with_max_events_per_span(64) +//! .with_max_attributes_per_span(16) +//! .with_resource(Resource::builder_empty().with_attributes([KeyValue::new("service.name", "example")]).build()) +//! .build(); //! global::set_tracer_provider(tracer_provider.clone()); //! let tracer = global::tracer("tracer-name"); //! # tracer diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index 37cd5c9c8a..c58304e727 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -74,6 +74,7 @@ - **Breaking** for custom `LogProcessor` authors: Changed `set_resource` to require mutable ref. `fn set_resource(&mut self, _resource: &Resource) {}` +- **Breaking** Removed deprecated functions and methods related to `trace::Config` ## 0.28.0 diff --git a/opentelemetry-sdk/src/lib.rs b/opentelemetry-sdk/src/lib.rs index 127f9e9094..fc684920b6 100644 --- a/opentelemetry-sdk/src/lib.rs +++ b/opentelemetry-sdk/src/lib.rs @@ -136,7 +136,6 @@ pub mod runtime; #[cfg_attr(docsrs, doc(cfg(any(feature = "testing", test))))] pub mod testing; -#[allow(deprecated)] #[cfg(feature = "trace")] #[cfg_attr(docsrs, doc(cfg(feature = "trace")))] pub mod trace; diff --git a/opentelemetry-sdk/src/trace/config.rs b/opentelemetry-sdk/src/trace/config.rs index 92b570d669..67db9509dc 100644 --- a/opentelemetry-sdk/src/trace/config.rs +++ b/opentelemetry-sdk/src/trace/config.rs @@ -9,12 +9,6 @@ use std::borrow::Cow; use std::env; use std::str::FromStr; -/// Default trace configuration -#[deprecated(since = "0.23.0", note = "Use Config::default() instead")] -pub fn config() -> Config { - Config::default() -} - /// Tracer configuration #[derive(Debug)] #[non_exhaustive] @@ -32,98 +26,6 @@ pub struct Config { pub resource: Cow<'static, Resource>, } -impl Config { - /// Specify the sampler to be used. - #[deprecated( - since = "0.27.1", - note = "Config is becoming private. Please use Builder::with_sampler(...) instead." - )] - pub fn with_sampler(mut self, sampler: T) -> Self { - self.sampler = Box::new(sampler); - self - } - - /// Specify the id generator to be used. - #[deprecated( - since = "0.27.1", - note = "Config is becoming private. Please use Builder::with_id_generator(...) instead." - )] - pub fn with_id_generator(mut self, id_generator: T) -> Self { - self.id_generator = Box::new(id_generator); - self - } - - /// Specify the maximum number of events that can be recorded per span. - #[deprecated( - since = "0.27.1", - note = "Config is becoming private. Please use Builder::with_max_events_per_span(...) instead." - )] - pub fn with_max_events_per_span(mut self, max_events: u32) -> Self { - self.span_limits.max_events_per_span = max_events; - self - } - - /// Specify the maximum number of attributes that can be recorded per span. - #[deprecated( - since = "0.27.1", - note = "Config is becoming private. Please use Builder::with_max_attributes_per_span(...) instead." - )] - pub fn with_max_attributes_per_span(mut self, max_attributes: u32) -> Self { - self.span_limits.max_attributes_per_span = max_attributes; - self - } - - /// Specify the maximum number of links that can be recorded per span. - #[deprecated( - since = "0.27.1", - note = "Config is becoming private. Please use Builder::with_max_links_per_span(...) instead." - )] - pub fn with_max_links_per_span(mut self, max_links: u32) -> Self { - self.span_limits.max_links_per_span = max_links; - self - } - - /// Specify the maximum number of attributes one event can have. - #[deprecated( - since = "0.27.1", - note = "Config is becoming private. Please use Builder::with_max_attributes_per_event(...) instead." - )] - pub fn with_max_attributes_per_event(mut self, max_attributes: u32) -> Self { - self.span_limits.max_attributes_per_event = max_attributes; - self - } - - /// Specify the maximum number of attributes one link can have. - #[deprecated( - since = "0.27.1", - note = "Config is becoming private. Please use Builder::with_max_attributes_per_link(...) instead." - )] - pub fn with_max_attributes_per_link(mut self, max_attributes: u32) -> Self { - self.span_limits.max_attributes_per_link = max_attributes; - self - } - - /// Specify all limit via the span_limits - #[deprecated( - since = "0.27.1", - note = "Config is becoming private. Please use Builder::with_span_limits(...) instead." - )] - pub fn with_span_limits(mut self, span_limits: SpanLimits) -> Self { - self.span_limits = span_limits; - self - } - - /// Specify the attributes representing the entity that produces telemetry - #[deprecated( - since = "0.27.1", - note = "Config is becoming private. Please use Builder::with_resource(...) instead." - )] - pub fn with_resource(mut self, resource: Resource) -> Self { - self.resource = Cow::Owned(resource); - self - } -} - impl Default for Config { /// Create default global sdk configuration. fn default() -> Self { diff --git a/opentelemetry-sdk/src/trace/mod.rs b/opentelemetry-sdk/src/trace/mod.rs index e9e1f82f8e..ad3a18543f 100644 --- a/opentelemetry-sdk/src/trace/mod.rs +++ b/opentelemetry-sdk/src/trace/mod.rs @@ -22,7 +22,7 @@ mod span_processor; pub mod span_processor_with_async_runtime; mod tracer; -pub use config::{config, Config}; +pub use config::Config; pub use error::{TraceError, TraceResult}; pub use events::SpanEvents; pub use export::{SpanData, SpanExporter}; diff --git a/opentelemetry-sdk/src/trace/provider.rs b/opentelemetry-sdk/src/trace/provider.rs index 6d0e01fe9a..2773b8778b 100644 --- a/opentelemetry-sdk/src/trace/provider.rs +++ b/opentelemetry-sdk/src/trace/provider.rs @@ -345,15 +345,6 @@ impl TracerProviderBuilder { TracerProviderBuilder { processors, ..self } } - /// The sdk [`crate::trace::Config`] that this provider will use. - #[deprecated( - since = "0.27.1", - note = "Config is becoming a private type. Use Builder::with_{config_name}(resource) instead. ex: Builder::with_resource(resource)" - )] - pub fn with_config(self, config: crate::trace::Config) -> Self { - TracerProviderBuilder { config, ..self } - } - /// Specify the sampler to be used. pub fn with_sampler(mut self, sampler: T) -> Self { self.config.sampler = Box::new(sampler); @@ -428,7 +419,7 @@ impl TracerProviderBuilder { // Now, we can update the config with the resource. if let Some(resource) = self.resource { - config = config.with_resource(resource); + config.resource = Cow::Owned(resource); }; // Standard config will contain an owned [`Resource`] (either sdk default or use supplied) diff --git a/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs b/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs index a24fb13b75..7f6ce1dde0 100644 --- a/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs +++ b/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs @@ -234,7 +234,7 @@ impl JaegerRemoteSampler { .unwrap(); let resp = client - .send(request) + .send_bytes(request) .await .map_err(|err| format!("the request is failed to send {}", err))?; diff --git a/opentelemetry-semantic-conventions/src/resource.rs b/opentelemetry-semantic-conventions/src/resource.rs index 6fd093e3da..ca297d6190 100644 --- a/opentelemetry-semantic-conventions/src/resource.rs +++ b/opentelemetry-semantic-conventions/src/resource.rs @@ -15,7 +15,7 @@ //! //! ```rust //! use opentelemetry::KeyValue; -//! use opentelemetry_sdk::{trace::{config, SdkTracerProvider}, Resource}; +//! use opentelemetry_sdk::{trace::SdkTracerProvider, Resource}; //! use opentelemetry_semantic_conventions as semconv; //! //! let _tracer = SdkTracerProvider::builder() From 9308e48c77606f3db731ba2826bb1819d9100120 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Tue, 18 Mar 2025 22:00:46 -0700 Subject: [PATCH 6/9] support rest of fields too --- opentelemetry-appender-tracing/CHANGELOG.md | 2 +- opentelemetry-appender-tracing/src/layer.rs | 58 +++++++++++++++++++-- opentelemetry-appender-tracing/src/lib.rs | 2 +- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/opentelemetry-appender-tracing/CHANGELOG.md b/opentelemetry-appender-tracing/CHANGELOG.md index d03d4f4d61..9633e06368 100644 --- a/opentelemetry-appender-tracing/CHANGELOG.md +++ b/opentelemetry-appender-tracing/CHANGELOG.md @@ -42,7 +42,7 @@ transparent to most users. implementations (SDK, processor, exporters) to leverage this additional information to determine if an event is enabled. -- `u64` and `usize` values are stored as `opentelemetry::logs::AnyValue::Int` +- `u64`, `i128`, `u128` and `usize` values are stored as `opentelemetry::logs::AnyValue::Int` when conversion is feasible. Otherwise stored as `opentelemetry::logs::AnyValue::String`. This avoids unnecessary string allocation when values can be represented in their original types. diff --git a/opentelemetry-appender-tracing/src/layer.rs b/opentelemetry-appender-tracing/src/layer.rs index e15dc6e017..fe0bc645ed 100644 --- a/opentelemetry-appender-tracing/src/layer.rs +++ b/opentelemetry-appender-tracing/src/layer.rs @@ -147,6 +147,34 @@ impl tracing::field::Visit for EventVisitor<'_, LR> { } } + fn record_i128(&mut self, field: &tracing::field::Field, value: i128) { + #[cfg(feature = "experimental_metadata_attributes")] + if is_duplicated_metadata(field.name()) { + return; + } + if let Ok(signed) = i64::try_from(value) { + self.log_record + .add_attribute(Key::new(field.name()), AnyValue::from(signed)); + } else { + self.log_record + .add_attribute(Key::new(field.name()), AnyValue::from(format!("{value:?}"))); + } + } + + fn record_u128(&mut self, field: &tracing::field::Field, value: u128) { + #[cfg(feature = "experimental_metadata_attributes")] + if is_duplicated_metadata(field.name()) { + return; + } + if let Ok(signed) = i64::try_from(value) { + self.log_record + .add_attribute(Key::new(field.name()), AnyValue::from(signed)); + } else { + self.log_record + .add_attribute(Key::new(field.name()), AnyValue::from(format!("{value:?}"))); + } + } + // TODO: Remaining field types from AnyValue : Bytes, ListAny, Boolean } @@ -367,7 +395,11 @@ mod tests { let big_u64value: u64 = u64::MAX; let small_usizevalue: usize = 42; let big_usizevalue: usize = usize::MAX; - 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, user_name = "otel", user_email = "otel@opentelemetry.io"); + let small_u128value: u128 = 42; + let big_u128value: u128 = u128::MAX; + let small_i128value: i128 = 42; + let big_i128value: i128 = i128::MAX; + 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 = "otel@opentelemetry.io"); assert!(logger_provider.force_flush().is_ok()); // Assert TODO: move to helper methods @@ -398,9 +430,9 @@ mod tests { // Validate attributes #[cfg(not(feature = "experimental_metadata_attributes"))] - assert_eq!(log.record.attributes_iter().count(), 9); - #[cfg(feature = "experimental_metadata_attributes")] assert_eq!(log.record.attributes_iter().count(), 13); + #[cfg(feature = "experimental_metadata_attributes")] + assert_eq!(log.record.attributes_iter().count(), 17); assert!(attributes_contains( &log.record, &Key::new("event_id"), @@ -441,6 +473,26 @@ mod tests { &Key::new("big_usizevalue"), &AnyValue::String(format!("{}", u64::MAX).into()) )); + assert!(attributes_contains( + &log.record, + &Key::new("small_u128value"), + &AnyValue::Int(42.into()) + )); + assert!(attributes_contains( + &log.record, + &Key::new("big_u128value"), + &AnyValue::String(format!("{}", u128::MAX).into()) + )); + assert!(attributes_contains( + &log.record, + &Key::new("small_i128value"), + &AnyValue::Int(42.into()) + )); + assert!(attributes_contains( + &log.record, + &Key::new("big_i128value"), + &AnyValue::String(format!("{}", i128::MAX).into()) + )); assert!(attributes_contains( &log.record, &Key::new("bytes"), diff --git a/opentelemetry-appender-tracing/src/lib.rs b/opentelemetry-appender-tracing/src/lib.rs index 5e2820b79b..690efc9b21 100644 --- a/opentelemetry-appender-tracing/src/lib.rs +++ b/opentelemetry-appender-tracing/src/lib.rs @@ -112,7 +112,7 @@ //! |----------------|-------------------------------| //! | `i64` | `Int` | //! | `f32`, `f64` | `Double` | -//! | `u64` | `Int` (if convertible without loss) else `String` | +//! | `u64`,`u128` ,`i128` | `Int` (if convertible without loss) else `String` | //! | `&str` | `String` | //! | `bool` | `Bool` | //! | `&[u8]` | `Bytes` | From fd3c173e12469020ea210f0ace9a7689c588b294 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Tue, 18 Mar 2025 22:07:35 -0700 Subject: [PATCH 7/9] lib doc --- opentelemetry-appender-tracing/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/opentelemetry-appender-tracing/src/lib.rs b/opentelemetry-appender-tracing/src/lib.rs index 690efc9b21..d536ea417b 100644 --- a/opentelemetry-appender-tracing/src/lib.rs +++ b/opentelemetry-appender-tracing/src/lib.rs @@ -54,14 +54,16 @@ //! //! ### 3. Create the OpenTelemetry-Tracing Bridge //! +//! Create `OpenTelemetryTracingBridge` layer using the `SdkLoggerProvider` created in the previous step. +//! //! ```rust //! # use opentelemetry_sdk::logs::SdkLoggerProvider; //! # use opentelemetry_stdout::LogExporter; //! # use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge; //! # let exporter = LogExporter::default(); //! # let provider = SdkLoggerProvider::builder() -//! .with_simple_exporter(exporter) -//! .build(); +//! # .with_simple_exporter(exporter) +//! # .build(); //! let otel_layer = OpenTelemetryTracingBridge::new(&provider); //! ``` //! @@ -80,7 +82,7 @@ //! //! tracing_subscriber::registry() //! .with(otel_layer) -//! .with(tracing_subscriber::fmt::layer()) +//! .with(tracing_subscriber::fmt::layer()) // In this example, `fmt` layer is also added. //! .init(); //! ``` //! From 333488413fa302e0bb17ce9d0fac15a1ccbf72e3 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Tue, 18 Mar 2025 22:07:46 -0700 Subject: [PATCH 8/9] fmt --- opentelemetry-appender-tracing/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-appender-tracing/src/lib.rs b/opentelemetry-appender-tracing/src/lib.rs index d536ea417b..b165060a94 100644 --- a/opentelemetry-appender-tracing/src/lib.rs +++ b/opentelemetry-appender-tracing/src/lib.rs @@ -55,7 +55,7 @@ //! ### 3. Create the OpenTelemetry-Tracing Bridge //! //! Create `OpenTelemetryTracingBridge` layer using the `SdkLoggerProvider` created in the previous step. -//! +//! //! ```rust //! # use opentelemetry_sdk::logs::SdkLoggerProvider; //! # use opentelemetry_stdout::LogExporter; From 327442b0d3248fe66484439d2f7b749d883605a6 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Wed, 19 Mar 2025 15:51:45 -0700 Subject: [PATCH 9/9] Apply suggestions from code review Co-authored-by: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> --- opentelemetry-appender-tracing/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-appender-tracing/src/lib.rs b/opentelemetry-appender-tracing/src/lib.rs index b165060a94..c868d508a4 100644 --- a/opentelemetry-appender-tracing/src/lib.rs +++ b/opentelemetry-appender-tracing/src/lib.rs @@ -114,7 +114,7 @@ //! |----------------|-------------------------------| //! | `i64` | `Int` | //! | `f32`, `f64` | `Double` | -//! | `u64`,`u128` ,`i128` | `Int` (if convertible without loss) else `String` | +//! | `u64`,`u128` ,`i128` | `Int` (if convertible to `i64` without loss) else `String` | //! | `&str` | `String` | //! | `bool` | `Bool` | //! | `&[u8]` | `Bytes` |