diff --git a/.schema/pgdog.schema.json b/.schema/pgdog.schema.json index 328267bb1..06c9fc10d 100644 --- a/.schema/pgdog.schema.json +++ b/.schema/pgdog.schema.json @@ -1255,6 +1255,11 @@ "description": "Structured JSON logs suitable for ECS/Datadog ingestion.", "type": "string", "const": "json" + }, + { + "description": "Structured JSON logs with event fields flattened into the root object.", + "type": "string", + "const": "json_flattened" } ] }, diff --git a/example.pgdog.toml b/example.pgdog.toml index 481a36f5f..7427d9636 100644 --- a/example.pgdog.toml +++ b/example.pgdog.toml @@ -138,6 +138,7 @@ openmetrics_namespace = "pgdog_" # Available options: # - text # - json +# - json_flattened log_format = "text" # Log filter directives using the same syntax as RUST_LOG. # diff --git a/pgdog-config/src/general.rs b/pgdog-config/src/general.rs index 9b8b2b2eb..40c279d6e 100644 --- a/pgdog-config/src/general.rs +++ b/pgdog-config/src/general.rs @@ -28,6 +28,8 @@ pub enum LogFormat { Text, /// Structured JSON logs suitable for ECS/Datadog ingestion. Json, + /// Structured JSON logs with event fields flattened into the root object. + JsonFlattened, } impl fmt::Display for LogFormat { @@ -35,6 +37,7 @@ impl fmt::Display for LogFormat { match self { Self::Text => f.write_str("text"), Self::Json => f.write_str("json"), + Self::JsonFlattened => f.write_str("json_flattened"), } } } @@ -46,6 +49,7 @@ impl FromStr for LogFormat { match s.to_ascii_lowercase().as_str() { "text" => Ok(Self::Text), "json" => Ok(Self::Json), + "json_flattened" => Ok(Self::JsonFlattened), _ => Err(()), } } @@ -1635,6 +1639,9 @@ mod tests { assert_eq!(General::log_format(), LogFormat::Json); assert_eq!(General::log_level(), "pgdog=debug,info"); + env::set_var("PGDOG_LOG_FORMAT", "json_flattened"); + assert_eq!(General::log_format(), LogFormat::JsonFlattened); + env::remove_var("PGDOG_LOG_FORMAT"); env::remove_var("RUST_LOG"); diff --git a/pgdog/src/lib.rs b/pgdog/src/lib.rs index 58c13c361..2aa95cc9a 100644 --- a/pgdog/src/lib.rs +++ b/pgdog/src/lib.rs @@ -173,10 +173,11 @@ fn init_logger(general: Option<&General>) { let throttle = throttle_handle().clone(); - match general + let log_format = general .map(|general| general.log_format) - .unwrap_or_default() - { + .unwrap_or_default(); + + match log_format { LogFormat::Text => { let format = fmt::layer() .with_ansi(std::io::stderr().is_terminal()) @@ -191,7 +192,7 @@ fn init_logger(general: Option<&General>) { .with(filter) .try_init(); } - LogFormat::Json => { + LogFormat::Json | LogFormat::JsonFlattened => { let format = fmt::layer() .json() .with_ansi(false) @@ -199,6 +200,10 @@ fn init_logger(general: Option<&General>) { .with_file(false) .with_current_span(false) .with_span_list(false); + let format = match log_format { + LogFormat::JsonFlattened => format.flatten_event(true), + _ => format, + }; #[cfg(not(debug_assertions))] let format = format.with_target(false); let format = format.with_filter(throttle); diff --git a/pgdog/src/plugin/mod.rs b/pgdog/src/plugin/mod.rs index 5d2186371..93a5900de 100644 --- a/pgdog/src/plugin/mod.rs +++ b/pgdog/src/plugin/mod.rs @@ -108,7 +108,10 @@ pub fn load(config: &Config) -> Result<(), libloading::Error> { let pd_config = PdConfig { log_level: PdStr::from(config.general.log_level.as_str()), - log_json: if config.general.log_format == LogFormat::Json { + log_json: if matches!( + config.general.log_format, + LogFormat::Json | LogFormat::JsonFlattened + ) { 1 } else { 0