summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2019-04-27 01:05:09 +0200
committerMatthias Beyer <mail@beyermatthias.de>2019-05-30 09:32:07 +0200
commit185ec25b9e388bb76b21c212b4a4123f5533f71d (patch)
tree91ce962fb7094b349c204754aef9d9bdb18f5f21
parentb1330c9916453073a32d429346bd3c0125dd6a45 (diff)
downloadimag-185ec25b9e388bb76b21c212b4a4123f5533f71d.zip
imag-185ec25b9e388bb76b21c212b4a4123f5533f71d.tar.gz
Rewrite logging config deserialization
This patch rewrites the logging config deserialization. It removes the manual traversing of the config toml structure and replaces it with types which implement `Deserialize`, which is way more convenient and easy to read (and extend). Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r--lib/core/libimagrt/Cargo.toml2
-rw-r--r--lib/core/libimagrt/src/lib.rs2
-rw-r--r--lib/core/libimagrt/src/logger.rs143
3 files changed, 78 insertions, 69 deletions
diff --git a/lib/core/libimagrt/Cargo.toml b/lib/core/libimagrt/Cargo.toml
index 63e97ee..31a04a8 100644
--- a/lib/core/libimagrt/Cargo.toml
+++ b/lib/core/libimagrt/Cargo.toml
@@ -29,6 +29,8 @@ toml-query = "0.9"
atty = "0.2"
failure = "0.1"
failure_derive = "0.1"
+serde_derive = "1"
+serde = "1"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
diff --git a/lib/core/libimagrt/src/lib.rs b/lib/core/libimagrt/src/lib.rs
index 825b49e..4247ff6 100644
--- a/lib/core/libimagrt/src/lib.rs
+++ b/lib/core/libimagrt/src/lib.rs
@@ -41,6 +41,8 @@
extern crate itertools;
extern crate ansi_term;
extern crate handlebars;
+extern crate serde;
+#[macro_use] extern crate serde_derive;
#[macro_use] extern crate failure;
extern crate clap;
diff --git a/lib/core/libimagrt/src/logger.rs b/lib/core/libimagrt/src/logger.rs
index ef586bb..8aabcb5 100644
--- a/lib/core/libimagrt/src/logger.rs
+++ b/lib/core/libimagrt/src/logger.rs
@@ -349,79 +349,84 @@ mod log_lvl_aggregate {
fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
-> Result<BTreeMap<ModuleName, ModuleSettings>>
{
- // Helper macro to return the error from Some(Err(_)) and map everything else to an
- // Option<_>
- macro_rules! inner_try {
- ($v:expr) => {
- match $v {
- Some(Ok(v)) => Some(v),
- Some(Err(e)) => return Err(e),
- None => None,
+ use toml_query::read::Partial;
+ use std::convert::TryInto;
+
+ #[derive(Serialize, Deserialize, Debug)]
+ struct LoggingModuleConfig {
+ pub destinations: Option<Vec<String>>,
+ pub level: Option<LogLevel>,
+ pub enabled: bool,
+ }
+
+ #[derive(Serialize, Deserialize, Debug)]
+ enum LogLevel {
+ #[serde(rename = "trace")]
+ Trace,
+
+ #[serde(rename = "debug")]
+ Debug,
+
+ #[serde(rename = "info")]
+ Info,
+
+ #[serde(rename = "warn")]
+ Warn,
+
+ #[serde(rename = "error")]
+ Error,
+ }
+
+ impl Into<Level> for LogLevel {
+ fn into(self) -> Level {
+ match self {
+ LogLevel::Trace => Level::Trace,
+ LogLevel::Debug => Level::Debug,
+ LogLevel::Info => Level::Info,
+ LogLevel::Warn => Level::Warn,
+ LogLevel::Error => Level::Error,
}
}
- };
+ }
- match config {
- Some(cfg) => match cfg.read("imag.logging.modules").map_err(Error::from) {
- Ok(Some(&Value::Table(ref t))) => {
- // translate the module settings from the table `t`
- let mut settings = BTreeMap::new();
-
- for (module_name, v) in t {
- let destinations = inner_try! {
- v.read("destinations")
- .context("Failed reading header 'destinations'")
- .map_err(Error::from)
- .context(EM::TomlQueryError)?
- .map(|val| {
- val.as_array()
- .ok_or_else(|| {
- let msg = "Type error at 'imag.logging.modules.<mod>.destinations', expected 'Array'";
- Error::from(err_msg(msg))
- })
- .and_then(translate_destinations)
- })
- };
-
- let level = inner_try! {
- v.read_string("level")
- .context("Failed reading header 'level'")
- .map_err(Error::from)
- .context(EM::TomlQueryError)?
- .map(|s| match_log_level_str(&s))
- };
-
- let enabled = v.read("enabled")
- .map_err(Error::from)
- .context(EM::TomlQueryError)?
- .map(|v| v.as_bool().unwrap_or(false))
- .ok_or_else(|| {
- let msg = "Type error at 'imag.logging.modules.<mod>.enabled', expected 'Boolean'";
- Error::from(err_msg(msg))
- })?;
-
- let module_settings = ModuleSettings {
- enabled: enabled,
- level: level,
- destinations: destinations,
- };
-
- // We don't care whether there was a value, we override it.
- let _ = settings.insert(module_name.to_owned(), module_settings);
- }
+ #[derive(Serialize, Deserialize, Debug)]
+ struct LoggingModuleConfigMap(BTreeMap<String, LoggingModuleConfig>);
- Ok(settings)
- },
- Ok(Some(_)) => {
- let msg = "Type error at 'imag.logging.modules', expected 'Table'";
- Err(Error::from(err_msg(msg)))
- },
- Ok(None) => {
- // No modules configured. This is okay!
- Ok(BTreeMap::new())
- },
- Err(e) => Err(e).context(EM::TomlQueryError).map_err(Error::from),
- },
+ impl<'a> Partial<'a> for LoggingModuleConfigMap {
+ const LOCATION: &'static str = "imag.logging.modules";
+ type Output = Self;
+ }
+
+ impl TryInto<BTreeMap<String, ModuleSettings>> for LoggingModuleConfigMap {
+ type Error = Error;
+
+ fn try_into(self) -> Result<BTreeMap<String, ModuleSettings>> {
+ let mut map = BTreeMap::new();
+
+ for (key, value) in self.0.into_iter() {
+ map.insert(key, ModuleSettings {
+ enabled: value.enabled,
+ level: value.level.map(Into::into),
+ destinations: match value.destinations {
+ None => None,
+ Some(ds) => Some(ds
+ .iter()
+ .map(Deref::deref)
+ .map(translate_destination)
+ .collect::<Result<Vec<LogDestination>>>()?)
+ },
+ });
+ }
+
+ Ok(map)
+ }
+ }
+
+ match config {
+ Some(cfg) => cfg.read_partial::<LoggingModuleConfigMap>()?
+ .ok_or_else(|| err_msg("Logging configuration missing"))?
+ .try_into()
+ .map_err(Error::from),
None => {
write!(stderr(), "No Configuration.").ok();
write!(stderr(), "cannot find module-settings for logging.").ok();