Refactor: Entferne Terminal-Überprüfung und vereinfache Ausgabehandling

This commit is contained in:
2026-08-23 17:48:50 +02:00
parent d042137d36
commit c2da58c74e
+13 -31
View File
@@ -1,10 +1,10 @@
//! Einfaches, threadsicheres Logging-Modul. //! Einfaches, threadsicheres Logging-Modul.
//! //!
//! Merkmale: //! Merkmale:
//! - Ausgabe in Terminal (stdout/stderr) und zusätzlich in eine Logdatei im temporären Verzeichnis. //! - Ausgabe auf Standard-Streams (stdout/stderr) und zusätzlich in eine Logdatei im temporären Verzeichnis.
//! - Nachrichtenvorlage: `[DD.MM.YYYY HH:MM:SS.mmm][LEVEL][TAG]: <Text>` mit Präfix ([!]/[?]/[i]/[d]). //! - Nachrichtenvorlage: `[DD.MM.YYYY HH:MM:SS.mmm][LEVEL][TAG]: <Text>` mit Präfix ([!]/[?]/[i]/[d]).
//! - Der aktuell verwendete Schweregradfilter ist statisch (`LOG_LEVEL`) und wird zur Laufzeit nicht geändert. //! - Der aktuell verwendete Schweregradfilter ist statisch (`LOG_LEVEL`) und wird zur Laufzeit nicht geändert.
//! - Terminal-Erkennung und Dateihandle werden lazily initialisiert und zwischengespeichert (`OnceLock`). //! - Dateihandle wird lazily initialisiert und zwischengespeichert (`OnceLock`).
//! //!
//! Hinweise: //! Hinweise:
//! - Bei einem leeren `tag` wird ein leerer Tag-Abschnitt erzeugt. //! - Bei einem leeren `tag` wird ein leerer Tag-Abschnitt erzeugt.
@@ -22,13 +22,13 @@
use std::env; use std::env;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::fs::{create_dir_all, File, OpenOptions}; use std::fs::{File, OpenOptions, create_dir_all};
use std::io::{stdout, IsTerminal, Write}; use std::io::Write;
use std::sync::{Mutex, OnceLock}; use std::sync::{Mutex, OnceLock};
use crate::config; use crate::config;
use crate::program; use crate::program;
use time::{macros::format_description, OffsetDateTime}; use time::{OffsetDateTime, macros::format_description};
/// Schweregrade für Logeinträge in aufsteigender Detailtiefe. /// Schweregrade für Logeinträge in aufsteigender Detailtiefe.
/// ///
@@ -71,14 +71,11 @@ impl TryFrom<String> for LogLevel {
"warn" => Ok(LogLevel::Warn), "warn" => Ok(LogLevel::Warn),
"info" => Ok(LogLevel::Info), "info" => Ok(LogLevel::Info),
"debug" => Ok(LogLevel::Debug), "debug" => Ok(LogLevel::Debug),
_ => Err(LogLevel::Info) _ => Err(LogLevel::Info),
} }
} }
} }
/// Zwischenspeicher für die einmalig ermittelte Terminal-Fähigkeit von `stdout`.
static IS_TERMINAL: OnceLock<bool> = OnceLock::new();
/// Globaler Schweregradfilter für Ausgabe. /// Globaler Schweregradfilter für Ausgabe.
static LOG_LEVEL: OnceLock<LogLevel> = OnceLock::new(); static LOG_LEVEL: OnceLock<LogLevel> = OnceLock::new();
@@ -89,7 +86,7 @@ static LOG_FILE: OnceLock<Mutex<Option<File>>> = OnceLock::new();
/// ///
/// Verhalten: /// Verhalten:
/// - Wenn `log_level` größer als der globale Filter ist, wird nichts ausgegeben. /// - Wenn `log_level` größer als der globale Filter ist, wird nichts ausgegeben.
/// - Bei Terminalausgabe gehen `Error`-Meldungen nach `stderr`, alle anderen nach `stdout`. /// - `Error`-Meldungen gehen nach `stderr`, alle anderen nach `stdout`.
/// - Zusätzlich wird in eine tägliche Logdatei im Temp-Verzeichnis geschrieben (wenn erfolgreich geöffnet). /// - Zusätzlich wird in eine tägliche Logdatei im Temp-Verzeichnis geschrieben (wenn erfolgreich geöffnet).
/// ///
/// Parameter: /// Parameter:
@@ -109,12 +106,10 @@ pub fn log(tag: &str, message: &str, log_level: LogLevel) {
if log_level <= get_log_level() { if log_level <= get_log_level() {
let message: String = format_message(tag, message, &log_level); let message: String = format_message(tag, message, &log_level);
if is_terminal() { if log_level == LogLevel::Error {
if log_level == LogLevel::Error { eprintln!("{}", message);
eprintln!("{}", message) } else {
} else { println!("{}", message);
println!("{}", message)
}
} }
let file_lock = get_or_init_log_file(); let file_lock = get_or_init_log_file();
@@ -138,17 +133,7 @@ fn get_log_level() -> LogLevel {
*LOG_LEVEL.get_or_init(|| { *LOG_LEVEL.get_or_init(|| {
let log_level = &config::get_config().general.log_level; let log_level = &config::get_config().general.log_level;
LogLevel::try_from(log_level.to_string()).unwrap_or(LogLevel::Info) LogLevel::try_from(log_level.to_string()).unwrap_or(LogLevel::Info)
} })
)
}
/// Ermittelt einmalig, ob `stdout` ein Terminal ist, und cached das Ergebnis.
///
/// Rückgabe:
/// - `true`, wenn `stdout` ein TTY/Terminal ist.
/// - `false` andernfalls.
fn is_terminal() -> bool {
*IS_TERMINAL.get_or_init(|| stdout().is_terminal())
} }
/// Formatiert eine Lognachricht mit Zeitstempel, Level, Tag und Präfix. /// Formatiert eine Lognachricht mit Zeitstempel, Level, Tag und Präfix.
@@ -234,10 +219,7 @@ fn open_log_file() -> std::io::Result<File> {
let file_name = format!("log-{}.log", date_str); let file_name = format!("log-{}.log", date_str);
dir.push(file_name); dir.push(file_name);
OpenOptions::new() OpenOptions::new().create(true).append(true).open(dir)
.create(true)
.append(true)
.open(dir)
} }
#[cfg(test)] #[cfg(test)]