fix: remove log (file) when level is explicitly set to OFF (#2083)

* fix level filter for OFF
* remove unwrap of file appender creation
This commit is contained in:
Luna Yao
2026-04-12 16:16:30 +02:00
committed by GitHub
parent 9e0a3b6936
commit 869e1b89f5
2 changed files with 44 additions and 46 deletions
+31 -36
View File
@@ -1,5 +1,3 @@
use std::io::IsTerminal as _;
use crate::common::config::{FileLoggerConfig, LoggingConfigLoader}; use crate::common::config::{FileLoggerConfig, LoggingConfigLoader};
use crate::common::get_logger_timer_rfc3339; use crate::common::get_logger_timer_rfc3339;
use crate::common::tracing_rolling_appender::{FileAppenderWrapper, RollingFileAppenderBase}; use crate::common::tracing_rolling_appender::{FileAppenderWrapper, RollingFileAppenderBase};
@@ -7,7 +5,7 @@ use crate::rpc_service::logger::{CURRENT_LOG_LEVEL, LOGGER_LEVEL_SENDER};
use anyhow::Context; use anyhow::Context;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use paste::paste; use paste::paste;
use regex::Regex; use std::io::IsTerminal;
use tracing::level_filters::LevelFilter; use tracing::level_filters::LevelFilter;
use tracing::{Level, Metadata}; use tracing::{Level, Metadata};
use tracing_subscriber::Registry; use tracing_subscriber::Registry;
@@ -49,18 +47,16 @@ macro_rules! __log__ {
__log__!(const LOG_TARGET = "CORE"); __log__!(const LOG_TARGET = "CORE");
fn parse_env_filter(default_level: LevelFilter) -> Result<EnvFilter, anyhow::Error> { fn parse_env_filter(default_level: Option<LevelFilter>) -> Result<EnvFilter, anyhow::Error> {
let mut filter = EnvFilter::builder() let directive = match default_level {
.with_default_directive(default_level.into()) Some(level) => level.into(),
None => format!("{LOG_TARGET}=info").parse()?,
};
EnvFilter::builder()
.with_default_directive(directive)
.from_env() .from_env()
.with_context(|| "failed to create env filter")?; .with_context(|| "failed to create env filter")
let pattern = Regex::new(&format!(r"(^|,){}\s*=", regex::escape(LOG_TARGET)))?;
if !pattern.is_match(&filter.to_string()) {
filter = filter.add_directive(format!("{LOG_TARGET}=info").parse()?);
}
Ok(filter)
} }
fn is_log(meta: &Metadata) -> bool { fn is_log(meta: &Metadata) -> bool {
@@ -96,8 +92,7 @@ pub fn init(
config config
.get_console_logger_config() .get_console_logger_config()
.level .level
.map(|s| s.parse().unwrap()) .map(|s| s.parse().unwrap()),
.unwrap_or(LevelFilter::OFF),
)?; )?;
layers.extend(console_layers); layers.extend(console_layers);
@@ -118,9 +113,9 @@ pub fn init(
type BoxLayer = Box<dyn Layer<Registry> + Send + Sync>; type BoxLayer = Box<dyn Layer<Registry> + Send + Sync>;
fn console_layers(default_level: LevelFilter) -> anyhow::Result<Vec<BoxLayer>> { fn console_layers(default_level: Option<LevelFilter>) -> anyhow::Result<Vec<BoxLayer>> {
let mut layers = Vec::new(); let mut layers = Vec::new();
if default_level == LevelFilter::OFF { if matches!(default_level, Some(LevelFilter::OFF)) {
return Ok(layers); return Ok(layers);
} }
@@ -173,15 +168,23 @@ fn file_layers(
) -> anyhow::Result<(Vec<BoxLayer>, Option<NewFilterSender>)> { ) -> anyhow::Result<(Vec<BoxLayer>, Option<NewFilterSender>)> {
let mut layers = Vec::new(); let mut layers = Vec::new();
let level = config let level = config.level.map(|s| s.parse().unwrap());
.level
.map(|s| s.parse().unwrap())
.unwrap_or(LevelFilter::OFF);
if level == LevelFilter::OFF && !reload { if matches!(level, Some(LevelFilter::OFF)) && !reload {
return Ok((layers, None)); return Ok((layers, None));
} }
let (file_filter, file_filter_reloader) =
tracing_subscriber::reload::Layer::<_, Registry>::new(parse_env_filter(level)?);
let layer = |wrapper| {
layer()
.with_ansi(false)
.with_writer(wrapper)
.with_timer(get_logger_timer_rfc3339())
};
let wrapper = {
let path = { let path = {
let dir = config.dir.as_deref().unwrap_or("."); let dir = config.dir.as_deref().unwrap_or(".");
let file = config.file.as_deref().unwrap_or("easytier.log"); let file = config.file.as_deref().unwrap_or("easytier.log");
@@ -196,19 +199,9 @@ fn file_layers(
.max_filecount(config.count.unwrap_or(10)) .max_filecount(config.count.unwrap_or(10))
.condition_max_file_size(config.size_mb.unwrap_or(100) * 1024 * 1024) .condition_max_file_size(config.size_mb.unwrap_or(100) * 1024 * 1024)
.build() .build()
.unwrap(); .with_context(|| "failed to initialize rolling file appender")?;
// Create a simple wrapper that implements MakeWriter FileAppenderWrapper::new(file_appender)
let wrapper = FileAppenderWrapper::new(file_appender);
let (file_filter, file_filter_reloader) =
tracing_subscriber::reload::Layer::<_, Registry>::new(parse_env_filter(level)?);
let layer = |wrapper| {
layer()
.with_ansi(false)
.with_writer(wrapper)
.with_timer(get_logger_timer_rfc3339())
}; };
layers.push( layers.push(
@@ -228,7 +221,9 @@ fn file_layers(
// 初始化全局状态 // 初始化全局状态
let _ = LOGGER_LEVEL_SENDER.set(std::sync::Mutex::new(tx.clone())); let _ = LOGGER_LEVEL_SENDER.set(std::sync::Mutex::new(tx.clone()));
if let Some(level) = level {
let _ = CURRENT_LOG_LEVEL.set(std::sync::Mutex::new(level.to_string())); let _ = CURRENT_LOG_LEVEL.set(std::sync::Mutex::new(level.to_string()));
}
std::thread::spawn(move || { std::thread::spawn(move || {
while let Ok(lf) = rx.recv() { while let Ok(lf) = rx.recv() {
@@ -279,7 +274,7 @@ mod tests {
#[ctor::ctor] #[ctor::ctor]
fn init() { fn init() {
let _ = Registry::default() let _ = Registry::default()
.with(console_layers(LevelFilter::DEBUG).unwrap()) .with(console_layers(Some(LevelFilter::DEBUG)).unwrap())
.try_init(); .try_init();
} }
@@ -1,4 +1,5 @@
use super::*; use super::*;
use anyhow::anyhow;
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct RollingConditionBase { pub struct RollingConditionBase {
@@ -135,9 +136,11 @@ impl RollingFileAppenderBaseBuilder {
/// Builds a RollingFileAppenderBase instance from the current settings. /// Builds a RollingFileAppenderBase instance from the current settings.
/// ///
/// Returns an error if the filename is empty. /// Returns an error if the filename is empty.
pub fn build(self) -> Result<RollingFileAppenderBase, &'static str> { pub fn build(self) -> anyhow::Result<RollingFileAppenderBase> {
if self.filename.is_empty() { if self.filename.is_empty() {
return Err("A filename is required to be set and can not be blank"); return Err(anyhow!(
"A filename is required to be set and can not be blank"
));
} }
Ok(RollingFileAppenderBase { Ok(RollingFileAppenderBase {
condition: self.condition, condition: self.condition,