slog-scope
Thread-local logging scopes for slog-rs, so you can log without manually threading Logger objects through every function call.
Repository Health
Technical Analysis
slog-scope is a small companion crate for slog-rs that lets Rust applications log through a global or thread-local Logger without passing that logger explicitly through every function signature. You set a global logger once at startup (typically in main), and from then on any code can call slog_scope::logger() or the crate’s info!/error!/debug! macros to log through whatever Logger is active for the current scope.
Logging scopes can be nested via slog_scope::scope(), which pushes a thread-local Logger for the duration of a closure and pops it on drop, making the mechanism panic-safe. The crate is explicitly framed by its own maintainers as an ergonomics escape hatch for application code (main functions, top-level handlers) rather than something to depend on inside reusable libraries, where slog’s usual philosophy of explicitly passing a Logger down the call stack is preferred.
What You Get
- A global logger slot (
set_global_logger) returning aGlobalLoggerGuardthat resets logging to a panicking drain on drop, so forgetting to hold the guard fails loudly instead of silently swallowing logs. - Thread-local logging scopes (
scope()) that let you push a childLoggerfor the duration of a closure, enabling nested contextual logging without changing function signatures. logger()andwith_logger()accessors — the former clones the current scope’sLogger, the latter borrows it for a callback when avoiding a clone matters for performance.- Drop-in macros (
crit!,error!,warn!,info!,debug!,trace!) that log through the current scope logger without needing to import or hold aLoggerreference at the call site.
Common Use Cases
- Application entry points that want to set up structured logging once in
mainand have it available everywhere without passing aLoggerthrough every layer. - Request or job handlers that push a scoped logger enriched with request-specific key-value context (request ID, user ID) for the duration of handling one unit of work.
- Retrofitting slog-based structured logging into existing code that wasn’t written with explicit
Loggerparameters, without a large refactor.
Under The Hood
Architecture: The crate is a single ~250-line lib.rs with no submodules. It holds two pieces of state: a process-wide lazy_static! GLOBAL_LOGGER: ArcSwap<slog::Logger> that defaults to a Discard drain, and a thread_local! TL_SCOPES: RefCell<Vec<*const slog::Logger>> stack per thread. logger()/with_logger() check the thread-local stack first and fall back to the global logger; scope() pushes a raw pointer onto that stack via an RAII ScopeGuard and pops it on drop (using unsafe to dereference the pointer, since the borrow is guaranteed valid for the closure’s lifetime by construction). set_global_logger() swaps the ArcSwap and returns a GlobalLoggerGuard that, unless cancel_reset() is called, resets the global logger to a drain that panics on any log call when dropped — a deliberate design choice to surface “logger torn down but still being used” bugs immediately rather than silently discarding.
Tech Stack: Pure Rust, no async runtime dependency. Core dependencies are slog 2.4 (the logging framework this crate augments), lazy_static 1.2 (for the global logger cell), and arc-swap 1.1 (lock-free atomic swapping of the global Logger). Dev-dependencies (slog-term, slog-async) are only used in the example under examples/compact-color.rs. The crate targets stable Rust and has no feature flags.
Code Quality: There is no dedicated test suite in the repository — no tests/ directory and no #[test] functions in lib.rs; correctness is exercised only via the single runnable example and the doctest embedded in the crate-level doc comment (which itself sets up a global logger and a nested scope). The unsafe pointer dereference in logger()/with_logger() is narrowly scoped and justified by the RAII guard’s lifetime discipline, but is unverified by any test. #![warn(missing_docs)] is set and every public item carries a doc comment, which is a genuine quality signal despite the missing tests. Naming is consistent with the rest of the slog-rs ecosystem (slog_info, slog_error, etc. re-exported alongside scope-aware info!/error! macros).
API Design: The public surface is intentionally tiny: set_global_logger, scope, logger, with_logger, and six logging macros. Getting started requires exactly one call (set_global_logger) plus holding onto its guard; from there, logging calls read identically to plain slog macros. The crate’s own documentation is unusually candid about when not to use it (library code, as opposed to applications), which is good API stewardship even though it constrains the crate’s applicability.