#[cfg(not(feature = "tracy"))] use std::fs;
use std::path::Path;
use termcolor::{ColorChoice, StandardStream};
use tracing::info;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::{
filter::LevelFilter, fmt::writer::MakeWriter, prelude::*, registry, EnvFilter,
};
const RUST_LOG_ENV: &str = "RUST_LOG";
pub fn init<W2>(log_path_file: Option<(&Path, &str)>, terminal: &'static W2) -> Vec<impl Drop>
where
W2: MakeWriter<'static> + 'static,
<W2 as MakeWriter<'static>>::Writer: 'static + Send + Sync,
{
#[cfg(not(feature = "tracy"))]
let mut guards: Vec<WorkerGuard> = Vec::new();
#[cfg(feature = "tracy")]
let guards: Vec<WorkerGuard> = Vec::new();
let mut filter = EnvFilter::default().add_directive(LevelFilter::INFO.into());
let default_directives = [
"dot_vox::parser=warn",
"veloren_common::trade=info",
"veloren_world::sim=info",
"veloren_world::civ=info",
"veloren_world::site::economy=info",
"veloren_server::events::entity_manipulation=info",
"hyper=info",
"prometheus_hyper=info",
"mio::poll=info",
"mio::sys::windows=info",
"h2=info",
"tokio_util=info",
"rustls=info",
"naga=info",
"gfx_backend_vulkan=info",
"wgpu_core=info",
"wgpu_core::device=warn",
"wgpu_core::swap_chain=info",
"veloren_network_protocol=info",
"quinn_proto::connection=info",
"refinery_core::traits::divergent=off",
"veloren_server::persistence::character=info",
"veloren_server::settings=info",
"veloren_query_server=info",
"symphonia_format_ogg::demuxer=off",
"symphonia_core::probe=off",
"wgpu_hal::dx12::device=off",
];
for s in default_directives {
filter = filter.add_directive(s.parse().unwrap());
}
match std::env::var(RUST_LOG_ENV) {
Ok(env) => {
for s in env.split(',') {
match s.parse() {
Ok(d) => filter = filter.add_directive(d),
Err(err) => eprintln!("WARN ignoring log directive: `{s}`: {err}"),
}
}
},
Err(std::env::VarError::NotUnicode(os_string)) => {
eprintln!("WARN ignoring log directives due to non-unicode data: {os_string:?}");
},
Err(std::env::VarError::NotPresent) => {},
};
let filter = filter; let registry = registry();
#[cfg(not(feature = "tracy"))]
let mut file_setup = false;
#[cfg(feature = "tracy")]
let file_setup = false;
#[cfg(feature = "tracy")]
let _terminal = terminal;
#[cfg(feature = "tracy")]
let registry = registry.with(tracing_tracy::TracyLayer::new(
tracing_tracy::DefaultConfig::default(),
));
#[cfg(not(feature = "tracy"))]
let registry = {
let (non_blocking, stdio_guard) = tracing_appender::non_blocking(terminal.make_writer());
guards.push(stdio_guard);
registry.with(tracing_subscriber::fmt::layer().with_writer(non_blocking))
};
#[cfg(not(feature = "tracy"))]
if let Some((path, file)) = log_path_file {
match fs::create_dir_all(path) {
Ok(_) => {
let file_appender = tracing_appender::rolling::never(path, file); let (non_blocking_file, file_guard) = tracing_appender::non_blocking(file_appender);
guards.push(file_guard);
file_setup = true;
registry
.with(tracing_subscriber::fmt::layer().with_writer(non_blocking_file))
.with(filter)
.init();
},
Err(e) => {
tracing::error!(
?e,
"Failed to create log file!. Falling back to terminal logging only.",
);
registry.with(filter).init();
},
}
} else {
registry.with(filter).init();
}
#[cfg(feature = "tracy")]
registry.with(filter).init();
if file_setup {
let (path, file) = log_path_file.unwrap();
info!(?path, ?file, "Setup terminal and file logging.");
}
if tracing::level_enabled!(tracing::Level::TRACE) {
info!("Tracing Level: TRACE");
} else if tracing::level_enabled!(tracing::Level::DEBUG) {
info!("Tracing Level: DEBUG");
};
guards
}
pub fn init_stdout(log_path_file: Option<(&Path, &str)>) -> Vec<impl Drop> {
init(log_path_file, &|| StandardStream::stdout(ColorChoice::Auto))
}