mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
feat(gateway): add option for outputting logs as JSON (#10620)
To enable customers to ingest flow logs (#8353) into various SIEMS, outputting structured logs is crucial.
This commit is contained in:
@@ -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<String>,
|
||||
|
||||
#[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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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<L>(additional_layer: L) -> Result<FilterReloadHandle>
|
||||
pub fn setup_global_subscriber<L>(
|
||||
additional_layer: L,
|
||||
stdout_json: bool,
|
||||
) -> Result<FilterReloadHandle>
|
||||
where
|
||||
L: Layer<Registry> + 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))
|
||||
|
||||
@@ -22,7 +22,11 @@ export default function Gateway() {
|
||||
|
||||
return (
|
||||
<Entries downloadLinks={downloadLinks} title="Gateway">
|
||||
<Unreleased></Unreleased>
|
||||
<Unreleased>
|
||||
<ChangeItem pull="10620">
|
||||
Adds a `--log-format` CLI option to output logs as JSON.
|
||||
</ChangeItem>
|
||||
</Unreleased>
|
||||
<Entry version="1.4.17" date={new Date("2025-10-16")}>
|
||||
<ChangeItem pull="10367">
|
||||
Fixes a rare CPU-spike issue in case a Client connected with many
|
||||
|
||||
Reference in New Issue
Block a user