use std::process;
use tokio::sync::watch;
use tracing::subscriber::SetGlobalDefaultError;
use crate::cancellation_token::CancellationToken;
#[must_use = "ctrlc_cancel_token should probably be used"]
pub struct InitResult {
pub ctrlc_cancel_token: CancellationToken,
}
pub fn init() -> InitResult {
if set_up_logging().is_err() {
tracing::debug!(
"Unable to set up the default tracing subscriber. Another one is probably already registered"
);
}
#[cfg(feature = "source-email-tokio-rustls")]
if tokio_rustls::rustls::crypto::aws_lc_rs::default_provider()
.install_default()
.is_err()
{
tracing::debug!("Unable to set up aws_lc as the default crypto provider for rustls");
}
InitResult {
ctrlc_cancel_token: set_up_ctrl_c_handler(),
}
}
pub fn set_up_logging() -> Result<(), SetGlobalDefaultError> {
use tracing::Level;
use tracing_subscriber::{
EnvFilter, Layer, filter::LevelFilter, fmt::time::OffsetTime, layer::SubscriberExt,
};
let env_filter = EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.from_env_lossy();
let is_debug_log_level = env_filter
.max_level_hint()
.map_or_else(|| false, |level| level >= Level::DEBUG);
let stdout = tracing_subscriber::fmt::layer()
.with_target(is_debug_log_level)
.with_file(is_debug_log_level)
.with_line_number(is_debug_log_level)
.with_thread_ids(is_debug_log_level)
.with_timer(OffsetTime::local_rfc_3339().expect("could not get local time offset"));
let stdout = if is_debug_log_level {
stdout.pretty().boxed()
} else {
stdout.boxed()
};
let journald = if cfg!(debug_assertions) {
None
} else {
tracing_journald::layer().ok()
};
let subscriber = tracing_subscriber::registry()
.with(journald.with_filter(LevelFilter::INFO))
.with(stdout.with_filter(env_filter));
tracing::subscriber::set_global_default(subscriber)
}
#[must_use]
pub fn set_up_ctrl_c_handler() -> CancellationToken {
let (shutdown_tx, shutdown_rx) = watch::channel(());
tokio::spawn(async move {
if let Err(e) = tokio::signal::ctrl_c().await {
tracing::error!("Failed to set up a CtrlC signal handler: {e}");
return;
}
_ = shutdown_tx.send(());
tracing::info!("Press Ctrl-C again to force close");
if let Err(e) = tokio::signal::ctrl_c().await {
tracing::error!("Failed to set up a CtrlC signal handler: {e}");
return;
}
tracing::info!("Force closing...");
#[expect(clippy::exit, reason = "user requested force close")]
process::exit(1);
});
CancellationToken(shutdown_rx)
}