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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! # Event subscriber trait.
//!
//! [`Subscribe`] is the extension point for plugging custom event handlers into the runtime.
//!
//! Each subscriber gets:
//! - **Dedicated worker task** (runs independently)
//! - **Per-subscriber bounded queue** (capacity via [`Subscribe::queue_capacity`])
//! - **Panic isolation** (panics are caught and reported as `EventKind::SubscriberPanicked`)
//!
//! ## Architecture
//!
//! ```text
//! SubscriberSet ──► [bounded queue] ──► worker task ──► subscriber.on_event()
//! └─► panic caught ──► EventKind::SubscriberPanicked
//! ```
//!
//! ## Rules
//!
//! - Queue overflow drops the event **for this subscriber only** and publishes`EventKind::SubscriberOverflow`;
//! other subscribers are unaffected.
//! - Events are processed sequentially (FIFO) per subscriber.
//! - Subscribers do not block publishers or each other.
//! - A slow subscriber only affects its own queue.
//!
//! ## Example
//!
//! ```rust
//! use taskvisor::{Subscribe, Event, EventKind};
//!
//! struct Metrics;
//!
//! impl Subscribe for Metrics {
//! fn on_event(&self, ev: &Event) {
//! if matches!(ev.kind, EventKind::TaskFailed) {
//! // update counters, push to channel, etc.
//! }
//! }
//!
//! fn name(&self) -> &'static str { "metrics" } // prefer short, descriptive names
//! fn queue_capacity(&self) -> usize { 2048 } // larger buffer for metrics
//! }
//! ```
use crateEvent;
/// Event subscriber for runtime observability.
///
/// Each subscriber runs in isolation:
/// - **Panic isolation**: panics are caught and published as `SubscriberPanicked`.
/// - **Bounded queue** buffers events (capacity via [`Self::queue_capacity`]).
/// - **Dedicated worker task** processes events sequentially (FIFO).
///
/// ### Implementation requirements
///
/// - Keep `on_event` fast: it runs on a dedicated worker task but blocks that worker's event loop.
/// For async I/O, send to a channel and process elsewhere.
/// - Slow processing affects only this subscriber's queue.
/// - Handle errors internally; do not panic.
///
/// ### Synchronous design
///
/// `on_event` is intentionally synchronous:
/// - The `SubscriberSet` infrastructure already provides async fan-out via per-subscriber `mpsc` channels and dedicated worker tasks.
/// - If a subscriber needs async I/O, send events to a channel inside `on_event` and process them in a separate task.
/// - Adding async to `on_event` would force a `Box::pin` allocation per event per subscriber with no benefit;
/// All real subscribers are synchronous.
///
/// ## Also
///
/// - See [`Event`](crate::Event) and [`EventKind`](crate::EventKind) for the event structure.
/// - For a built-in reference implementation see [`LogWriter`](crate::LogWriter) *(feature = `logging`)*.