journal_env_logger/
lib.rs

1//! # journal-env-logger
2//!
3//! Logging into system journal based on `RUST_LOG` environment variable
4//!
5//! ## Usage
6//! ```rust,no_run
7//! // Initialize logging into journal
8//! journal_env_logger::init_journal().unwrap();
9//!
10//! // Initialize logging into stdout (e.g. for dev purposes)
11//! journal_env_logger::init_stdout().unwrap();
12//!
13//! // A helper to initialize stdout on dev and journal on prod
14//! let is_prod = true;
15//! journal_env_logger::init(is_prod).unwrap();
16//! ```
17
18#![warn(clippy::all, missing_docs, nonstandard_style, future_incompatible)]
19
20use std::{error, fmt, io};
21use tracing_subscriber::{filter::FromEnvError, prelude::*, registry, EnvFilter};
22
23/// Logging initialization error
24#[derive(Debug)]
25pub enum Error {
26    /// can't parse `RUST_LOG` env var
27    Env(FromEnvError),
28    /// can't connect to Journald
29    Journal(io::Error),
30}
31
32/// Initialises logging with formatting based on `RUST_LOG` environment variable
33/// Writes logs to journal with `to_journal` is true or to `stdout` otherwise
34pub fn init(to_journal: bool) -> Result<(), Error> {
35    if to_journal {
36        init_journal()
37    } else {
38        init_stdout()
39    }
40}
41
42/// Initialises logging into journal with formatting based on `RUST_LOG` environment variable
43pub fn init_journal() -> Result<(), Error> {
44    let filter = env_filter()?;
45    let journal_layer = tracing_journald::layer().map_err(Error::Journal)?;
46    registry().with(filter).with(journal_layer).init();
47    Ok(())
48}
49
50/// Initialises logging to stdout (e.g. for dev purposes) with formatting based on `RUST_LOG`
51/// environment variable
52pub fn init_stdout() -> Result<(), Error> {
53    let filter = env_filter()?;
54    tracing_subscriber::fmt().with_env_filter(filter).init();
55    Ok(())
56}
57
58fn env_filter() -> Result<EnvFilter, Error> {
59    EnvFilter::try_from_default_env().map_err(Error::Env)
60}
61
62impl fmt::Display for Error {
63    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64        match self {
65            Self::Env(_) => f.write_str("can't parse `RUST_LOG` environment variable"),
66            Self::Journal(_) => f.write_str("cat't connect to journald"),
67        }
68    }
69}
70
71impl error::Error for Error {
72    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
73        match self {
74            Self::Env(ref e) => Some(e),
75            Self::Journal(ref e) => Some(e),
76        }
77    }
78}