epics_base_rs/runtime/
log.rs1use std::sync::atomic::{AtomicU8, Ordering};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
22#[repr(u8)]
23pub enum ErrlogSevEnum {
24 Info = 0,
26 Minor = 1,
28 Major = 2,
30 Fatal = 3,
32}
33
34impl ErrlogSevEnum {
35 pub fn as_str(self) -> &'static str {
37 match self {
38 ErrlogSevEnum::Info => "info",
39 ErrlogSevEnum::Minor => "minor",
40 ErrlogSevEnum::Major => "major",
41 ErrlogSevEnum::Fatal => "fatal",
42 }
43 }
44
45 fn from_u8(v: u8) -> ErrlogSevEnum {
46 match v {
47 0 => ErrlogSevEnum::Info,
48 1 => ErrlogSevEnum::Minor,
49 2 => ErrlogSevEnum::Major,
50 _ => ErrlogSevEnum::Fatal,
51 }
52 }
53}
54
55pub fn errlog_sev_enum_string(severity: ErrlogSevEnum) -> &'static str {
61 severity.as_str()
62}
63
64static SEV_TO_LOG: AtomicU8 = AtomicU8::new(ErrlogSevEnum::Minor as u8);
68
69pub fn errlog_set_sev_to_log(severity: ErrlogSevEnum) {
73 SEV_TO_LOG.store(severity as u8, Ordering::Relaxed);
74}
75
76pub fn errlog_get_sev_to_log() -> ErrlogSevEnum {
79 ErrlogSevEnum::from_u8(SEV_TO_LOG.load(Ordering::Relaxed))
80}
81
82pub fn errlog_sev_printf(severity: ErrlogSevEnum, message: &str) -> bool {
91 if severity < errlog_get_sev_to_log() {
92 return false;
93 }
94 let line = format!("sevr={} {}", severity.as_str(), message);
95 match severity {
96 ErrlogSevEnum::Info => {
97 tracing::info!(target: "epics_base_rs::errlog", "{line}")
98 }
99 ErrlogSevEnum::Minor => {
100 tracing::warn!(target: "epics_base_rs::errlog", "{line}")
101 }
102 ErrlogSevEnum::Major | ErrlogSevEnum::Fatal => {
103 tracing::error!(target: "epics_base_rs::errlog", "{line}")
104 }
105 }
106 true
107}
108
109#[macro_export]
111macro_rules! rt_debug {
112 ($($arg:tt)*) => {
113 ::tracing::debug!(target: "epics_base_rs::runtime", "{}", format!($($arg)*));
114 };
115}
116
117#[macro_export]
119macro_rules! rt_info {
120 ($($arg:tt)*) => {
121 ::tracing::info!(target: "epics_base_rs::runtime", "{}", format!($($arg)*));
122 };
123}
124
125#[macro_export]
127macro_rules! rt_warn {
128 ($($arg:tt)*) => {
129 ::tracing::warn!(target: "epics_base_rs::runtime", "{}", format!($($arg)*));
130 };
131}
132
133#[macro_export]
135macro_rules! rt_error {
136 ($($arg:tt)*) => {
137 ::tracing::error!(target: "epics_base_rs::runtime", "{}", format!($($arg)*));
138 };
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use serial_test::serial;
145
146 #[test]
147 fn test_log_macros_compile() {
148 rt_debug!("debug message {}", 42);
149 rt_info!("info message");
150 rt_warn!("warn: {}", "something");
151 rt_error!("error: {} {}", "bad", "thing");
152 }
153
154 #[test]
155 fn sev_enum_strings_match_c() {
156 assert_eq!(errlog_sev_enum_string(ErrlogSevEnum::Info), "info");
158 assert_eq!(errlog_sev_enum_string(ErrlogSevEnum::Minor), "minor");
159 assert_eq!(errlog_sev_enum_string(ErrlogSevEnum::Major), "major");
160 assert_eq!(errlog_sev_enum_string(ErrlogSevEnum::Fatal), "fatal");
161 }
162
163 #[test]
164 fn sev_enum_ordering() {
165 assert!(ErrlogSevEnum::Info < ErrlogSevEnum::Minor);
166 assert!(ErrlogSevEnum::Minor < ErrlogSevEnum::Major);
167 assert!(ErrlogSevEnum::Major < ErrlogSevEnum::Fatal);
168 }
169
170 #[test]
171 #[serial(errlog_sev)]
172 fn sev_to_log_threshold_roundtrips() {
173 errlog_set_sev_to_log(ErrlogSevEnum::Major);
174 assert_eq!(errlog_get_sev_to_log(), ErrlogSevEnum::Major);
175 errlog_set_sev_to_log(ErrlogSevEnum::Minor);
177 assert_eq!(errlog_get_sev_to_log(), ErrlogSevEnum::Minor);
178 }
179
180 #[test]
181 #[serial(errlog_sev)]
182 fn sev_printf_suppresses_below_threshold() {
183 errlog_set_sev_to_log(ErrlogSevEnum::Major);
184 assert!(!errlog_sev_printf(ErrlogSevEnum::Info, "quiet"));
186 assert!(!errlog_sev_printf(ErrlogSevEnum::Minor, "quiet"));
187 assert!(errlog_sev_printf(ErrlogSevEnum::Major, "loud"));
189 assert!(errlog_sev_printf(ErrlogSevEnum::Fatal, "loud"));
190 errlog_set_sev_to_log(ErrlogSevEnum::Minor);
191 }
192}