Skip to main content

syslog_rs/formatters/
mod.rs

1/*-
2 * syslog-rs - a syslog client translated from libc to rust
3 * 
4 * Copyright 2025 Aleksandr Morozov
5 * 
6 * The syslog-rs crate can be redistributed and/or modified
7 * under the terms of either of the following licenses:
8 *
9 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
10 *
11 *   2. The MIT License (MIT)
12 *                     
13 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
14 */
15
16/// A list of build-in formatters.
17/// 
18/// Excluding Windows specific.
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum SyslogFormatters
21{
22    FormatRfc3146,
23    FormatRfc5424,
24    FormatFile,
25}
26
27impl FromStr for SyslogFormatters
28{
29    type Err = SyslogError;
30
31    fn from_str(s: &str) -> Result<Self, Self::Err> 
32    {
33        let s_up = s.to_ascii_uppercase();
34
35        match s_up.as_str()
36        {
37            Self::FORMAT_RFC3146_NAME => 
38                return Ok(Self::FormatRfc3146),
39            Self::FORMAT_RFC5424_NAME => 
40                return Ok(Self::FormatRfc5424),
41            Self::FORMAT_FILE_NAME => 
42                return Ok(Self::FormatFile),
43            n => 
44                throw_error!("unknown syslog formatter: {}", n)
45        }
46    }
47}
48
49impl SyslogFormatters
50{
51    pub const FORMAT_RFC3146_NAME: &'static str = FormatRfc3146::FORMATTER_NAME;
52    pub const FORMAT_RFC5424_NAME: &'static str = FormatRfc5424::FORMATTER_NAME;
53    pub const FORMAT_FILE_NAME: &'static str = FormatFile::FORMATTER_NAME;
54}
55
56/// A container which holds the formatted message and a range of slices 
57/// which are suitable for the stderror output or syscons output. 
58/// Normally, the `stderr_range` is a message without `PRI` and other headers
59/// 
60/// For example for the message type <34> Mon 12 ... the stderr_tange can be 1.. 
61/// which will exclude the <34>.
62#[derive(Debug)]
63pub struct SyslogFormatted
64{
65    /// A header
66    msg_header: Option<String>,
67
68    /// A msg which is sent to stderr if needed. Usually this is a message without PRI
69    msg_payload: String,
70
71    /// A cache in case if it will be reqired to obtain a full message which consists
72    /// from header and payload.
73    full_msg: Option<String>,
74}
75
76impl SyslogFormatted
77{
78    /// Constructs new container.
79    pub 
80    fn new(msg_header: Option<String>, msg_payload: String) -> Self
81    {
82        return Self{ msg_header: msg_header, msg_payload: msg_payload, full_msg: None };
83    }
84
85    /// Returns the payload without header.
86    pub(crate) 
87    fn get_stderr_output(&self) -> &str
88    {
89        return &self.msg_payload;
90    }
91
92    /// Returns the concatinated message (headr+payload) or just a payload
93    /// if header does not present.
94    pub(crate) 
95    fn get_full_msg(&mut self) -> &str
96    {
97        if self.full_msg.is_some() == true
98        {
99            return self.full_msg.as_ref().unwrap();
100        }
101        else
102        {
103            let header= 
104                if self.msg_header.is_some() == true
105                {
106                    let msg = [self.msg_header.as_ref().unwrap().as_str(), self.msg_payload.as_str()].concat();
107
108                    self.full_msg.replace(msg);
109
110                    self.full_msg.as_ref().unwrap().as_str()
111                }
112                else
113                {
114                    self.msg_payload.as_ref()
115                };
116
117            return header;
118        }
119    }
120}
121
122/// A trait for the custom syslog formatter.
123pub trait SyslogFormatter: std::fmt::Debug + Send + Sync + Clone + From<String> + From<&'static str> + 'static
124{
125    // Should return the identification of the 
126    //fn get_formatter_type(&self) -> &'static str;
127
128    /// Formats the message for the syslog server with specific protocol or
129    /// RFC.
130    /// 
131    /// # Arguments
132    /// 
133    /// * `max_msg_size` - a max msg size in bytes.
134    /// 
135    /// * `prifac` - a [SyslogMsgPriFac] a prepared PRI header value.
136    /// 
137    /// * `progname` - a ref to program name or identifier which is set during init.
138    /// 
139    /// * `pid` - an [Option] value where inner constains a PID number already converted 
140    ///     into `string` form. If [Option::None] is provided, a [crate::LogStat::LOG_PID] was
141    ///     not set during init. The formatter must exclude the `PID` from the report.
142    /// 
143    /// # Returns
144    /// 
145    /// A [SyslogFormatted] should be returned.
146    fn vsyslog1_format(&self, max_msg_size: usize, prifac: SyslogMsgPriFac, progname: &str, pid: Option<&str>) -> SyslogFormatted;
147}
148
149/// A windows specific formatter (which is not bounded to any standart). 
150/// Used for Windows Event Log and not appliciable to the rest logging.
151#[cfg(target_os = "windows")]
152pub mod windows_10;
153
154/// RFC3146 based formatter.
155pub mod syslog_3146;
156
157/// RFC5424 based formatter.
158pub mod syslog_5424;
159
160/// Formatter for local file (which is not bounded to any standart).
161pub mod syslog_file;
162
163use std::str::FromStr;
164
165pub use syslog_3146::FormatRfc3146;
166pub use syslog_5424::FormatRfc5424;
167pub use syslog_file::FormatFile;
168
169#[cfg(target_os = "windows")]
170pub use windows_10::FormatWindows;
171
172use crate::{SyslogMsgPriFac, error::SyslogError, throw_error};
173
174/// A default syslog formatter. For GNU/Linux it is RFC3146
175#[cfg(target_os = "linux")]
176pub type DefaultSyslogFormatter = FormatRfc3146;
177
178/// A default syslog formatter. For GNU/Linux it is RFC3146 (as a runtime type)
179#[cfg(target_os = "linux")]
180pub const DEFAULT_SYSLOG_FORMATTER_TYPE: SyslogFormatters = SyslogFormatters::FormatRfc3146;
181
182/// A default syslog formatter. For xBSD it is RFC5424
183#[cfg(any(
184    target_os = "freebsd",
185    target_os = "dragonfly",
186    target_os = "openbsd",
187    target_os = "netbsd",
188    target_os = "macos"
189))]
190pub type DefaultSyslogFormatter = FormatRfc5424;
191
192/// A default syslog formatter. For xBSD it is RFC5424 (as a runtime type)
193#[cfg(any(
194    target_os = "freebsd",
195    target_os = "dragonfly",
196    target_os = "openbsd",
197    target_os = "netbsd",
198    target_os = "macos"
199))]
200pub const DEFAULT_SYSLOG_FORMATTER_TYPE: SyslogFormatters = SyslogFormatters::FormatRfc5424;
201
202/// If the crate is compiled on the Windows OS, the value is set to 
203/// the one which is for the Local Windows Event Log because by default
204/// the default syslog instance is `local`. You must override the value
205/// if working with remote or local syslog.
206#[cfg(target_os = "windows")]
207pub type DefaultSyslogFormatter = FormatWindows;
208
209/// A default syslog message formatter for local files.
210pub type DefaultSyslogFormatterFile = FormatFile;