#[non_exhaustive]pub struct LogScope { /* private fields */ }Expand description
A guard that represents an active logging context on the current thread’s scope stack.
When the guard is dropped, the context is automatically removed from the stack.
Created by LogScope::enter.
§Examples
use context_logger::{LogContext, LogScope};
// Create a context with some data
let context = LogContext::new().with_record("user_id", 123);
// Enter the context (pushes to stack)
let guard = LogScope::enter(context);
// Log operations here will have access to the context
// ...
// When `guard` goes out of scope, the context is automatically removedImplementations§
Source§impl LogScope
impl LogScope
Sourcepub fn enter(context: LogContext) -> Self
pub fn enter(context: LogContext) -> Self
Pushes the given context onto the current thread’s scope stack and returns a guard.
The context remains active until the returned guard is dropped, at which point it is automatically removed from the stack.
§In Asynchronous Code
Warning: in asynchronous code Self::enter should be used very carefully or avoided entirely.
Holding the drop guard across .await points will result in incorrect logs:
use context_logger::{LogContext, LogScope};
async fn my_async_fn() {
let ctx = LogContext::new()
.with_record("request_id", "req-123")
.with_record("user_id", 42);
// WARNING: This context will remain active until this
// guard is dropped...
let _guard = LogScope::enter(ctx);
// But this code causing the runtime to switch to another task,
// while remaining in this context.
tokio::task::yield_now().await;
}Please use the crate::FutureExt::in_log_context instead.
Sourcepub fn add_record(key: impl Into<Cow<'static, str>>, value: impl Into<LogValue>)
pub fn add_record(key: impl Into<Cow<'static, str>>, value: impl Into<LogValue>)
Adds a record to the currently active scope.
This is useful for adding records dynamically without having direct access to the current scope.
§Note
If there is no active context, this operation will have no effect.
§Ordering
The order in which records appear in log output is not guaranteed. Do not rely on any specific ordering of keys.
§Examples
use context_logger::{LogContext, LogScope};
use log::info;
fn process_request() {
// Add a record to the current scope dynamically
LogScope::add_record("processing_time_ms", 42);
info!("Request processed");
}
let _guard = LogScope::enter(LogContext::new()
.with_record("request_id", "req-123"));
process_request(); // Will log with both request_id and processing_time_msSourcepub fn current_context() -> LogContext
pub fn current_context() -> LogContext
Extracts the currently active logging context.
This is useful for propagating context when spawning new threads or async tasks, allowing child tasks to inherit logging information from the current scope.
§Example
use std::time::Duration;
use context_logger::{ContextLogger, FutureExt, LogContext, LogScope};
fn try_init_logger() -> Result<(), Box<dyn std::error::Error>> {
let level = log::LevelFilter::Info;
let logger = structured_logger::Builder::with_level(level.as_str())
.with_target_writer("*", structured_logger::json::new_writer(std::io::stdout()))
.build();
ContextLogger::new(logger)
.default_record("instance", "contexted_log_async")
.try_init(level)?;
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
try_init_logger()?;
log::info!("Initialized context logger");
// Create a new context with properties.
let log_context = LogContext::new()
.with_record("user_id", "12345")
.with_record("tag", "example");
count_with_tokio_spawn(7).in_log_context(log_context).await;
log::info!("Finished counting");
Ok(())
}
async fn count_with_tokio_spawn(counter: u64) {
log::info!("Invoked a function with detached work");
// The scope stack is thread-local, so the active context is not visible
// inside `tokio::spawn` by default. Capture it here and pass it explicitly.
let context = LogScope::current_context();
let handle = tokio::spawn(
async move {
for i in 0..counter {
log::info!(i; "Counting...");
tokio::time::sleep(Duration::from_millis(250)).await;
}
}
.in_log_context(context),
);
handle.await.unwrap();
}§Notes
- Returns an empty context if there is no active scope.
- The returned
LogContextis a clone of the active context, so it’s safe to move into spawned tasks.