log4rs_syslog_net/
rfc5425.rs

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