summaryrefslogtreecommitdiff
path: root/libsyslog/src/builder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'libsyslog/src/builder.rs')
-rw-r--r--libsyslog/src/builder.rs127
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
+ }
+}
+