use std::sync::atomic::{AtomicU8, Ordering};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u8)]
pub enum ErrlogSevEnum {
Info = 0,
Minor = 1,
Major = 2,
Fatal = 3,
}
impl ErrlogSevEnum {
pub fn as_str(self) -> &'static str {
match self {
ErrlogSevEnum::Info => "info",
ErrlogSevEnum::Minor => "minor",
ErrlogSevEnum::Major => "major",
ErrlogSevEnum::Fatal => "fatal",
}
}
fn from_u8(v: u8) -> ErrlogSevEnum {
match v {
0 => ErrlogSevEnum::Info,
1 => ErrlogSevEnum::Minor,
2 => ErrlogSevEnum::Major,
_ => ErrlogSevEnum::Fatal,
}
}
}
pub fn errlog_sev_enum_string(severity: ErrlogSevEnum) -> &'static str {
severity.as_str()
}
static SEV_TO_LOG: AtomicU8 = AtomicU8::new(ErrlogSevEnum::Minor as u8);
pub fn errlog_set_sev_to_log(severity: ErrlogSevEnum) {
SEV_TO_LOG.store(severity as u8, Ordering::Relaxed);
}
pub fn errlog_get_sev_to_log() -> ErrlogSevEnum {
ErrlogSevEnum::from_u8(SEV_TO_LOG.load(Ordering::Relaxed))
}
pub fn errlog_sev_printf(severity: ErrlogSevEnum, message: &str) -> bool {
if severity < errlog_get_sev_to_log() {
return false;
}
let line = format!("sevr={} {}", severity.as_str(), message);
match severity {
ErrlogSevEnum::Info => {
tracing::info!(target: "epics_base_rs::errlog", "{line}")
}
ErrlogSevEnum::Minor => {
tracing::warn!(target: "epics_base_rs::errlog", "{line}")
}
ErrlogSevEnum::Major | ErrlogSevEnum::Fatal => {
tracing::error!(target: "epics_base_rs::errlog", "{line}")
}
}
true
}
#[macro_export]
macro_rules! rt_debug {
($($arg:tt)*) => {
::tracing::debug!(target: "epics_base_rs::runtime", "{}", format!($($arg)*));
};
}
#[macro_export]
macro_rules! rt_info {
($($arg:tt)*) => {
::tracing::info!(target: "epics_base_rs::runtime", "{}", format!($($arg)*));
};
}
#[macro_export]
macro_rules! rt_warn {
($($arg:tt)*) => {
::tracing::warn!(target: "epics_base_rs::runtime", "{}", format!($($arg)*));
};
}
#[macro_export]
macro_rules! rt_error {
($($arg:tt)*) => {
::tracing::error!(target: "epics_base_rs::runtime", "{}", format!($($arg)*));
};
}
#[cfg(test)]
mod tests {
use super::*;
use serial_test::serial;
#[test]
fn test_log_macros_compile() {
rt_debug!("debug message {}", 42);
rt_info!("info message");
rt_warn!("warn: {}", "something");
rt_error!("error: {} {}", "bad", "thing");
}
#[test]
fn sev_enum_strings_match_c() {
assert_eq!(errlog_sev_enum_string(ErrlogSevEnum::Info), "info");
assert_eq!(errlog_sev_enum_string(ErrlogSevEnum::Minor), "minor");
assert_eq!(errlog_sev_enum_string(ErrlogSevEnum::Major), "major");
assert_eq!(errlog_sev_enum_string(ErrlogSevEnum::Fatal), "fatal");
}
#[test]
fn sev_enum_ordering() {
assert!(ErrlogSevEnum::Info < ErrlogSevEnum::Minor);
assert!(ErrlogSevEnum::Minor < ErrlogSevEnum::Major);
assert!(ErrlogSevEnum::Major < ErrlogSevEnum::Fatal);
}
#[test]
#[serial(errlog_sev)]
fn sev_to_log_threshold_roundtrips() {
errlog_set_sev_to_log(ErrlogSevEnum::Major);
assert_eq!(errlog_get_sev_to_log(), ErrlogSevEnum::Major);
errlog_set_sev_to_log(ErrlogSevEnum::Minor);
assert_eq!(errlog_get_sev_to_log(), ErrlogSevEnum::Minor);
}
#[test]
#[serial(errlog_sev)]
fn sev_printf_suppresses_below_threshold() {
errlog_set_sev_to_log(ErrlogSevEnum::Major);
assert!(!errlog_sev_printf(ErrlogSevEnum::Info, "quiet"));
assert!(!errlog_sev_printf(ErrlogSevEnum::Minor, "quiet"));
assert!(errlog_sev_printf(ErrlogSevEnum::Major, "loud"));
assert!(errlog_sev_printf(ErrlogSevEnum::Fatal, "loud"));
errlog_set_sev_to_log(ErrlogSevEnum::Minor);
}
}