diff --git a/Cargo.toml b/Cargo.toml index 311b621..71c9818 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,12 +18,11 @@ opentelemetry-semantic-conventions = { version = "0.27.0" } opentelemetry_sdk = { version = "0.27.1", features = ["rt-tokio"] } thiserror = "1.0.64" tracing-opentelemetry = { version = "0.28.0" } -tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } +tracing-subscriber = { version = "0.3.19", features = ["env-filter", "json"] } tracing = "0.1.40" serde = { version = "1.0.210", features = ["derive"] } url = { version = "2.5.2", features = ["serde"] } - # reqwest-middleware opentelemetry-http = { version = "0.27.0", optional = true } reqwest = { version = "0.12.12", optional = true } @@ -50,7 +49,7 @@ axum = ["dep:axum", "dep:tower-otel-http-metrics"] dead_code = "warn" missing_debug_implementations = "warn" missing_docs = "warn" -trivial_casts = "warn" +trivial_casts = "allow" trivial_numeric_casts = "warn" unused_extern_crates = "warn" unused_import_braces = "warn" diff --git a/src/config.rs b/src/config.rs index 2c7b188..61136f9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -48,6 +48,9 @@ pub struct StdoutLogsConfig { /// Level for the dependencies #[serde(default = "default_level_filter")] pub general_level: LevelFilter, + /// Output structured JSON logs + #[serde(default)] + pub json_output: bool, } /// Provider configuration for OpenTelemetry export @@ -79,7 +82,12 @@ impl StdoutLogsConfig { impl Default for StdoutLogsConfig { fn default() -> Self { - Self { enabled: true, level: default_level_filter(), general_level: default_level_filter() } + Self { + enabled: true, + level: default_level_filter(), + general_level: default_level_filter(), + json_output: false, + } } } diff --git a/src/lib.rs b/src/lib.rs index c982c0d..5390f21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,8 +127,14 @@ pub fn init_otel( .and_then(|stdout| stdout.enabled.then_some(stdout)) .map(|logger_config| { let filter_fmt = EnvFilter::from_str(&logger_config.get_filter(main_crate))?; + let stdout_layer = tracing_subscriber::fmt::layer().with_thread_names(true); Ok::<_, OtelInitError>( - tracing_subscriber::fmt::layer().with_thread_names(true).with_filter(filter_fmt), + if logger_config.json_output { + Box::new(stdout_layer.json()) as Box + Send + Sync> + } else { + Box::new(stdout_layer) + } + .with_filter(filter_fmt), ) }) .transpose()?; @@ -146,8 +152,8 @@ pub fn init_otel( )?; // Create a new OpenTelemetryTracingBridge using the above LoggerProvider. - let logs_layer = OpenTelemetryTracingBridge::new(&logger_provider); - let logs_layer = logs_layer.with_filter(filter_otel); + let logs_layer = + OpenTelemetryTracingBridge::new(&logger_provider).with_filter(filter_otel); Ok::<_, OtelInitError>((Some(logger_provider), Some(logs_layer))) })