diff --git a/Cargo.lock b/Cargo.lock index 17be733..4267e6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2959,6 +2959,16 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.18" @@ -2969,12 +2979,15 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2b1929a..7c1445e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ tokio = { version = "1.32.0", features = ["full", "tracing"] } tokio-util = "0.7.4" tower-http = { version = "0.5.2", features = ["cors", "trace"] } tracing = "0.1.34" -tracing-subscriber = "0.3.11" +tracing-subscriber = { version = "0.3.11", features = ["json"] } uuid = { version = "1.3.2", features = ["v4", "fast-rng", "serde"] } [dev-dependencies] diff --git a/boilmaster.toml b/boilmaster.toml index 741e9bd..b25b084 100644 --- a/boilmaster.toml +++ b/boilmaster.toml @@ -1,6 +1,11 @@ -[tracing.filters] -default = "debug" -hyper = "info" +[tracing.console] +enabled = false + +[tracing.stdout] +enabled = true +format = "full" +filters.default = "debug" +filters.hyper = "info" [http] # address = "0.0.0.0" diff --git a/src/tracing.rs b/src/tracing.rs index 0b84f77..b782635 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -1,16 +1,36 @@ use std::{collections::HashMap, fmt, str::FromStr}; use serde::{de, Deserialize}; -use tracing::metadata::LevelFilter; -use tracing_subscriber::{filter, layer::SubscriberExt, util::SubscriberInitExt, Layer}; +use tracing::{metadata::LevelFilter, Subscriber}; +use tracing_subscriber::{ + filter, layer::SubscriberExt, registry::LookupSpan, util::SubscriberInitExt, Layer, +}; -// TODO: tracing should proooobably be it's own file at this point #[derive(Debug, Deserialize)] pub struct Config { - // TODO: log file config? or like, sink config? work out how that's going to work i guess. + console: ConsoleConfig, + stdout: StdoutConfig, +} + +#[derive(Debug, Deserialize)] +struct ConsoleConfig { + enabled: bool, +} + +#[derive(Debug, Deserialize)] +struct StdoutConfig { + enabled: bool, + format: StdoutFormat, filters: TracingFilters, } +#[derive(Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +enum StdoutFormat { + Full, + Json, +} + #[derive(Debug, Deserialize)] struct TracingFilters { default: ConfigLevelFilter, @@ -46,19 +66,49 @@ impl<'de> Deserialize<'de> for ConfigLevelFilter { } pub fn init(config: Config) { - // TODO: consider enabling this with a config flag or something tracing.console? - let console_filter = filter::Targets::new() + // TODO: env filter (will need feature enabled). consider enabling pulling from log! too. + // TODO: now that i have config working, is it worth using env filter here or should i handle it via config env? + tracing_subscriber::registry() + .with(tokio_console(config.console)) + .with(stdout(config.stdout)) + .init(); +} + +fn tokio_console(config: ConsoleConfig) -> Option> +where + S: Subscriber + for<'a> LookupSpan<'a>, +{ + if !config.enabled { + return None; + } + + let layer = console_subscriber::spawn(); + + let filter = filter::Targets::new() .with_target("tokio", LevelFilter::TRACE) .with_target("runtime", LevelFilter::TRACE); - let tracing_filter = filter::Targets::new() + Some(layer.with_filter(filter)) +} + +fn stdout(config: StdoutConfig) -> Option> +where + S: Subscriber + for<'a> LookupSpan<'a>, +{ + if !config.enabled { + return None; + } + + let layer = tracing_subscriber::fmt::layer(); + + let layer = match config.format { + StdoutFormat::Full => layer.boxed(), + StdoutFormat::Json => layer.json().boxed(), + }; + + let filter = filter::Targets::new() .with_default(config.filters.default) .with_targets(config.filters.targets); - // TODO: env filter (will need feature enabled). consider enabling pulling from log! too. - // TODO: now that i have config working, is it worth using env filter here or should i handle it via config env? - tracing_subscriber::registry() - .with(console_subscriber::spawn().with_filter(console_filter)) - .with(tracing_subscriber::fmt::layer().with_filter(tracing_filter)) - .init(); + Some(layer.with_filter(filter)) }