diff --git a/rust/gateway/src/main.rs b/rust/gateway/src/main.rs index 2f076b3fb..505c7efe0 100644 --- a/rust/gateway/src/main.rs +++ b/rust/gateway/src/main.rs @@ -22,7 +22,7 @@ use phoenix_channel::get_user_agent; use phoenix_channel::PhoenixChannel; use secrecy::{Secret, SecretString}; -use std::{collections::BTreeSet, path::Path}; +use std::{collections::BTreeSet, fmt, path::Path}; use std::{path::PathBuf, process::ExitCode}; use std::{sync::Arc, time::Duration}; use tracing_subscriber::layer; @@ -91,8 +91,14 @@ fn has_necessary_permissions() -> bool { } async fn try_main(cli: Cli, telemetry: &mut Telemetry) -> Result<()> { - firezone_logging::setup_global_subscriber(layer::Identity::default()) - .context("Failed to set up logging")?; + firezone_logging::setup_global_subscriber( + layer::Identity::default(), + match cli.log_format { + LogFormat::Json => true, + LogFormat::Human => false, + }, + ) + .context("Failed to set up logging")?; tracing::info!( arch = std::env::consts::ARCH, @@ -306,6 +312,9 @@ struct Cli { #[arg(short = 'i', long, env = "FIREZONE_ID")] firezone_id: Option, + #[arg(long, env = "FIREZONE_LOG_FORMAT", default_value_t = LogFormat::Human)] + log_format: LogFormat, + /// Where to export metrics to. /// /// This configuration option is private API and has no stability guarantees. @@ -336,6 +345,21 @@ struct Cli { no_inc_buf: bool, } +#[derive(Debug, Clone, Copy, clap::ValueEnum)] +enum LogFormat { + Json, + Human, +} + +impl fmt::Display for LogFormat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + LogFormat::Json => write!(f, "json"), + LogFormat::Human => write!(f, "human"), + } + } +} + #[derive(Debug, Clone, Copy, clap::ValueEnum)] enum MetricsExporter { Stdout, diff --git a/rust/headless-client/src/main.rs b/rust/headless-client/src/main.rs index 2e0a5d7d9..273155aad 100644 --- a/rust/headless-client/src/main.rs +++ b/rust/headless-client/src/main.rs @@ -215,7 +215,7 @@ fn try_main() -> Result<()> { .as_deref() .map(|dir| firezone_logging::file::layer(dir, "firezone-headless-client")) .unzip(); - firezone_logging::setup_global_subscriber(layer).context("Failed to set up logging")?; + firezone_logging::setup_global_subscriber(layer, false).context("Failed to set up logging")?; // Deactivate DNS control before starting telemetry or connecting to the portal, // in case a previous run of Firezone left DNS control on and messed anything up. diff --git a/rust/logging/Cargo.toml b/rust/logging/Cargo.toml index 4e86f9ba5..fc39b20d3 100644 --- a/rust/logging/Cargo.toml +++ b/rust/logging/Cargo.toml @@ -19,7 +19,7 @@ time = { workspace = true, features = ["formatting"] } tracing = { workspace = true } tracing-appender = { workspace = true } tracing-log = { workspace = true } -tracing-subscriber = { workspace = true, features = ["env-filter"] } +tracing-subscriber = { workspace = true, features = ["env-filter", "json"] } [dev-dependencies] tempfile = { workspace = true } diff --git a/rust/logging/src/lib.rs b/rust/logging/src/lib.rs index ea3d1d9ce..78aa7785f 100644 --- a/rust/logging/src/lib.rs +++ b/rust/logging/src/lib.rs @@ -33,7 +33,10 @@ pub use err_with_sources::{ErrorWithSources, err_with_src}; pub use format::Format; /// Registers a global subscriber with stdout logging and `additional_layer` -pub fn setup_global_subscriber(additional_layer: L) -> Result +pub fn setup_global_subscriber( + additional_layer: L, + stdout_json: bool, +) -> Result where L: Layer + Send + Sync, { @@ -51,12 +54,19 @@ where let subscriber = Registry::default() .with(additional_layer.with_filter(filter1)) .with(sentry_layer()) - .with( - fmt::layer() + .with(match stdout_json { + true => fmt::layer() + .json() + .flatten_event(true) + .with_ansi(stdout_supports_ansi()) + .with_filter(filter2) + .boxed(), + false => fmt::layer() .with_ansi(stdout_supports_ansi()) .event_format(Format::new()) - .with_filter(filter2), - ); + .with_filter(filter2) + .boxed(), + }); init(subscriber)?; Ok(reload_handle1.merge(reload_handle2)) diff --git a/website/src/components/Changelog/Gateway.tsx b/website/src/components/Changelog/Gateway.tsx index 879fbb0e9..06aba5a0c 100644 --- a/website/src/components/Changelog/Gateway.tsx +++ b/website/src/components/Changelog/Gateway.tsx @@ -22,7 +22,11 @@ export default function Gateway() { return ( - + + + Adds a `--log-format` CLI option to output logs as JSON. + + Fixes a rare CPU-spike issue in case a Client connected with many