Add a cli arg to support redirect log (#230)

* add cli arg to support redirect log
This commit is contained in:
Al Liu 2023-06-28 17:10:19 +08:00 committed by GitHub
parent 8956a3547b
commit 4a80690c1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 30 deletions

View File

@ -1,7 +1,14 @@
use std::str::FromStr; use std::{
fs::File,
io::{stderr, stdout},
path::PathBuf,
str::FromStr,
};
use tracing_subscriber::fmt::{format::Format, FormatEvent, FormatFields, SubscriberBuilder};
#[derive(Copy, Clone)] #[derive(Default, Copy, Clone)]
pub enum LogFormat { pub enum LogFormat {
#[default]
Plain, Plain,
Json, Json,
} }
@ -18,30 +25,62 @@ impl FromStr for LogFormat {
} }
} }
pub fn config_tracing(fmt: Option<LogFormat>) { #[derive(Default, Clone)]
let filter = std::env::var("SIMULATION_LOG").unwrap_or_else(|_| "info".to_owned()); pub enum LogOutput {
if let Some(LogFormat::Json) = fmt { #[default]
let subscriber = tracing_subscriber::fmt::fmt() StdOut,
.without_time() StdErr,
.with_line_number(true) File(PathBuf),
.with_env_filter(filter) }
.with_file(false)
.with_target(true) impl FromStr for LogOutput {
.with_ansi(true) type Err = anyhow::Error;
.json()
.finish(); fn from_str(s: &str) -> Result<Self, Self::Err> {
tracing::subscriber::set_global_default(subscriber) match s.trim().to_ascii_lowercase().as_str() {
.expect("config_tracing is only called once"); "stdout" => Ok(Self::StdOut),
} else { "stderr" => Ok(Self::StdErr),
let subscriber = tracing_subscriber::fmt::fmt() path => Ok(Self::File(PathBuf::from(path))),
.without_time() }
.with_line_number(true)
.with_env_filter(filter)
.with_file(false)
.with_target(true)
.with_ansi(true)
.finish();
tracing::subscriber::set_global_default(subscriber)
.expect("config_tracing is only called once");
} }
} }
pub fn config_tracing(fmt: LogFormat, file: &LogOutput) {
let filter = std::env::var("SIMULATION_LOG").unwrap_or_else(|_| "info".to_owned());
let subscriber = tracing_subscriber::fmt::fmt()
.without_time()
.with_line_number(true)
.with_env_filter(filter)
.with_file(false)
.with_target(true);
if let LogFormat::Json = fmt {
set_global(subscriber.json(), file);
} else {
set_global(subscriber, file);
}
}
fn set_global<N, L, T>(
subscriber: SubscriberBuilder<N, Format<L, T>, tracing_subscriber::EnvFilter>,
output: &LogOutput,
) where
N: for<'writer> FormatFields<'writer> + 'static + Send + Sync,
Format<L, T>: FormatEvent<tracing_subscriber::Registry, N>,
L: Send + Sync + 'static,
T: Send + Sync + 'static,
{
use tracing::subscriber::set_global_default;
match output {
LogOutput::StdOut => set_global_default(subscriber.with_writer(stdout).finish()),
LogOutput::StdErr => set_global_default(subscriber.with_writer(stderr).finish()),
LogOutput::File(path) => set_global_default(
subscriber
.with_ansi(false)
.with_writer(File::create(path).expect("Unable to create log file"))
.finish(),
),
}
.expect("Unable to set global default subscriber")
}

View File

@ -39,8 +39,10 @@ pub struct SimulationApp {
input_settings: PathBuf, input_settings: PathBuf,
#[clap(long)] #[clap(long)]
stream_type: Option<StreamType>, stream_type: Option<StreamType>,
#[clap(long)] #[clap(long, default_value = "plain")]
log_format: Option<log::LogFormat>, log_format: log::LogFormat,
#[clap(long, default_value = "stdout")]
log_to: log::LogOutput,
} }
impl SimulationApp { impl SimulationApp {
@ -49,6 +51,7 @@ impl SimulationApp {
input_settings, input_settings,
stream_type, stream_type,
log_format: _, log_format: _,
log_to: _,
} = self; } = self;
let simulation_settings: SimulationSettings = load_json_from_file(&input_settings)?; let simulation_settings: SimulationSettings = load_json_from_file(&input_settings)?;
@ -174,7 +177,7 @@ fn load_json_from_file<T: DeserializeOwned>(path: &Path) -> anyhow::Result<T> {
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let app: SimulationApp = SimulationApp::parse(); let app: SimulationApp = SimulationApp::parse();
log::config_tracing(app.log_format); log::config_tracing(app.log_format, &app.log_to);
if let Err(e) = app.run() { if let Err(e) = app.run() {
tracing::error!("error: {}", e); tracing::error!("error: {}", e);