arcly_stream/observe.rs
1//! Telemetry hook — the injected replacement for `stream-center`'s global
2//! Prometheus singleton (`sc_metrics::Metrics::global()`).
3//!
4//! The engine calls these methods on lifecycle transitions and (opt-in) per
5//! frame. The **default no-op** means the pure engine has zero observability
6//! dependencies; wire a real sink only when you want one.
7
8use crate::bus::StreamEvent;
9use crate::{MediaFrame, StreamKey};
10
11/// Telemetry observer. All methods default to no-ops so implementors override
12/// only what they care about. Compare `arcly-http`'s `AuditSink` / `HealthCheck`
13/// injection points: behaviour is supplied by the host, never reached for
14/// through global state.
15pub trait Observer: Send + Sync + 'static {
16 /// A stream lifecycle event was emitted.
17 fn on_event(&self, _event: &StreamEvent) {}
18
19 /// A publish session started in application `app`.
20 fn on_publish_started(&self, _app: &str) {}
21
22 /// A publish session ended in application `app`.
23 fn on_publish_ended(&self, _app: &str) {}
24
25 /// A frame was published. **Hot-path hook — keep it cheap.** The default
26 /// is a no-op so the branch is trivially predicted away when no observer
27 /// is installed.
28 fn on_frame(&self, _key: &StreamKey, _frame: &MediaFrame) {}
29
30 /// A subscriber fell behind the broadcast buffer and `skipped` frames were
31 /// dropped from its view before it could read them. This is the canonical
32 /// slow-consumer signal: alert on it. Fired by
33 /// [`StreamHandle::subscribe_resilient`](crate::StreamHandle::subscribe_resilient).
34 fn on_subscriber_lagged(&self, _key: &StreamKey, _skipped: u64) {}
35
36 /// A chronically slow subscriber crossed its `max_lag` budget and was shed.
37 /// Fired by [`Subscription::recv`](crate::Subscription::recv).
38 fn on_subscriber_evicted(&self, _key: &StreamKey) {}
39
40 /// An ingress rate limit was exceeded for `key`; the protocol handler should
41 /// drop or backpressure the connection. Handlers call this from their
42 /// ingest loop (e.g. when [`IngestRateLimit`](crate::protocol::IngestRateLimit)
43 /// returns `false`).
44 fn on_rate_limited(&self, _key: &StreamKey) {}
45
46 /// A publish session was reaped for exceeding the engine's idle timeout.
47 fn on_stream_reaped(&self, _key: &StreamKey) {}
48}
49
50/// The default observer. Selected automatically when the builder gets none.
51#[derive(Debug, Default, Clone, Copy)]
52pub struct NoopObserver;
53
54impl Observer for NoopObserver {}