Skip to content

Commit

Permalink
Support GELF logging output.
Browse files Browse the repository at this point in the history
  • Loading branch information
jbgi committed Jun 17, 2019
1 parent 67434b6 commit 756fe69
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 10 deletions.
28 changes: 28 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Fields description:
- 2: debug
- 3 and above: trace
- *format*: log output format - plain or json.
- *output*: log output - stderr, syslog (unix only) or journald (linux with systemd only, must be enabled during compilation)
- *output*: log output - stderr, gelf (graylog), syslog (unix only) or journald (linux with systemd only, must be enabled during compilation)
- *backend*: for gelf output: hostname:port of a graylog server.
- *rest*: (optional) configuration of the rest endpoint.
- *listen*: listen address
- *pkcs12*: certificate file (optional)
Expand Down
3 changes: 2 additions & 1 deletion doc/quickstart/02_passive_node.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ Fields description:
- *logger*: (optional) logger configuration,
- *verbosity*: 0 - warning, 1 - info, 2 -debug, 3 and above - trace
- *format*: log output format - plain or json.
- *output*: log output - stderr, syslog (unix only) or journald (linux with systemd only, must be enabled during compilation)
- *output*: log output - stderr, gelf (graylog) syslog (unix only) or journald (linux with systemd only, must be enabled during compilation)
- *backend*: for gelf output: hostname:port of a graylog server.
- *rest*: (optional) configuration of the rest endpoint.
- *listen*: listen address
- *pkcs12*: certificate file (optional)
Expand Down
3 changes: 3 additions & 0 deletions jormungandr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ jormungandr-utils = { path = "../jormungandr-utils" }
strfmt = "0.1"
gtmpl = "0.5.6"
mktemp = "0.4.0"
slog-gelf = { git = "https://github.com/jbgi/slog-gelf", rev = "18197f7d5c9f439197111299509f02b24efe8985" }
hostname = "^0.1"
uuid = { version = "^0.7", features = ["v4"] }

[dependencies.actix-web]
version = "0.7.18"
Expand Down
2 changes: 2 additions & 0 deletions jormungandr/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ extern crate serde_yaml;
#[macro_use(b, o, record_static, debug, info, warn, error, crit)]
extern crate slog;
extern crate slog_async;
extern crate slog_gelf;
#[cfg(feature = "systemd")]
extern crate slog_journald;
extern crate slog_json;
Expand All @@ -55,6 +56,7 @@ extern crate structopt;
#[cfg(test)]
#[cfg(feature = "with-bench")]
extern crate test;
extern crate uuid;

use crate::{
blockcfg::Leader,
Expand Down
2 changes: 1 addition & 1 deletion jormungandr/src/settings/command_arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub struct CommandLine {
#[structopt(long = "log-format", parse(try_from_str))]
pub log_format: Option<LogFormat>,

/// Set format of the log emitted. Can be "stderr", "syslog" (unix only) or "journald"
/// Set format of the log emitted. Can be "stderr", "gelf", "syslog" (unix only) or "journald"
/// (linux with systemd only, must be enabled during compilation).
/// If not configured anywhere, defaults to "stderr".
#[structopt(long = "log-output", parse(try_from_str))]
Expand Down
29 changes: 22 additions & 7 deletions jormungandr/src/settings/logging.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
use crate::log::{AsyncableDrain, JsonDrain};
use slog::{Drain, Logger};
use slog_async::Async;
use slog_gelf::Gelf;
#[cfg(feature = "systemd")]
use slog_journald::JournaldDrain;
#[cfg(unix)]
use slog_syslog::Facility;
use std::io;
use std::str::FromStr;
use uuid::Uuid;

#[derive(Debug)]
pub struct LogSettings {
pub verbosity: slog::Level,
pub format: LogFormat,
pub output: LogOutput,
pub backend: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
Expand All @@ -28,6 +31,7 @@ pub enum LogFormat {
/// Output of the logger.
pub enum LogOutput {
Stderr,
Gelf,
#[cfg(unix)]
Syslog,
#[cfg(feature = "systemd")]
Expand All @@ -52,6 +56,7 @@ impl FromStr for LogOutput {
fn from_str(s: &str) -> Result<Self, Self::Err> {
match &*s.trim().to_lowercase() {
"stderr" => Ok(LogOutput::Stderr),
"gelf" => Ok(LogOutput::Gelf),
#[cfg(unix)]
"syslog" => Ok(LogOutput::Syslog),
#[cfg(feature = "systemd")]
Expand All @@ -63,21 +68,30 @@ impl FromStr for LogOutput {

impl LogSettings {
pub fn to_logger(&self) -> Result<Logger, Error> {
let drain = self.output.to_logger(&self.format)?.fuse();
let drain = self.output.to_logger(&self.format, &self.backend)?.fuse();
let drain = slog::LevelFilter::new(drain, self.verbosity).fuse();
Ok(slog::Logger::root(drain, o!()))
}
}

impl LogOutput {
fn to_logger(&self, format: &LogFormat) -> Result<Async, Error> {
Ok(match self {
LogOutput::Stderr => format.decorate_stderr(),
fn to_logger(&self, format: &LogFormat, backend: &Option<String>) -> Result<Async, Error> {
match self {
LogOutput::Stderr => Ok(format.decorate_stderr()),
LogOutput::Gelf => match backend {
Some(graylog_host_port) => {
// We generate an UUID to anonymously but uniquely identify the logs of this node.
let source = Uuid::new_v4().to_string();
let gelf_drain = Gelf::new(&source, graylog_host_port).unwrap().fuse();
Ok(format.decorate(gelf_drain))
}
_ => Err(Error::MissingGelfBackend),
},
#[cfg(unix)]
LogOutput::Syslog => format.decorate(slog_syslog::unix_3164(Facility::LOG_USER)?),
LogOutput::Syslog => Ok(format.decorate(slog_syslog::unix_3164(Facility::LOG_USER)?)),
#[cfg(feature = "systemd")]
LogOutput::Journald => format.decorate(JournaldDrain),
})
LogOutput::Journald => Ok(format.decorate(JournaldDrain)),
}
}
}

Expand All @@ -102,4 +116,5 @@ impl LogFormat {

custom_error! {pub Error
SyslogAccessFailed { source: io::Error } = "syslog access failed",
MissingGelfBackend = "Please specify a backend (host:port of graylog server) for the GELF logger output",
}
1 change: 1 addition & 0 deletions jormungandr/src/settings/start/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub struct ConfigLogSettings {
pub verbosity: Option<u8>,
pub format: Option<LogFormat>,
pub output: Option<LogOutput>,
pub backend: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
Expand Down
2 changes: 2 additions & 0 deletions jormungandr/src/settings/start/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ impl RawSettings {
}

pub fn to_logger(&self) -> Result<Logger, logging::Error> {
let backend = self.config.logger.as_ref().and_then(|l| l.backend.clone());
LogSettings {
verbosity: self.logger_verbosity(),
format: self.logger_format(),
output: self.logger_output(),
backend,
}
.to_logger()
}
Expand Down

0 comments on commit 756fe69

Please sign in to comment.