summaryrefslogtreecommitdiff
path: root/libsyslog/src/builder.rs
blob: c4b0781aaf20e0f0e54b1771d1fd24dc9e8d3333 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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
    }
}