summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-10-08 19:00:07 +0200
committerGitHub <noreply@github.com>2017-10-08 19:00:07 +0200
commit75a8041c0ea491789da0f1971105bf57d5945360 (patch)
tree1901a6f1af313f4d9f543949bc55da2f03201a22
parente5155caccad11b4a59afad6f13dd9c479d9f84f9 (diff)
parentf266791142bcd77c77243c547e6354bfcfcd1d76 (diff)
downloadimag-75a8041c0ea491789da0f1971105bf57d5945360.zip
imag-75a8041c0ea491789da0f1971105bf57d5945360.tar.gz
Merge pull request #1127 from matthiasbeyer/libimagrt/logging-to-file
Add multi-destination logging to logger
-rw-r--r--doc/src/09020-changelog.md2
-rw-r--r--lib/core/libimagrt/src/logger.rs56
2 files changed, 50 insertions, 8 deletions
diff --git a/doc/src/09020-changelog.md b/doc/src/09020-changelog.md
index 79edabf..974d94b 100644
--- a/doc/src/09020-changelog.md
+++ b/doc/src/09020-changelog.md
@@ -25,6 +25,8 @@ This section contains the changelog from the last release to the next release.
* `imag-view` uses the configuration file now to find the command to call
for viewing the entry. This way one can view the entry in an editor or the
browser or on the toaster.
+ * The logger is now able to handle multiple destinations (file and "-" for
+ stderr)
## 0.4.0
diff --git a/lib/core/libimagrt/src/logger.rs b/lib/core/libimagrt/src/logger.rs
index 46086cf..9bdc097 100644
--- a/lib/core/libimagrt/src/logger.rs
+++ b/lib/core/libimagrt/src/logger.rs
@@ -20,6 +20,9 @@
use std::io::Write;
use std::io::stderr;
use std::collections::BTreeMap;
+use std::sync::Arc;
+use std::sync::Mutex;
+use std::ops::Deref;
use configuration::Configuration;
use error::RuntimeErrorKind as EK;
@@ -38,7 +41,7 @@ type Result<T> = ::std::result::Result<T, RE>;
enum LogDestination {
Stderr,
- File(::std::fs::File),
+ File(Arc<Mutex<::std::fs::File>>),
}
impl Default for LogDestination {
@@ -163,22 +166,57 @@ impl Log for ImagLogger {
.render(&format!("{}", record.level()), &data)
.unwrap_or_else(|e| format!("Failed rendering logging data: {:?}\n", e));
+ let log_to_destination = |d: &LogDestination| match d {
+ &LogDestination::Stderr => {
+ let _ = write!(stderr(), "{}\n", logtext);
+ },
+ &LogDestination::File(ref arc_mutex_logdest) => {
+ // if there is an error in the lock, we cannot do anything. So we ignore it here.
+ let _ = arc_mutex_logdest
+ .deref()
+ .lock()
+ .map(|mut logdest| {
+ write!(logdest, "{}\n", logtext)
+ });
+ }
+ };
+
+ // hack to get the right target configuration.
+ // If there is no element here, we use the empty string which automatically drops through
+ // to the unwrap_or_else() case
+ let record_target = record
+ .target()
+ .split("::")
+ .next()
+ .unwrap_or("");
+
self.module_settings
- .get(record.target())
+ .get(record_target)
.map(|module_setting| {
let set = module_setting.enabled &&
module_setting.level.unwrap_or(self.global_loglevel) >= record.level();
if set {
- let _ = write!(stderr(), "{}\n", logtext);
+ module_setting.destinations.as_ref().map(|destinations| for d in destinations {
+ // If there's an error, we cannot do anything, can we?
+ let _ = log_to_destination(&d);
+ });
+
+ for d in self.global_destinations.iter() {
+ // If there's an error, we cannot do anything, can we?
+ let _ = log_to_destination(&d);
+ }
}
})
- .unwrap_or_else(|| {
- if self.global_loglevel >= record.level() {
- // Yes, we log
- let _ = write!(stderr(), "{}\n", logtext);
+ .unwrap_or_else(|| {
+ if self.global_loglevel >= record.level() {
+ // Yes, we log
+ for d in self.global_destinations.iter() {
+ // If there's an error, we cannot do anything, can we?
+ let _ = log_to_destination(&d);
}
- });
+ }
+ });
}
}
@@ -230,6 +268,8 @@ fn translate_destination(raw: &str) -> Result<LogDestination> {
.append(true)
.create(true)
.open(other)
+ .map(Mutex::new)
+ .map(Arc::new)
.map(LogDestination::File)
.chain_err(|| EK::IOLogFileOpenError)
}