Expand description

A pure Rust log logger for the systemd journal.

Usage

Create a JournalLog with JournalLog::default and then use JournalLog::install to setup journal logging. Then configure the logging level and now you can use the standard macros from the log crate to send log messages to the systemd journal:

use log::{info, warn, error, LevelFilter};
use systemd_journal_logger::JournalLog;

JournalLog::default().install().unwrap();
log::set_max_level(LevelFilter::Info);

info!("hello log");
warn!("warning");
error!("oops");

In a service you can use connected_to_journal to check whether the standard output or error stream of the current process is directly connected to the systemd journal (the default for services started by systemd) and fall back to logging to standard error if that’s not the case. Take a look at the systemd_service.rs example for details.

Journal fields

The journald logger always sets the following standard journal fields:

  • PRIORITY: The log level mapped to a priority (see below).
  • MESSAGE: The formatted log message (see log::Record::args()).
  • SYSLOG_PID: The PID of the running process (see std::process::id()).
  • CODE_FILE: The filename the log message originates from (see log::Record::file(), only if present).
  • CODE_LINE: The line number the log message originates from (see log::Record::line(), only if present).

It also sets SYSLOG_IDENTIFIER if non-empty (see JournalLog::with_syslog_identifier and JournalLog::default).

Additionally it also adds the following non-standard fields:

In addition to these fields the logger also adds all structures key-values (see log::Record::key_values) from each log record as journal fields, after converting the keys to uppercase letters and replacing invalid characters with underscores.

You can also add custom fields to every log entry with JournalLog::with_extra_fields and customize the syslog identifier with JournalLog::with_syslog_identifier:

use log::{info, warn, error, LevelFilter};
use systemd_journal_logger::JournalLog;

JournalLog::default()
    .with_extra_fields(vec![("VERSION", env!("CARGO_PKG_VERSION"))])
    .with_syslog_identifier("foo".to_string())
    .install().unwrap();
log::set_max_level(LevelFilter::Info);

info!("this message has an extra VERSION field in the journal");

You can display these extra fields with journalctl --output=verbose and extract them with any of the structured output formats of journalctl, e.g. journalctl --output=json.

Log levels and priorities

The journal logger maps log::Level to journal priorities as follows:

Errors

This crate currently does not implement any kind of error handling for journal messages. In particular it will panic when sending a record to journald fails, e.g. if journald is not running. There are no plans to change this behaviour, give that journald is reliable in general.

To implement an alternative error handling behaviour define a custom log implementation around journal_send which sends a single log record to the journal.

Structs

Functions