Skip to main content

truefix_log/
tracing_log.rs

1//! `tracing`-facade log (the SLF4J-equivalent).
2
3use crate::{Log, is_heartbeat};
4
5/// Output switches for [`TracingLog`] (FR-026): `SLF4JLogHeartbeats`. Session-ID prefixing
6/// (`SLF4JLogPrependSessionID`) is provided generically by wrapping in [`crate::SessionPrefixLog`]
7/// rather than as a field here.
8#[derive(Debug, Clone, Copy)]
9pub struct TracingLogOptions {
10    /// `SLF4JLogHeartbeats`: whether Heartbeat (`35=0`) messages are emitted.
11    pub include_heartbeats: bool,
12}
13
14impl Default for TracingLogOptions {
15    fn default() -> Self {
16        Self {
17            include_heartbeats: true,
18        }
19    }
20}
21
22/// Logs via the `tracing` facade, separating message and event targets.
23pub struct TracingLog {
24    options: TracingLogOptions,
25}
26
27impl Default for TracingLog {
28    fn default() -> Self {
29        Self::new()
30    }
31}
32
33impl TracingLog {
34    /// Create a tracing log with default (unfiltered) output switches.
35    pub fn new() -> Self {
36        Self::with_options(TracingLogOptions::default())
37    }
38
39    /// Create a tracing log honoring `options` (FR-026).
40    pub fn with_options(options: TracingLogOptions) -> Self {
41        Self { options }
42    }
43}
44
45impl Log for TracingLog {
46    fn on_incoming(&self, message: &str) {
47        if is_heartbeat(message) && !self.options.include_heartbeats {
48            return;
49        }
50        tracing::info!(target: "truefix::message", direction = "incoming", %message);
51    }
52    fn on_outgoing(&self, message: &str) {
53        if is_heartbeat(message) && !self.options.include_heartbeats {
54            return;
55        }
56        tracing::info!(target: "truefix::message", direction = "outgoing", %message);
57    }
58    fn on_event(&self, text: &str) {
59        tracing::info!(target: "truefix::event", %text);
60    }
61}