From 407dd50e6b77b8d0320e601f05aefcb9d84a762c Mon Sep 17 00:00:00 2001 From: Jeremiah Senkpiel Date: Tue, 24 Nov 2020 11:20:39 -0800 Subject: [PATCH] feat: add try_start() and try_with_level() It is very useful to have non-panic-ing logger setups for test binaries, which compile all test-cases into one binary and can have conflicts when there is optional logging in a test setup. --- src/lib.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++------ src/ndjson.rs | 7 +++-- src/pretty.rs | 7 +++-- src/wasm.rs | 7 +++-- 4 files changed, 81 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4d75fc6..a4f6167 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,8 @@ //! log::info!("Listening on port 8080"); //! ``` +use log::SetLoggerError; + pub use log::LevelFilter; #[cfg(not(target_arch = "wasm32"))] @@ -22,42 +24,101 @@ mod wasm; /// Starts logging depending on current environment. /// -/// # Log output +/// ## Log output /// /// - when compiling with `--release` uses ndjson. /// - pretty-prints otherwise. /// - works in WASM out of the box. /// -/// # Examples +/// ## Examples /// /// ``` /// femme::start(); /// log::warn!("Unauthorized access attempt on /login"); /// log::info!("Listening on port 8080"); /// ``` +/// +/// ## Panics +/// +/// This function will panic if it is called more than once, or if another library has already initialized a global logger. +/// pub fn start() { - with_level(LevelFilter::Info); + with_level(LevelFilter::Info) +} + +/// Starts logging depending on current environment. +/// +/// ## Log output +/// +/// - when compiling with `--release` uses ndjson. +/// - pretty-prints otherwise. +/// - works in WASM out of the box. +/// +/// ## Examples +/// +/// ``` +/// femme::try_start().ok(); // Handle Result or ignore +/// log::warn!("Unauthorized access attempt on /login"); +/// log::info!("Listening on port 8080"); +/// ``` +/// +/// ## Errors +/// +/// This function will fail if it is called more than once, or if another library has already initialized a global logger. +/// +pub fn try_start() -> Result<(), SetLoggerError> { + try_with_level(LevelFilter::Info) } /// Start logging with a log level. /// /// All messages under the specified log level will statically be filtered out. /// -/// # Examples +/// ## Examples +/// /// ``` -/// femme::with_level(log::LevelFilter::Trace); +/// femme::with_level(log::LevelFilter::Warn); +/// log::warn!("Unauthorized access attempt on /login"); +/// log::info!("Listening on port 8080"); // Will be hidden /// ``` +/// +/// ## Panics +/// +/// This function will panic if it is called more than once, or if another library has already initialized a global logger. +/// pub fn with_level(level: log::LevelFilter) { + try_with_level(level).expect("Could not start logging") +} + +/// Start logging with a log level. +/// +/// All messages under the specified log level will statically be filtered out. +/// +/// ## Examples +/// +/// ``` +/// femme::try_with_level(log::LevelFilter::Warn).ok(); // Handle Result or ignore +/// log::warn!("Unauthorized access attempt on /login"); +/// log::info!("Listening on port 8080"); // Will be hidden +/// ``` +/// +/// ## Errors +/// +/// This function will fail if it is called more than once, or if another library has already initialized a global logger. +/// +pub fn try_with_level(level: log::LevelFilter) -> Result<(), SetLoggerError> { #[cfg(target_arch = "wasm32")] - wasm::start(level); + wasm::start(level)?; #[cfg(not(target_arch = "wasm32"))] { // Use ndjson in release mode, pretty logging while debugging. if cfg!(debug_assertions) { - pretty::start(level); + pretty::start(level)?; } else { - ndjson::start(level); + ndjson::start(level)?; } } + + Ok(()) } diff --git a/src/ndjson.rs b/src/ndjson.rs index 9801026..9ebe5b6 100644 --- a/src/ndjson.rs +++ b/src/ndjson.rs @@ -1,14 +1,15 @@ //! Print logs as ndjson. -use log::{kv, LevelFilter, Log, Metadata, Record}; +use log::{kv, LevelFilter, Log, Metadata, Record, SetLoggerError}; use std::io::{self, StdoutLock, Write}; use std::time; /// Start logging. -pub(crate) fn start(level: LevelFilter) { +pub(crate) fn start(level: LevelFilter) -> Result<(), SetLoggerError> { let logger = Box::new(Logger {}); - log::set_boxed_logger(logger).expect("Could not start logging"); + log::set_boxed_logger(logger)?; log::set_max_level(level); + Ok(()) } #[derive(Debug)] diff --git a/src/pretty.rs b/src/pretty.rs index 97938a8..de2c649 100644 --- a/src/pretty.rs +++ b/src/pretty.rs @@ -1,6 +1,6 @@ //! Pretty print logs. -use log::{kv, Level, LevelFilter, Log, Metadata, Record}; +use log::{kv, Level, LevelFilter, Log, Metadata, Record, SetLoggerError}; use std::io::{self, StdoutLock, Write}; // ANSI term codes. @@ -11,10 +11,11 @@ const GREEN: &'static str = "\x1b[32m"; const YELLOW: &'static str = "\x1b[33m"; /// Start logging. -pub(crate) fn start(level: LevelFilter) { +pub(crate) fn start(level: LevelFilter) -> Result<(), SetLoggerError> { let logger = Box::new(Logger {}); - log::set_boxed_logger(logger).expect("Could not start logging"); + log::set_boxed_logger(logger)?; log::set_max_level(level); + Ok(()) } #[derive(Debug)] diff --git a/src/wasm.rs b/src/wasm.rs index 98d5eae..cd1ad31 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -1,16 +1,17 @@ //! Print logs as ndjson. use js_sys::Object; -use log::{kv, Level, LevelFilter, Log, Metadata, Record}; +use log::{kv, Level, LevelFilter, Log, Metadata, Record, SetLoggerError}; use wasm_bindgen::prelude::*; use std::collections::HashMap; /// Start logging. -pub(crate) fn start(level: LevelFilter) { +pub(crate) fn start(level: LevelFilter) -> Result<(), SetLoggerError> { let logger = Box::new(Logger {}); - log::set_boxed_logger(logger).expect("Could not start logging"); + log::set_boxed_logger(logger)?; log::set_max_level(level); + Ok(()) } #[derive(Debug)]