From ae249540204d0e0107d20eb381823427f7a4b160 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 26 Aug 2017 22:49:30 +0200 Subject: [PATCH] Implement templating --- lib/core/libimagrt/Cargo.toml | 1 + lib/core/libimagrt/src/error.rs | 3 +- lib/core/libimagrt/src/logger.rs | 207 +++++++++++++++++++++++++------ 3 files changed, 174 insertions(+), 37 deletions(-) diff --git a/lib/core/libimagrt/Cargo.toml b/lib/core/libimagrt/Cargo.toml index 25e95ff0..e557ecd4 100644 --- a/lib/core/libimagrt/Cargo.toml +++ b/lib/core/libimagrt/Cargo.toml @@ -23,6 +23,7 @@ itertools = "0.5" ansi_term = "0.9" is-match = "0.1" toml-query = "0.3.0" +handlebars = "0.29.0" libimagstore = { version = "0.4.0", path = "../../../lib/core/libimagstore" } libimagerror = { version = "0.4.0", path = "../../../lib/core/libimagerror" } diff --git a/lib/core/libimagrt/src/error.rs b/lib/core/libimagrt/src/error.rs index ff992291..8427f0b6 100644 --- a/lib/core/libimagrt/src/error.rs +++ b/lib/core/libimagrt/src/error.rs @@ -29,7 +29,8 @@ generate_error_types!(RuntimeError, RuntimeErrorKind, ConfigTypeError => "Error while reading the configuration: Type Error", GlobalLogLevelConfigMissing => "Global config 'imag.logging.level' missing", InvalidLogLevelSpec => "Invalid log level specification: Only 'trace', 'debug', 'info', 'warn', 'error' are allowed", - TomlReadError => "Error while reading in TOML document" + TomlReadError => "Error while reading in TOML document", + TemplateStringRegistrationError => "Error while registering logging template string" ); impl From for RuntimeError { diff --git a/lib/core/libimagrt/src/logger.rs b/lib/core/libimagrt/src/logger.rs index e80a4c7b..c82bac3b 100644 --- a/lib/core/libimagrt/src/logger.rs +++ b/lib/core/libimagrt/src/logger.rs @@ -33,6 +33,7 @@ use clap::ArgMatches; use log::{Log, LogLevel, LogRecord, LogMetadata}; use toml::Value; use toml_query::read::TomlValueReadExt; +use handlebars::Handlebars; type ModuleName = String; type Result = ::std::result::Result; @@ -68,21 +69,56 @@ pub struct ImagLogger { // global_format_warn : , // global_format_error : , module_settings : BTreeMap, + + handlebars: Handlebars, } impl ImagLogger { /// Create a new ImagLogger object with a certain level pub fn new(matches: &ArgMatches, config: Option<&Configuration>) -> Result { + let mut handlebars = Handlebars::new(); + + handlebars.register_helper("black" , Box::new(self::template_helpers::ColorizeBlackHelper)); + handlebars.register_helper("blue" , Box::new(self::template_helpers::ColorizeBlueHelper)); + handlebars.register_helper("cyan" , Box::new(self::template_helpers::ColorizeCyanHelper)); + handlebars.register_helper("green" , Box::new(self::template_helpers::ColorizeGreenHelper)); + handlebars.register_helper("purple" , Box::new(self::template_helpers::ColorizePurpleHelper)); + handlebars.register_helper("red" , Box::new(self::template_helpers::ColorizeRedHelper)); + handlebars.register_helper("white" , Box::new(self::template_helpers::ColorizeWhiteHelper)); + handlebars.register_helper("yellow" , Box::new(self::template_helpers::ColorizeYellowHelper)); + + { + let fmt = try!(aggregate_global_format_trace(matches, config)); + try!(handlebars.register_template_string("TRACE", fmt) // name must be uppercase + .map_err_into(EK::TemplateStringRegistrationError)); + } + { + let fmt = try!(aggregate_global_format_debug(matches, config)); + try!(handlebars.register_template_string("DEBUG", fmt) // name must be uppercase + .map_err_into(EK::TemplateStringRegistrationError)); + } + { + let fmt = try!(aggregate_global_format_info(matches, config)); + try!(handlebars.register_template_string("INFO", fmt) // name must be uppercase + .map_err_into(EK::TemplateStringRegistrationError)); + } + { + let fmt = try!(aggregate_global_format_warn(matches, config)); + try!(handlebars.register_template_string("WARN", fmt) // name must be uppercase + .map_err_into(EK::TemplateStringRegistrationError)); + } + { + let fmt = try!(aggregate_global_format_error(matches, config)); + try!(handlebars.register_template_string("ERROR", fmt) // name must be uppercase + .map_err_into(EK::TemplateStringRegistrationError)); + } + Ok(ImagLogger { global_loglevel : try!(aggregate_global_loglevel(matches, config)), global_destinations : try!(aggregate_global_destinations(matches, config)), - // global_format_trace : try!(aggregate_global_format_trace(matches, config)), - // global_format_debug : try!(aggregate_global_format_debug(matches, config)), - // global_format_info : try!(aggregate_global_format_info(matches, config)), - // global_format_warn : try!(aggregate_global_format_warn(matches, config)), - // global_format_error : try!(aggregate_global_format_error(matches, config)), module_settings : try!(aggregate_module_settings(matches, config)), + handlebars : handlebars, }) } @@ -103,17 +139,31 @@ impl Log for ImagLogger { let log_location = record.location(); let log_target = record.target(); + let mut data = BTreeMap::new(); + { + data.insert("level", format!("{}", log_level)); + data.insert("module_path", String::from(log_location.module_path())); + data.insert("file", String::from(log_location.file())); + data.insert("line", format!("{}", log_location.line())); + data.insert("target", String::from(log_target)); + data.insert("message", format!("{}", record.args())); + } + let logtext = self + .handlebars + .render(&format!("{}", log_level), &data) + .unwrap_or_else(|e| format!("Failed rendering logging data: {:?}\n", e)); + self.module_settings .get(log_target) .map(|module_setting| { if module_setting.enabled && module_setting.level >= log_level { - write!(stderr(), "[imag][{}]: {}", log_level, record.args()).ok(); + let _ = write!(stderr(), "{}\n", logtext); } }) .unwrap_or_else(|| { if self.global_loglevel >= log_level { // Yes, we log - write!(stderr(), "[imag][{}]: {}", log_level, record.args()).ok(); + let _ = write!(stderr(), "{}\n", logtext); } }); } @@ -219,35 +269,35 @@ fn aggregate_global_destinations(matches: &ArgMatches, config: Option<&Configura } } -// fn aggregate_global_format_trace(matches: &ArgMatches, config: Option<&Configuration>) -// -> -// { -// unimplemented!() -// } -// -// fn aggregate_global_format_debug(matches: &ArgMatches, config: Option<&Configuration>) -// -> -// { -// unimplemented!() -// } -// -// fn aggregate_global_format_info(matches: &ArgMatches, config: Option<&Configuration>) -// -> -// { -// unimplemented!() -// } -// -// fn aggregate_global_format_warn(matches: &ArgMatches, config: Option<&Configuration>) -// -> -// { -// unimplemented!() -// } -// -// fn aggregate_global_format_error(matches: &ArgMatches, config: Option<&Configuration>) -// -> -// { -// unimplemented!() -// } +fn aggregate_global_format_trace(matches: &ArgMatches, config: Option<&Configuration>) + -> Result +{ + unimplemented!() +} + +fn aggregate_global_format_debug(matches: &ArgMatches, config: Option<&Configuration>) + -> Result +{ + unimplemented!() +} + +fn aggregate_global_format_info(matches: &ArgMatches, config: Option<&Configuration>) + -> Result +{ + unimplemented!() +} + +fn aggregate_global_format_warn(matches: &ArgMatches, config: Option<&Configuration>) + -> Result +{ + unimplemented!() +} + +fn aggregate_global_format_error(matches: &ArgMatches, config: Option<&Configuration>) + -> Result +{ + unimplemented!() +} fn aggregate_module_settings(matches: &ArgMatches, config: Option<&Configuration>) -> Result> @@ -309,3 +359,88 @@ fn aggregate_module_settings(matches: &ArgMatches, config: Option<&Configuration } } +mod template_helpers { + use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper}; + use ansi_term::Colour; + + #[derive(Clone, Copy)] + pub struct ColorizeBlackHelper; + + impl HelperDef for ColorizeBlackHelper { + fn call(&self, h: &Helper, hb: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + colorize(Colour::Black, h, hb, rc) + } + } + + #[derive(Clone, Copy)] + pub struct ColorizeBlueHelper; + + impl HelperDef for ColorizeBlueHelper { + fn call(&self, h: &Helper, hb: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + colorize(Colour::Blue, h, hb, rc) + } + } + + #[derive(Clone, Copy)] + pub struct ColorizeCyanHelper; + + impl HelperDef for ColorizeCyanHelper { + fn call(&self, h: &Helper, hb: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + colorize(Colour::Cyan, h, hb, rc) + } + } + + #[derive(Clone, Copy)] + pub struct ColorizeGreenHelper; + + impl HelperDef for ColorizeGreenHelper { + fn call(&self, h: &Helper, hb: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + colorize(Colour::Green, h, hb, rc) + } + } + + #[derive(Clone, Copy)] + pub struct ColorizePurpleHelper; + + impl HelperDef for ColorizePurpleHelper { + fn call(&self, h: &Helper, hb: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + colorize(Colour::Purple, h, hb, rc) + } + } + + #[derive(Clone, Copy)] + pub struct ColorizeRedHelper; + + impl HelperDef for ColorizeRedHelper { + fn call(&self, h: &Helper, hb: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + colorize(Colour::Red, h, hb, rc) + } + } + + #[derive(Clone, Copy)] + pub struct ColorizeWhiteHelper; + + impl HelperDef for ColorizeWhiteHelper { + fn call(&self, h: &Helper, hb: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + colorize(Colour::White, h, hb, rc) + } + } + + #[derive(Clone, Copy)] + pub struct ColorizeYellowHelper; + + impl HelperDef for ColorizeYellowHelper { + fn call(&self, h: &Helper, hb: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + colorize(Colour::Yellow, h, hb, rc) + } + } + + fn colorize(color: Colour, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + use handlebars::JsonRender; + let p = try!(h.param(0).ok_or(RenderError::new("Too few arguments"))); + + try!(write!(rc.writer(), "{}", color.paint(p.value().render()))); + Ok(()) + } +} +