log4rs_syslog_net/
rfc5424.rs

1use crate::consts::{level_to_severity, Facility, NILVALUE};
2use log::Record;
3use log4rs::encode::writer::simple::SimpleWriter;
4use log4rs::encode::Encode;
5use std::error::Error;
6use std::sync::Arc;
7
8#[derive(Clone, Debug)]
9pub struct Format {
10    facility: Facility,
11    hostname: String,
12    app_name: String,
13    proc_id: String,
14    encoder: std::sync::Arc<dyn log4rs::encode::Encode>,
15}
16
17impl Default for Format {
18    fn default() -> Self {
19        Format::new()
20    }
21}
22
23impl Format {
24    pub fn new() -> Self {
25        Format {
26            facility: Facility::LOCAL0,
27            hostname: "".to_string(),
28            app_name: "".to_string(),
29            proc_id: format!("{}", std::process::id()),
30            encoder: Arc::new(log4rs::encode::pattern::PatternEncoder::default()),
31        }
32    }
33
34    pub fn facility(mut self, facility: Facility) -> Self {
35        self.facility = facility;
36        self
37    }
38
39    pub fn hostname<S: Into<String>>(mut self, hostname: S) -> Self {
40        self.hostname = hostname.into();
41        self
42    }
43    pub fn encoder<E: Encode>(mut self, encoder: E) -> Self {
44        self.encoder = Arc::new(encoder) as Arc<dyn Encode + 'static>;
45        self
46    }
47
48    pub fn app_name<S: Into<String>>(mut self, app_name: S) -> Self {
49        self.app_name = app_name.into();
50        self
51    }
52
53    pub fn proc_id<S: Into<String>>(mut self, proc_id: S) -> Self {
54        self.proc_id = proc_id.into();
55        self
56    }
57}
58
59impl log4rs::encode::Encode for Format {
60    fn encode(
61        &self,
62        w: &mut dyn log4rs::encode::Write,
63        record: &Record<'_>,
64    ) -> Result<(), Box<dyn Error + Sync + Send>> {
65        let priority = self.facility as u8 | level_to_severity(record.level());
66        let msg_id = 0;
67        let struct_data = NILVALUE;
68
69        let mut buf: Vec<u8> = Vec::new();
70        self.encoder.encode(&mut SimpleWriter(&mut buf), record)?;
71        let msg = String::from_utf8_lossy(&buf);
72
73        let msg = format!(
74            "<{}>{} {} {} {} {} {} {} {}\n",
75            priority,
76            1,
77            chrono::Utc::now(),
78            self.hostname,
79            self.app_name,
80            self.proc_id,
81            msg_id,
82            struct_data,
83            msg
84        );
85
86        w.write_all(msg.as_bytes())?;
87
88        Ok(())
89    }
90}