From: Ian Jackson Date: Sun, 18 Sep 2022 18:01:49 +0000 (+0100) Subject: syslog: Add syslog support X-Git-Tag: hippotat/1.0.0~73 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=9762acc40258e1cefdced06c7f87be8f39979c08;p=hippotat.git syslog: Add syslog support Signed-off-by: Ian Jackson --- diff --git a/Cargo.lock b/Cargo.lock index 79c9711..d2a14c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -180,6 +180,15 @@ dependencies = [ "termcolor", ] +[[package]] +name = "error-chain" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +dependencies = [ + "version_check", +] + [[package]] name = "extend" version = "1.1.1" @@ -437,6 +446,7 @@ dependencies = [ "sha2", "structopt", "subtle", + "syslog", "thiserror", "tokio", "void", @@ -452,6 +462,17 @@ dependencies = [ "syn", ] +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + [[package]] name = "http" version = "0.2.4" @@ -460,7 +481,7 @@ checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 0.4.7", ] [[package]] @@ -507,7 +528,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.7", "pin-project-lite", "socket2", "tokio", @@ -575,6 +596,12 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + [[package]] name = "lazy-regex" version = "2.2.1" @@ -606,9 +633,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "lock_api" @@ -628,6 +655,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "memchr" version = "2.4.0" @@ -709,6 +742,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.26.0" @@ -1077,6 +1119,19 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "syslog" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978044cc68150ad5e40083c9f6a725e6fd02d7ba1bcf691ec2ff0d66c0b41acc" +dependencies = [ + "error-chain", + "hostname", + "libc", + "log", + "time", +] + [[package]] name = "tempfile" version = "3.2.0" @@ -1129,6 +1184,17 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" +dependencies = [ + "itoa 1.0.3", + "libc", + "num_threads", +] + [[package]] name = "tokio" version = "1.8.2" diff --git a/Cargo.toml b/Cargo.toml index e6c0659..2d6289b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ pin-project-lite = "0.2" sha2 = "0.9" structopt = "0.3" subtle = "2" +syslog = "6" tokio = { version = "1", features = ["full"] } thiserror = "1" void = "1" diff --git a/src/reporter.rs b/src/reporter.rs index 6f4fb0d..49c26a2 100644 --- a/src/reporter.rs +++ b/src/reporter.rs @@ -7,27 +7,99 @@ use crate::prelude::*; #[derive(StructOpt,Debug)] pub struct LogOpts { /// Increase debug level + /// + /// May be repeated for more verbosity. + /// + /// When using syslog, one `-D` this arranges to send to syslog even + /// trace messages (mapped onto syslog level `DEBUG`); + /// and two -`D` means to send to syslog even messages from lower layers + /// (normally just the hippotat modules log to + /// syslog). #[structopt(long, short="D", parse(from_occurrences))] debug: usize, + + /// Syslog facility to use + #[structopt(long, parse(try_from_str=parse_syslog_facility))] + syslog_facility: Option, +} + +#[throws(AE)] +fn parse_syslog_facility(s: &str) -> syslog::Facility { + s.parse().map_err(|()| anyhow!("unrecognised syslog facility: {:?}", s))? +} + +#[derive(Debug)] +struct FilteringLogWrapper(T); + +impl FilteringLogWrapper { + fn wanted(&self, md: &log::Metadata<'_>) -> bool { + let first = |mod_path| { + let mod_path: &str = mod_path; // can't do in args as breaks lifetimes + mod_path.split_once("::").map(|s| s.0).unwrap_or(mod_path) + }; + first(md.target()) == first(module_path!()) + } +} + +impl log::Log for FilteringLogWrapper where T: log::Log { + fn enabled(&self, md: &log::Metadata<'_>) -> bool { + self.wanted(md) && self.0.enabled(md) + } + + fn log(&self, record: &log::Record<'_>) { + if self.wanted(record.metadata()) { + self.0.log(record) + } + } + + fn flush(&self) { + self.0.flush() + } } impl LogOpts { #[throws(AE)] pub fn log_init(&self) { - let env = env_logger::Env::new() - .filter("HIPPOTAT_LOG") - .write_style("HIPPOTAT_LOG_STYLE"); + if let Some(facility) = self.syslog_facility { + let f = syslog::Formatter3164 { + facility, + hostname: None, + process: "hippotatd".into(), + pid: std::process::id(), + }; + let l = syslog::unix(f) + // syslog::Error is not Sync. + // https://github.com/Geal/rust-syslog/issues/65 + .map_err(|e| anyhow!(e.to_string())) + .context("set up syslog logger")?; + let l = syslog::BasicLogger::new(l); + let l = if self.debug < 2 { + Box::new(FilteringLogWrapper(l)) as _ + } else { + Box::new(l) as _ + }; + log::set_boxed_logger(l).context("install syslog logger")?; + log::set_max_level(if self.debug < 1 { + log::LevelFilter::Debug + } else { + log::LevelFilter::Trace + }); + } else { + let env = env_logger::Env::new() + .filter("HIPPOTAT_LOG") + .write_style("HIPPOTAT_LOG_STYLE"); - let mut logb = env_logger::Builder::new(); - logb.filter(Some("hippotat"), - *[ log::LevelFilter::Info, - log::LevelFilter::Debug ] - .get(self.debug) - .unwrap_or( - &log::LevelFilter::Trace - )); - logb.parse_env(env); - logb.init(); + let mut logb = env_logger::Builder::new(); + logb.filter(Some("hippotat"), + *[ log::LevelFilter::Info, + log::LevelFilter::Debug ] + .get(self.debug) + .unwrap_or( + &log::LevelFilter::Trace + )); + logb.parse_env(env); + logb.init(); + } } }