From 8cb31fea4392b8148860f1febcb75ef36eee1e1b Mon Sep 17 00:00:00 2001 From: Timshel Date: Thu, 1 Feb 2024 17:32:15 +0100 Subject: [PATCH] Allow to override log level for specific target --- .env.template | 7 +++++++ src/config.rs | 37 +++++++++++++++++++++++++++++++++++++ src/main.rs | 4 ++++ 3 files changed, 48 insertions(+) diff --git a/.env.template b/.env.template index 0189cc7a..c5daab1c 100644 --- a/.env.template +++ b/.env.template @@ -366,6 +366,13 @@ ## routes and static file, websocket and alive requests # LOG_LEVEL=info +## log level target override +## Change the verbosity of specific log output +## Format is a line for each "target=log_level" +#LOG_LEVEL_OVERRIDE=" +#routes=warn +#" + ## Token for the admin interface, preferably an Argon2 PCH string ## Vaultwarden has a built-in generator by calling `vaultwarden hash` ## For details see: https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page#secure-the-admin_token diff --git a/src/config.rs b/src/config.rs index 489a229d..aef86e16 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,8 +1,10 @@ use std::env::consts::EXE_SUFFIX; use std::process::exit; +use std::str::FromStr; use std::sync::RwLock; use job_scheduler_ng::Schedule; +use log::LevelFilter; use once_cell::sync::Lazy; use reqwest::Url; @@ -566,6 +568,8 @@ make_config! { log_file: String, false, option; /// Log level log_level: String, false, def, "Info".to_string(); + /// Override individual log level + log_level_override: String, false, def, String::new(); /// Enable DB WAL |> Turning this off might lead to worse performance, but might help if using vaultwarden on some exotic filesystems, /// that do not support WAL. Please make sure you read project wiki on the topic before changing this setting. @@ -1060,6 +1064,26 @@ fn smtp_convert_deprecated_ssl_options(smtp_ssl: Option, smtp_explicit_tls "starttls".to_string() } +/// Allow to parse a multiline list of Key/Values (`key=value`) +/// Will ignore comment lines (starting with `//`) +fn parse_param_list(config: String) -> Vec<(String, String)> { + config + .lines() + .map(|l| l.trim()) + .filter(|l| !l.is_empty() && !l.starts_with("//")) + .filter_map(|l| { + let split = l.split('=').collect::>(); + match &split[..] { + [key, value] => Some(((*key).to_string(), (*value).to_string())), + _ => { + println!("[WARNING] Failed to parse ({l}). Expected key=value"); + None + } + } + }) + .collect() +} + impl Config { pub fn load() -> Result { // Loading from env and file @@ -1249,6 +1273,19 @@ impl Config { } } } + + pub fn log_overrides(&self) -> Vec<(String, LevelFilter)> { + parse_param_list(self.log_level_override()) + .into_iter() + .filter_map(|(k, v)| match LevelFilter::from_str(&v) { + Ok(lv) => Some((k, lv)), + Err(_) => { + println!("[WARNING] Invalid log level: {k}={v}"); + None + } + }) + .collect() + } } use handlebars::{ diff --git a/src/main.rs b/src/main.rs index e3b29383..ab66c792 100644 --- a/src/main.rs +++ b/src/main.rs @@ -284,6 +284,10 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> { logger = logger.level_for("lettre::transport::smtp", log::LevelFilter::Off) } + for (path, level) in CONFIG.log_overrides() { + logger = logger.level_for(path, level); + } + if CONFIG.extended_logging() { logger = logger.format(|out, message, record| { out.finish(format_args!(