rust_loguru/
context.rs

1//! Context management for rust-loguru
2//!
3//! - Thread-local storage for context data
4//! - Context stack management
5//! - Structured data for context values
6//! - Async propagation helpers
7
8use std::cell::RefCell;
9use std::collections::HashMap;
10use std::fmt::Debug;
11use std::sync::Arc;
12
13/// Type alias for context key-value pairs
14pub type ContextMap = HashMap<String, ContextValue>;
15
16/// Structured value for context
17#[derive(Clone, Debug, PartialEq)]
18pub enum ContextValue {
19    String(String),
20    Integer(i64),
21    Float(f64),
22    Bool(bool),
23    // Add more types as needed
24}
25
26impl std::fmt::Display for ContextValue {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match self {
29            ContextValue::String(s) => write!(f, "{}", s),
30            ContextValue::Integer(i) => write!(f, "{}", i),
31            ContextValue::Float(fl) => write!(f, "{}", fl),
32            ContextValue::Bool(b) => write!(f, "{}", b),
33        }
34    }
35}
36
37thread_local! {
38    static CONTEXT_STACK: RefCell<Vec<ContextMap>> = const { RefCell::new(vec![]) };
39}
40
41/// Push a new context map onto the stack
42pub fn push_context(ctx: ContextMap) {
43    CONTEXT_STACK.with(|stack| stack.borrow_mut().push(ctx));
44}
45
46/// Pop the top context map from the stack
47pub fn pop_context() {
48    CONTEXT_STACK.with(|stack| {
49        stack.borrow_mut().pop();
50    });
51}
52
53/// Get the current merged context (top to bottom)
54pub fn current_context() -> ContextMap {
55    CONTEXT_STACK.with(|stack| {
56        let mut merged = ContextMap::new();
57        for ctx in stack.borrow().iter() {
58            for (k, v) in ctx.iter() {
59                merged.insert(k.clone(), v.clone());
60            }
61        }
62        merged
63    })
64}
65
66/// Set a key-value pair in the current context
67pub fn set_context_value(key: &str, value: ContextValue) {
68    CONTEXT_STACK.with(|stack| {
69        if let Some(top) = stack.borrow_mut().last_mut() {
70            top.insert(key.to_string(), value);
71        }
72    });
73}
74
75/// Get a value from the current context
76pub fn get_context_value(key: &str) -> Option<ContextValue> {
77    CONTEXT_STACK.with(|stack| {
78        for ctx in stack.borrow().iter().rev() {
79            if let Some(val) = ctx.get(key) {
80                return Some(val.clone());
81            }
82        }
83        None
84    })
85}
86
87/// Check if there is any context data available
88pub fn has_context() -> bool {
89    CONTEXT_STACK.with(|stack| !stack.borrow().is_empty())
90}
91
92// Async propagation helpers (stub)
93pub fn propagate_context_for_async() -> Arc<ContextMap> {
94    Arc::new(current_context())
95}
96
97pub fn set_context_from_arc(ctx: Arc<ContextMap>) {
98    push_context(ctx.as_ref().clone());
99}