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
#![forbid(unsafe_code)]
use std;
use libc;
use log;
use log4rs;
use syslog;
#[derive(Deserialize)]
struct SyslogAppenderOpenlogConfig {
ident: String,
option: syslog::LogOption,
facility: syslog::Facility,
}
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Deserialize)]
#[allow(non_camel_case_types)]
enum FakeLibcLogLevel {
LOG_EMERG,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG,
}
type LevelMapConf = std::collections::BTreeMap<log::Level, FakeLibcLogLevel>;
#[derive(Deserialize)]
struct SyslogAppenderConfig {
openlog: Option<SyslogAppenderOpenlogConfig>,
encoder: Option<log4rs::encode::EncoderConfig>,
level_map: Option<LevelMapConf>,
}
struct SyslogAppenderDeserializer;
impl log4rs::file::Deserialize for SyslogAppenderDeserializer {
type Trait = log4rs::append::Append;
type Config = SyslogAppenderConfig;
fn deserialize(
&self,
config: Self::Config,
deserializers: &log4rs::file::Deserializers,
) -> Result<Box<Self::Trait>, Box<std::error::Error + Sync + Send>> {
let mut builder = syslog::SyslogAppender::builder();
if let Some(openlog_conf) = config.openlog {
builder = builder.openlog(
&openlog_conf.ident,
openlog_conf.option,
openlog_conf.facility,
);
};
if let Some(encoder_conf) = config.encoder {
builder = builder.encoder(deserializers.deserialize(&encoder_conf.kind, encoder_conf.config)?);
}
if let Some(level_map) = config.level_map {
let mut map = std::collections::BTreeMap::new();
for (level, libc_level) in level_map {
let libc_level = match libc_level {
FakeLibcLogLevel::LOG_EMERG => libc::LOG_EMERG,
FakeLibcLogLevel::LOG_ALERT => libc::LOG_ALERT,
FakeLibcLogLevel::LOG_CRIT => libc::LOG_CRIT,
FakeLibcLogLevel::LOG_ERR => libc::LOG_ERR,
FakeLibcLogLevel::LOG_WARNING => libc::LOG_WARNING,
FakeLibcLogLevel::LOG_NOTICE => libc::LOG_NOTICE,
FakeLibcLogLevel::LOG_INFO => libc::LOG_INFO,
FakeLibcLogLevel::LOG_DEBUG => libc::LOG_DEBUG,
};
let _ = map.insert(level, libc_level);
}
for level in &[
log::Level::Error,
log::Level::Warn,
log::Level::Info,
log::Level::Debug,
log::Level::Trace,
] {
let _ = map.get(level)
.ok_or_else(|| format!("Log level missing in map: {:?}", level))?;
}
builder = builder.level_map(Box::new(move |l| map[&l]));
}
Ok(Box::new(builder.build()))
}
}
pub fn register(deserializers: &mut log4rs::file::Deserializers) {
deserializers.insert("libc-syslog", SyslogAppenderDeserializer);
}