use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;
use std::io::Write;
use std::io::stdout;
use std::sync::OnceLock;
use std::sync::RwLock;
use convert_case::Case;
use convert_case::Casing;
pub struct StatisticOptions<'a> {
statistic_prefix: &'a str,
after_statistics: Option<&'a str>,
statistics_casing: Option<Case<'static>>,
statistics_writer: Box<dyn Write + Send + Sync>,
}
impl Debug for StatisticOptions<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StatisticOptions")
.field("statistic_prefix", &self.statistic_prefix)
.field("after_statistics", &self.after_statistics)
.field("statistics_casing", &self.statistics_casing)
.field("statistics_writer", &"<Writer>")
.finish()
}
}
static STATISTIC_OPTIONS: OnceLock<RwLock<StatisticOptions>> = OnceLock::new();
pub fn configure_statistic_logging(
prefix: &'static str,
after: Option<&'static str>,
casing: Option<Case<'static>>,
writer: Option<Box<dyn Write + Send + Sync>>,
) {
let _ = STATISTIC_OPTIONS.get_or_init(|| {
RwLock::from(StatisticOptions {
statistic_prefix: prefix,
after_statistics: after,
statistics_casing: casing,
statistics_writer: writer.unwrap_or(Box::new(stdout())),
})
});
}
pub fn log_statistic(name: impl Display, value: impl Display) {
let Some(statistic_options_lock) = STATISTIC_OPTIONS.get() else {
return;
};
let Ok(mut statistic_options) = statistic_options_lock.write() else {
return;
};
let name = if let Some(casing) = &statistic_options.statistics_casing {
name.to_string().to_case(*casing)
} else {
name.to_string()
};
let prefix = statistic_options.statistic_prefix;
let _ = writeln!(
statistic_options.statistics_writer,
"{prefix} {name}={value}"
);
}
pub fn log_statistic_postfix() {
let Some(statistic_options_lock) = STATISTIC_OPTIONS.get() else {
return;
};
let Ok(mut statistic_options) = statistic_options_lock.write() else {
return;
};
let Some(post_fix) = statistic_options.after_statistics else {
return;
};
let _ = writeln!(statistic_options.statistics_writer, "{post_fix}");
}
pub fn should_log_statistics() -> bool {
STATISTIC_OPTIONS.get().is_some()
}