Skip to content

Commit

Permalink
feat: Allow configuring the tracing log output format (#275)
Browse files Browse the repository at this point in the history
  • Loading branch information
spencewenski authored Jul 8, 2024
1 parent a5e8461 commit 727f770
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ dotenvy = "0.15.5"

# Tracing
tracing = { workspace = true }
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
tracing-subscriber = { version = "0.3.17", features = ["env-filter", "json"] }
opentelemetry-semantic-conventions = "0.15.0"
opentelemetry = { version = "0.23.0", features = ["trace", "metrics", "logs"], optional = true }
opentelemetry_sdk = { version = "0.23.0", features = ["tokio", "rt-tokio", "metrics", "logs", "trace"], optional = true }
Expand Down
3 changes: 3 additions & 0 deletions config/development.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[tracing]
format = "pretty"

[auth.jwt]
secret = "secret-dev"

Expand Down
3 changes: 3 additions & 0 deletions config/test.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[tracing]
format = "pretty"

[auth.jwt]
secret = "secret-test"

Expand Down
3 changes: 3 additions & 0 deletions examples/full/config/development.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[tracing]
format = "pretty"

[auth.jwt]
secret = "secret-dev"

Expand Down
3 changes: 3 additions & 0 deletions examples/full/config/test.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[tracing]
format = "pretty"

[auth.jwt]
secret = "secret-test"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ required-claims = []

[tracing]
level = 'debug'
format = 'compact'
trace-propagation = true

[database]
Expand Down
1 change: 1 addition & 0 deletions src/config/tracing/default.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[tracing]
format = "compact"
trace-propagation = true
21 changes: 20 additions & 1 deletion src/config/tracing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::util::serde_util::default_true;
use config::{FileFormat, FileSourceString};
use serde_derive::{Deserialize, Serialize};
use strum_macros::{EnumString, IntoStaticStr};
#[cfg(feature = "otel")]
use url::Url;
use validator::Validate;
Expand All @@ -16,6 +17,9 @@ pub fn default_config() -> config::File<FileSourceString, FileFormat> {
pub struct Tracing {
pub level: String,

/// The format to use when printing traces to logs.
pub format: Format,

/// The name of the service to use for the OpenTelemetry `service.name` field. If not provided,
/// will use the [`App::name`][crate::config::app_config::App] config value, translated to `snake_case`.
#[cfg(feature = "otel")]
Expand All @@ -31,6 +35,17 @@ pub struct Tracing {
pub otlp_endpoint: Option<Url>,
}

#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, EnumString, IntoStaticStr)]
#[serde(rename_all = "kebab-case")]
#[strum(serialize_all = "kebab-case")]
#[non_exhaustive]
pub enum Format {
None,
Pretty,
Compact,
Json,
}

// To simplify testing, these are only run when all of the config fields are available
#[cfg(all(test, feature = "otel"))]
mod deserialize_tests {
Expand All @@ -49,28 +64,32 @@ mod deserialize_tests {
#[case(
r#"
level = "debug"
format = "compact"
"#
)]
#[case(
r#"
level = "info"
format = "json"
service-name = "foo"
"#
)]
#[case(
r#"
level = "error"
format = "pretty"
trace-propagation = false
"#
)]
#[case(
r#"
level = "debug"
format = "none"
otlp-endpoint = "https://example.com:1234"
"#
)]
#[cfg_attr(coverage_nightly, coverage(off))]
fn sidekiq(_case: TestCase, #[case] config: &str) {
fn tracing(_case: TestCase, #[case] config: &str) {
let tracing: Tracing = toml::from_str(config).unwrap();

assert_toml_snapshot!(tracing);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
source: src/config/tracing.rs
source: src/config/tracing/mod.rs
expression: tracing
---
level = 'debug'
format = 'compact'
trace-propagation = true
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
source: src/config/tracing.rs
source: src/config/tracing/mod.rs
expression: tracing
---
level = 'info'
format = 'json'
service-name = 'foo'
trace-propagation = true
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
source: src/config/tracing.rs
source: src/config/tracing/mod.rs
expression: tracing
---
level = 'error'
format = 'pretty'
trace-propagation = false
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
source: src/config/tracing.rs
source: src/config/tracing/mod.rs
expression: tracing
---
level = 'debug'
format = 'none'
trace-propagation = true
otlp-endpoint = 'https://example.com:1234/'
42 changes: 40 additions & 2 deletions src/tracing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::EnvFilter;

use crate::config::app_config::AppConfig;
use crate::config::tracing::Format;
use crate::error::RoadsterResult;

// Todo: make this configurable
Expand All @@ -30,7 +31,42 @@ pub fn init_tracing(
metadata: &AppMetadata,
) -> RoadsterResult<()> {
// Stdout Layer
let stdout_layer = tracing_subscriber::fmt::layer();
// Each format results in a different type, so we can't use a `match` on the format enum.
// Instead, we need to create an optional layer of each type, and add all of them to the
// registry -- if a layer is `None`, it won't actually be added.
let compact_log_layer = if matches!(config.tracing.format, Format::Compact) {
Some(tracing_subscriber::fmt::layer().compact())
} else {
None
};
let pretty_log_layer = if matches!(config.tracing.format, Format::Pretty) {
Some(tracing_subscriber::fmt::layer().pretty())
} else {
None
};
let json_log_layer = if matches!(config.tracing.format, Format::Json) {
Some(tracing_subscriber::fmt::layer().json())
} else {
None
};
match config.tracing.format {
Format::None => {
assert!(
pretty_log_layer.is_none()
&& compact_log_layer.is_none()
&& json_log_layer.is_none()
)
}
Format::Pretty => {
assert!(pretty_log_layer.is_some())
}
Format::Compact => {
assert!(compact_log_layer.is_some())
}
Format::Json => {
assert!(json_log_layer.is_some())
}
}

#[cfg(feature = "otel")]
if config.tracing.trace_propagation {
Expand Down Expand Up @@ -104,7 +140,9 @@ pub fn init_tracing(

let registry = tracing_subscriber::Registry::default()
.with(env_filter)
.with(stdout_layer);
.with(compact_log_layer)
.with(pretty_log_layer)
.with(json_log_layer);

#[cfg(feature = "otel")]
let registry = { registry.with(oltp_traces_layer).with(otlp_metrics_layer) };
Expand Down

0 comments on commit 727f770

Please sign in to comment.