Skip to main content

rex_logger/tracing_logger/
layers.rs

1/// Creates a formatted layer with standard configuration options.
2///
3/// This macro applies consistent formatting settings to any tracing layer,
4/// including line numbers, log levels, thread IDs, and target information.
5/// ANSI colors are disabled for compatibility with various output destinations.
6///
7/// # Arguments
8///
9/// * `$layer` - A tracing layer expression to be configured
10///
11/// # Returns
12///
13/// The configured layer with the following settings:
14/// - ANSI colors: disabled
15/// - Line numbers: enabled
16/// - Log levels: enabled
17/// - Thread IDs: enabled
18/// - Target information: enabled
19#[macro_export]
20macro_rules! default_fmt_layer {
21    ($layer:expr) => {
22        $layer
23            .with_ansi(false)
24            .with_file(true)
25            .with_line_number(true)
26            .with_level(true)
27            .with_thread_ids(true)
28            .with_target(true)
29    };
30}
31
32/// Creates a console logging layer that outputs to stdout.
33///
34/// This macro conditionally creates a console logging layer based on the enabled flag.
35/// When enabled, it creates a formatted layer that writes to stdout with RFC 3339
36/// timestamps and applies the specified log level filter.
37///
38/// # Arguments
39///
40/// * `$enabled` - Boolean expression indicating whether console logging should be enabled
41/// * `$log_level` - Log level filter to apply to the layer
42///
43/// # Returns
44///
45/// * `Some(Layer)` - Configured console layer if enabled
46/// * `None` - If console logging is disabled
47#[macro_export]
48macro_rules! create_console_layer {
49    ($enabled:expr, $log_level:expr) => {
50        if $enabled {
51            Some(
52                default_fmt_layer!(fmt::layer()
53                    .with_writer(std::io::stdout)
54                    .with_timer(UtcTime::rfc_3339()))
55                .with_filter($log_level),
56            )
57        } else {
58            None
59        }
60    };
61}
62
63/// Creates a script logging layer for capturing script execution logs in memory.
64///
65/// This macro conditionally creates a script logging layer that captures log entries
66/// in memory for later retrieval. When enabled, it creates a [`ScriptLogHandle`] that
67/// implements the tracing [`Layer`] trait and stores log entries in an in-memory buffer.
68///
69/// # Arguments
70///
71/// * `$enabled` - Boolean expression indicating whether script logging should be enabled
72///
73/// # Returns
74///
75/// * `Some(ScriptLogHandle)` - Configured script log layer if enabled
76/// * `None` - If script logging is disabled
77#[macro_export]
78macro_rules! create_script_log_layer {
79    ($enabled:expr, $max_script_log_message_length:expr) => {
80        if $enabled {
81            Some(ScriptLogHandle::new(
82                $max_script_log_message_length,
83                DEFAULT_LOG_ENTRIES_LIMIT,
84            ))
85        } else {
86            None
87        }
88    };
89}
90
91/// Creates a syslog logging layer for Unix systems.
92///
93/// This macro conditionally creates a syslog logging layer based on the enabled flag.
94/// When enabled, it initializes a connection to the system's syslog daemon using the
95/// `Daemon` facility and includes the process ID in log entries.
96///
97/// **Platform Support**: Unix-based systems only (Linux, macOS, etc.)
98///
99/// # Arguments
100///
101/// * `$enabled` - Boolean expression indicating whether syslog logging should be enabled
102/// * `$log_level` - Log level filter to apply to the layer
103///
104/// # Returns
105///
106/// * `Some(Layer)` - Configured syslog layer if enabled and initialization succeeds
107/// * `None` - If syslog logging is disabled
108///
109/// # Errors
110///
111/// Returns [`RexLoggerError::InitializationError`] if:
112/// * Failed to create `CString` for syslog identity
113/// * Failed to initialize syslog connection
114#[macro_export]
115#[cfg(target_family = "unix")]
116macro_rules! create_syslog_layer {
117    ($enabled:expr, $log_level:expr) => {
118        if $enabled {
119            let identity =
120                CString::new(SYSLOG_IDENTITY).map_err(|e| RexLoggerError::InitializationError {
121                    reason: "Failed to create CString for syslog identity".to_string(),
122                    source: Some(Box::new(e)),
123                })?;
124            let options = Options::LOG_PID;
125            let facility = Facility::Daemon;
126            let syslog = Syslog::new(identity, options, facility).ok_or_else(|| {
127                RexLoggerError::InitializationError {
128                    reason: "Failed to initialize syslog".to_string(),
129                    source: None,
130                }
131            })?;
132            Some(
133                default_fmt_layer!(fmt::layer().with_writer(syslog).without_time()).with_filter(
134                    $log_level.and(filter::filter_fn(|metadata| {
135                        metadata.target() != RUNNER_TARGET
136                            && metadata.target() != RUNNER_TARGET_FOR_SCRIPT_LOGS
137                    })),
138                ),
139            )
140        } else {
141            None
142        }
143    };
144}