pub struct LogDispatcher { /* private fields */ }Expand description
Thread-safe fan-out dispatcher; ordinary sinks receive only sanitized events.
Implementations§
Source§impl LogDispatcher
impl LogDispatcher
Sourcepub fn new(policy: LogPolicy, sinks: Vec<Arc<dyn LogSink>>) -> Self
pub fn new(policy: LogPolicy, sinks: Vec<Arc<dyn LogSink>>) -> Self
Creates a dispatcher with explicit filtering and sinks.
Examples found in repository?
examples/component_filter.rs (line 26)
19fn main() {
20 // All components start at V4, keeping normal output concise.
21 let mut policy = LogPolicy::new(Verbosity::V4);
22
23 // Synchronization may need temporary I/O and timing diagnostics.
24 policy.set_component("sync", Verbosity::V8);
25
26 let log = LogDispatcher::new(policy, vec![Arc::new(ConsoleSink::new())]);
27
28 let event = log.event(0, "sync");
29
30 // This V7 event is selected only because the sync override allows it.
31 event.verbosity(7).debug("batch details");
32}More examples
examples/sensitive_diagnostics.rs (line 48)
24fn main() -> Result<(), appcore_log::LogError> {
25 let key_id = KeyId::new("example-log-key").map_err(|_| appcore_log::LogError::Encryption)?;
26
27 let provider =
28 StaticDntKeyProvider::new().with_key(key_id.clone(), SecretKey::new(demo_key()?));
29
30 // The sink bounds the encrypted snapshot by both bytes and event count.
31 let sink = SensitiveDntSink::new(
32 SensitiveDntSinkConfig {
33 path: std::env::temp_dir().join("appcore-sensitive-log.dnt"),
34 application_id: ApplicationId::new("example-log")
35 .map_err(|_| appcore_log::LogError::Encryption)?,
36 key_id,
37 max_bytes: 4096,
38 max_events: 8,
39 retention: 2,
40 },
41 provider,
42 )?;
43
44 // Sensitive mode must be explicit and has no console or JSONL fallback.
45 let mut policy = LogPolicy::default();
46 policy.sensitivity = Sensitivity::Sensitive;
47
48 let log = LogDispatcher::new(policy, vec![Arc::new(sink)]);
49
50 log.event(0, "security").verbosity(2).error("diagnostic");
51
52 Ok(())
53}examples/async_file.rs (line 40)
19fn main() -> Result<(), LogError> {
20 let directory = std::path::PathBuf::from("target/appcore-log-example");
21 std::fs::create_dir_all(&directory).map_err(|_| LogError::Io)?;
22
23 let path = directory.join("async.jsonl");
24 let file = Arc::new(FileSink::new(FileSinkConfig {
25 path: path.clone(),
26 max_bytes: LOG_SIZE_8_MIB,
27 sync_each_write: true,
28 retention: 2,
29 archive: None,
30 })?);
31
32 // This queue retains at most 256 events and 1 MiB, including active I/O.
33 let asynchronous = Arc::new(AsyncSink::new(
34 AsyncSinkConfig {
35 max_events: 256,
36 max_bytes: 1024 * 1024,
37 },
38 file,
39 )?);
40 let dispatcher = LogDispatcher::new(LogPolicy::default(), vec![asynchronous.clone()]);
41 let log = dispatcher.event(0, "application");
42
43 log.info("application started");
44 log.warn("storage response is slow");
45
46 // The lifecycle owner drains durable writes before exiting.
47 asynchronous.shutdown()?;
48 let path = std::fs::canonicalize(path).map_err(|_| LogError::Io)?;
49 println!("log written to {}", path.display());
50 Ok(())
51}Sourcepub fn emit(&self, event: LogEvent)
pub fn emit(&self, event: LogEvent)
Emits once. Critical failure accounting is retained even when a sink fails.
Sourcepub fn event<'a>(
&'a self,
timestamp_ms: u64,
component: impl Into<Cow<'a, str>>,
) -> LogBuilder<'a>
pub fn event<'a>( &'a self, timestamp_ms: u64, component: impl Into<Cow<'a, str>>, ) -> LogBuilder<'a>
Creates a fluent event builder for a stable component and clock value.
Examples found in repository?
examples/component_filter.rs (line 28)
19fn main() {
20 // All components start at V4, keeping normal output concise.
21 let mut policy = LogPolicy::new(Verbosity::V4);
22
23 // Synchronization may need temporary I/O and timing diagnostics.
24 policy.set_component("sync", Verbosity::V8);
25
26 let log = LogDispatcher::new(policy, vec![Arc::new(ConsoleSink::new())]);
27
28 let event = log.event(0, "sync");
29
30 // This V7 event is selected only because the sync override allows it.
31 event.verbosity(7).debug("batch details");
32}More examples
examples/basic.rs (line 27)
18fn main() -> Result<(), appcore_log::LogConfigError> {
19 // Safe V4 terminal logging is explicit and creates no global state.
20 let logger = LoggerConfig {
21 output: LogOutputMode::Terminal,
22 ..LoggerConfig::default()
23 }
24 .build()?;
25
26 // The builder defaults to V4 and can be kept for related events.
27 let log = logger.dispatcher().event(0, "application");
28
29 log.info("application started");
30 log.warn("connection is slower than expected");
31 log.error("document could not be saved");
32
33 Ok(())
34}examples/output_modes.rs (line 34)
15fn main() -> Result<(), appcore_log::LogConfigError> {
16 // Replace this with Disabled, Terminal, File, TerminalAndFile or CrashOnly.
17 let output = LogOutputMode::CrashOnly;
18
19 let logger = LoggerConfig {
20 output,
21 file: Some(FileSinkConfig {
22 path: std::env::temp_dir().join("my-application-crash.jsonl"),
23 max_bytes: LOG_SIZE_2_MIB,
24 sync_each_write: true,
25 retention: 1,
26 archive: None,
27 }),
28 crash_events: 128,
29 crash_bytes: 512 * 1024,
30 ..LoggerConfig::default()
31 }
32 .build()?;
33
34 let log = logger.dispatcher().event(0, "application");
35
36 log.info("kept only in the bounded crash ring");
37
38 // Call this from the application's panic/crash boundary. In every other
39 // mode it is a no-op and returns zero.
40 let _written_events = logger.dump_crash()?;
41
42 Ok(())
43}examples/sensitive_diagnostics.rs (line 50)
24fn main() -> Result<(), appcore_log::LogError> {
25 let key_id = KeyId::new("example-log-key").map_err(|_| appcore_log::LogError::Encryption)?;
26
27 let provider =
28 StaticDntKeyProvider::new().with_key(key_id.clone(), SecretKey::new(demo_key()?));
29
30 // The sink bounds the encrypted snapshot by both bytes and event count.
31 let sink = SensitiveDntSink::new(
32 SensitiveDntSinkConfig {
33 path: std::env::temp_dir().join("appcore-sensitive-log.dnt"),
34 application_id: ApplicationId::new("example-log")
35 .map_err(|_| appcore_log::LogError::Encryption)?,
36 key_id,
37 max_bytes: 4096,
38 max_events: 8,
39 retention: 2,
40 },
41 provider,
42 )?;
43
44 // Sensitive mode must be explicit and has no console or JSONL fallback.
45 let mut policy = LogPolicy::default();
46 policy.sensitivity = Sensitivity::Sensitive;
47
48 let log = LogDispatcher::new(policy, vec![Arc::new(sink)]);
49
50 log.event(0, "security").verbosity(2).error("diagnostic");
51
52 Ok(())
53}examples/async_file.rs (line 41)
19fn main() -> Result<(), LogError> {
20 let directory = std::path::PathBuf::from("target/appcore-log-example");
21 std::fs::create_dir_all(&directory).map_err(|_| LogError::Io)?;
22
23 let path = directory.join("async.jsonl");
24 let file = Arc::new(FileSink::new(FileSinkConfig {
25 path: path.clone(),
26 max_bytes: LOG_SIZE_8_MIB,
27 sync_each_write: true,
28 retention: 2,
29 archive: None,
30 })?);
31
32 // This queue retains at most 256 events and 1 MiB, including active I/O.
33 let asynchronous = Arc::new(AsyncSink::new(
34 AsyncSinkConfig {
35 max_events: 256,
36 max_bytes: 1024 * 1024,
37 },
38 file,
39 )?);
40 let dispatcher = LogDispatcher::new(LogPolicy::default(), vec![asynchronous.clone()]);
41 let log = dispatcher.event(0, "application");
42
43 log.info("application started");
44 log.warn("storage response is slow");
45
46 // The lifecycle owner drains durable writes before exiting.
47 asynchronous.shutdown()?;
48 let path = std::fs::canonicalize(path).map_err(|_| LogError::Io)?;
49 println!("log written to {}", path.display());
50 Ok(())
51}examples/file_logging.rs (line 52)
22fn main() -> Result<(), appcore_log::LogConfigError> {
23 // Keep generated output predictable and inside Cargo's ignored target tree.
24 let output_directory = PathBuf::from("target/appcore-log-example");
25 std::fs::create_dir_all(&output_directory).map_err(|_| LogConfigError::Sink(LogError::Io))?;
26
27 let active_file = output_directory.join("application.jsonl");
28
29 // Two rotations stay beside the active file. Older rotations move into
30 // archive/YYYY/MM and the complete archive never exceeds 120 files.
31 let archive_directory = output_directory.join("archive");
32 let mut policy = LogPolicy::new(Verbosity::V4);
33 policy.set_component("sync", Verbosity::V8);
34
35 let logger = LoggerConfig {
36 policy,
37 output: LogOutputMode::TerminalAndFile,
38 file: Some(FileSinkConfig {
39 path: active_file,
40 max_bytes: LOG_SIZE_8_MIB,
41 sync_each_write: false,
42 retention: 2,
43 archive: Some(FileArchiveConfig {
44 directory: archive_directory,
45 max_files: 120,
46 }),
47 }),
48 ..LoggerConfig::default()
49 }
50 .build()?;
51
52 let application = logger.dispatcher().event(0, "application");
53 let sync = logger.dispatcher().event(1, "sync.transport");
54
55 application.info("application ready; inspect target/appcore-log-example/application.jsonl");
56
57 // The parent component policy makes this V7 diagnostic visible.
58 sync.verbosity(7).debug("replication batch sent");
59
60 sync.warn("peer response was delayed");
61
62 let stats = logger.dispatcher().stats();
63 assert_eq!(stats.sink_failures, 0);
64
65 Ok(())
66}Sourcepub fn event_now<'a>(
&'a self,
clock: &dyn LogClock,
component: impl Into<Cow<'a, str>>,
) -> LogBuilder<'a>
pub fn event_now<'a>( &'a self, clock: &dyn LogClock, component: impl Into<Cow<'a, str>>, ) -> LogBuilder<'a>
Creates a fluent event builder using an injected clock.
Sourcepub fn enabled(&self, component: &str, verbosity: Verbosity) -> bool
pub fn enabled(&self, component: &str, verbosity: Verbosity) -> bool
Reports whether a component and verbosity would reach at least one sink.
Sourcepub fn stats(&self) -> LogStats
pub fn stats(&self) -> LogStats
Returns counters without taking global locks.
Examples found in repository?
examples/file_logging.rs (line 62)
22fn main() -> Result<(), appcore_log::LogConfigError> {
23 // Keep generated output predictable and inside Cargo's ignored target tree.
24 let output_directory = PathBuf::from("target/appcore-log-example");
25 std::fs::create_dir_all(&output_directory).map_err(|_| LogConfigError::Sink(LogError::Io))?;
26
27 let active_file = output_directory.join("application.jsonl");
28
29 // Two rotations stay beside the active file. Older rotations move into
30 // archive/YYYY/MM and the complete archive never exceeds 120 files.
31 let archive_directory = output_directory.join("archive");
32 let mut policy = LogPolicy::new(Verbosity::V4);
33 policy.set_component("sync", Verbosity::V8);
34
35 let logger = LoggerConfig {
36 policy,
37 output: LogOutputMode::TerminalAndFile,
38 file: Some(FileSinkConfig {
39 path: active_file,
40 max_bytes: LOG_SIZE_8_MIB,
41 sync_each_write: false,
42 retention: 2,
43 archive: Some(FileArchiveConfig {
44 directory: archive_directory,
45 max_files: 120,
46 }),
47 }),
48 ..LoggerConfig::default()
49 }
50 .build()?;
51
52 let application = logger.dispatcher().event(0, "application");
53 let sync = logger.dispatcher().event(1, "sync.transport");
54
55 application.info("application ready; inspect target/appcore-log-example/application.jsonl");
56
57 // The parent component policy makes this V7 diagnostic visible.
58 sync.verbosity(7).debug("replication batch sent");
59
60 sync.warn("peer response was delayed");
61
62 let stats = logger.dispatcher().stats();
63 assert_eq!(stats.sink_failures, 0);
64
65 Ok(())
66}Sourcepub fn sink_stats(&self) -> Vec<SinkStats>
pub fn sink_stats(&self) -> Vec<SinkStats>
Returns bounded failure counters for each configured sink.
Auto Trait Implementations§
impl !Freeze for LogDispatcher
impl !RefUnwindSafe for LogDispatcher
impl !UnwindSafe for LogDispatcher
impl Send for LogDispatcher
impl Sync for LogDispatcher
impl Unpin for LogDispatcher
impl UnsafeUnpin for LogDispatcher
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more