diff options
Diffstat (limited to 'libsyslog/src/builder.rs')
-rw-r--r-- | libsyslog/src/builder.rs | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/libsyslog/src/builder.rs b/libsyslog/src/builder.rs new file mode 100644 index 0000000..c4b0781 --- /dev/null +++ b/libsyslog/src/builder.rs @@ -0,0 +1,127 @@ +use { + crate::{ + Facility, + Syslog, + }, + + libsyslog_sys::*, + log::{ + LevelFilter, + }, + std::{ + env::args, + ffi::{ + CString, + NulError, + }, + os::raw::c_int, + }, +}; + +#[cfg(feature = "bitflags")] +use crate::Logopt; + +/// Builder used to create and customize the [Syslog][Syslog] logger object. +#[derive(Debug,Default)] +pub struct SyslogBuilder { + facility_opt: Option<c_int>, + ident_opt: Option<CString>, + level_opt: Option<LevelFilter>, + logopt_opt: Option<c_int>, + module_levels: Vec<(String, LevelFilter)>, +} + +impl SyslogBuilder { + fn ident_from_argv() -> CString { + let argv0 = args().next().unwrap_or_default(); + let program = match argv0.rsplit_once('/') { + Some((_, filename)) => filename, + None => argv0.as_str(), + }; + CString::new(program).unwrap_or_default() + } + + #[must_use = "Syslog only gets active after calling .init() on it."] + pub fn build(self) -> Syslog { + //! Consumes `self` and returns a freshly created [`Syslog`] logger object. To be called at + //! the end of the builder chain, after all other methods on the [`SyslogBuilder`] object. + + let facility = self.facility_opt.unwrap_or(Facility::default() as c_int); + let ident = self.ident_opt.unwrap_or_else(Self::ident_from_argv); + let level = self.level_opt.unwrap_or(LevelFilter::Info); + let logopt = self.logopt_opt.unwrap_or(LOG_PID); + let module_levels = self.module_levels; + + Syslog { + facility, + ident, + level, + logopt, + module_levels, + } + } + + #[must_use = "No Syslog is constructed unless .build() is called."] + pub fn facility(mut self, facility: Facility) -> Self { + //! Sets logging facility to given [`Facility`] value. + + self.facility_opt = Some(facility as c_int); + self + } + + #[must_use = "No Syslog is constructed unless .build() is called."] + pub fn facility_raw(mut self, facility: c_int) -> Self { + //! Sets logging facility to unchecked `c_int` value. Can be used for + //! setting a raw [libsyslog-sys][libsyslog_sys] constant directly. + + self.facility_opt = Some(facility); + self + } + + #[must_use = "No Syslog is constructed unless .build() is called."] + pub fn ident<T: Into<Vec<u8>>>(mut self, ident: T) -> Result<Self, NulError> { + //! Sets ident to the string like argument provided. By default ident is + //! derived from the name of the executable. + + self.ident_opt = Some(CString::new(ident)?); + Ok(self) + } + + #[must_use = "No Syslog is constructed unless .build() is called."] + pub fn level(mut self, level: LevelFilter) -> Self { + //! Sets global log level to be used when no + //! [module_level][`SyslogBuilder::module_level`] rule matches. + + self.level_opt = Some(level); + self + } + + #[cfg(feature = "bitflags")] + #[must_use = "No Syslog is constructed unless .build() is called."] + pub fn logopt(mut self, logopt: Logopt) -> Self { + //! Sets logopt to to given [`Logopt`] value. + + self.logopt_opt = Some(logopt.bits()); + self + } + + #[must_use = "No Syslog is constructed unless .build() is called."] + pub fn logopt_raw(mut self, logopt: c_int) -> Self { + //! Sets logopt to unchecked `c_int` value. Can be used for setting a raw + //! [libsyslog-sys][libsyslog_sys] constant directly. + + self.logopt_opt = Some(logopt); + self + } + + #[must_use = "No Syslog is constructed unless .build() is called."] + pub fn module_level(mut self, target: &str, level: LevelFilter) -> Self { + //! Sets log level for specified target Rust module. Multiple calls to this + //! method is possible and will set multiple filters. More specific filters + //! on children will override those of their parent modules. + + self.module_levels.push((target.to_string(), level)); + self + } +} + |