1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[derive(Serialize, Deserialize)]
#[serde(default)]
pub struct LoggingConfiguration
{
pub syslog_facility: SyslogFacility,
pub syslog_priority: SyslogPriority,
pub identity: String,
pub enable_full_rust_stack_back_traces: bool,
}
impl Default for LoggingConfiguration
{
#[inline(always)]
fn default() -> Self
{
Self
{
syslog_facility: Default::default(),
syslog_priority: Default::default(),
identity: get_program_name(),
enable_full_rust_stack_back_traces: true,
}
}
}
impl LoggingConfiguration
{
#[inline(always)]
pub fn warn(name: &str, message: String)
{
let name = to_c_string_robustly(name);
let message = to_c_string_robustly(message);
unsafe { syslog(LOG_WARNING, b"%s:%s\0".as_ptr() as *const _ as *const _, name.as_ptr(), message.as_ptr()) };
}
#[inline(always)]
fn caught_panic(source_file: &str, line_number: u32, column_number: u32, cause: &str)
{
let source_file = to_c_string_robustly(source_file);
let cause = to_c_string_robustly(cause);
unsafe { syslog(LOG_CRIT, b"File:%s:Line:%u:Column:%u:Cause:%s\0".as_ptr() as *const _ as *const _, source_file, line_number, column_number, cause) }
}
#[inline(always)]
pub fn start_logging(&self, running_interactively: bool)
{
self.configure_rust_stack_back_traces();
self.configure_syslog(running_interactively);
self.configure_panic_hook()
}
#[inline(always)]
pub fn stop_logging(&self)
{
drop(take_hook());
unsafe { closelog() }
}
#[inline(always)]
fn configure_rust_stack_back_traces(&self)
{
let setting = if self.enable_full_rust_stack_back_traces
{
"1"
}
else
{
"0"
};
set_var("RUST_BACKTRACE", setting);
}
#[inline(always)]
fn configure_syslog(&self, running_interactively_so_also_log_to_standard_error: bool)
{
unsafe { setlogmask(self.syslog_priority.log_upto()) };
let mut log_options = LOG_PID | LOG_NDELAY;
if running_interactively_so_also_log_to_standard_error
{
log_options |= LOG_PERROR;
}
let identity = CString::new(self.identity.as_str()).unwrap();
unsafe { openlog(identity.as_ptr(), log_options, self.syslog_facility as i32) }
}
#[inline(always)]
fn configure_panic_hook(&self)
{
set_hook(Box::new(|panic_info|
{
let (source_file, line_number, column_number) = match panic_info.location()
{
None => ("(unknown source file)", 0, 0),
Some(location) => (location.file(), location.line(), location.column())
};
let cause = panic_payload_to_cause(panic_info.payload());
Self::caught_panic(source_file, line_number, column_number, &cause)
}));
}
}