anvil/
logging.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! User facing Logger

use parking_lot::RwLock;
use std::sync::Arc;
use tracing::{subscriber::Interest, Metadata};
use tracing_subscriber::{layer::Context, Layer};

/// The target that identifies the events intended to be logged to stdout
pub(crate) const NODE_USER_LOG_TARGET: &str = "node::user";

/// The target that identifies the events coming from the `console.log` invocations.
pub(crate) const EVM_CONSOLE_LOG_TARGET: &str = "node::console";

/// A logger that listens for node related events and displays them.
///
/// This layer is intended to be used as filter for `NODE_USER_LOG_TARGET` events that will
/// eventually be logged to stdout
#[derive(Clone, Debug, Default)]
pub struct NodeLogLayer {
    state: LoggingManager,
}

impl NodeLogLayer {
    /// Returns a new instance of this layer
    pub fn new(state: LoggingManager) -> Self {
        Self { state }
    }
}

// use `Layer`'s filter function to globally enable/disable `NODE_USER_LOG_TARGET` events
impl<S> Layer<S> for NodeLogLayer
where
    S: tracing::Subscriber,
{
    fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
        if metadata.target() == NODE_USER_LOG_TARGET || metadata.target() == EVM_CONSOLE_LOG_TARGET
        {
            Interest::sometimes()
        } else {
            Interest::never()
        }
    }

    fn enabled(&self, metadata: &Metadata<'_>, _ctx: Context<'_, S>) -> bool {
        self.state.is_enabled() &&
            (metadata.target() == NODE_USER_LOG_TARGET ||
                metadata.target() == EVM_CONSOLE_LOG_TARGET)
    }
}

/// Contains the configuration of the logger
#[derive(Clone, Debug)]
pub struct LoggingManager {
    /// Whether the logger is currently enabled
    pub enabled: Arc<RwLock<bool>>,
}

impl LoggingManager {
    /// Returns true if logging is currently enabled
    pub fn is_enabled(&self) -> bool {
        *self.enabled.read()
    }

    /// Updates the `enabled` state
    pub fn set_enabled(&self, enabled: bool) {
        let mut current = self.enabled.write();
        *current = enabled;
    }
}

impl Default for LoggingManager {
    fn default() -> Self {
        Self { enabled: Arc::new(RwLock::new(true)) }
    }
}