log.rs (2752B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2025 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 17 use std::io::IsTerminal; 18 19 use jiff::{Timestamp, fmt::StdFmtWrite, tz::TimeZone}; 20 use tracing::Level; 21 use tracing_subscriber::{fmt::time::FormatTime, layer::SubscriberExt, util::SubscriberInitExt}; 22 23 pub struct TalerTime { 24 zone: Option<TimeZone>, 25 } 26 27 impl TalerTime { 28 pub fn load() -> Self { 29 let zone = if std::env::var_os("JOURNAL_STREAM").is_some() { 30 None 31 } else { 32 Some(match TimeZone::try_system() { 33 Ok(z) => z, 34 Err(e) => { 35 eprintln!("could not fetch system time zone, default to UTC: {e}"); 36 TimeZone::UTC 37 } 38 }) 39 }; 40 Self { zone } 41 } 42 } 43 44 impl FormatTime for TalerTime { 45 fn format_time(&self, w: &mut tracing_subscriber::fmt::format::Writer<'_>) -> std::fmt::Result { 46 if let Some(zone) = &self.zone { 47 let timestamp = Timestamp::now(); 48 let offset = zone.to_offset(timestamp); 49 jiff::fmt::temporal::DateTimePrinter::new() 50 .precision(Some(6)) 51 .separator(b'T') 52 .print_timestamp_with_offset(×tamp, offset, StdFmtWrite(w)) 53 .map_err(|_| std::fmt::Error)?; 54 // TODO remove : in offset 55 } 56 Ok(()) 57 } 58 } 59 60 pub fn taler_logger(max_level: Option<Level>) -> impl SubscriberInitExt { 61 let max_level = max_level.unwrap_or(Level::INFO); 62 tracing_subscriber::registry() 63 .with( 64 tracing_subscriber::fmt::layer() 65 .compact() 66 .with_writer(std::io::stderr) 67 .with_timer(TalerTime::load()) 68 .with_ansi(std::io::stderr().is_terminal()), 69 ) 70 .with(tracing_subscriber::filter::filter_fn(move |metadata| { 71 let target = metadata.target(); 72 *metadata.level() <= max_level 73 && !(target.starts_with("sqlx") 74 || target.starts_with("hyper_util") 75 || target.starts_with("reqwest")) 76 })) 77 }