Skip to main content

obs_core/sink/
mod.rs

1//! Sinks consume `ScrubbedEnvelope` and ship it to a destination
2//! (stdout, NDJSON file, OTLP, ClickHouse, etc.).
3//!
4//! Phase-3 surface (impl-plan tasks 3.7 / 3.12 + 3.1 worker pool):
5//!
6//! - `Sink` trait + `flush` / `shutdown` lifecycle.
7//! - `NoopSink`, `InMemorySink` (test harness).
8//! - `StdoutSink` with all four `FormatterStyle`s.
9//! - `NdjsonFileSink` over `RollingFileWriter`.
10//! - `MakeWriter` family: `StdoutWriter`, `StderrWriter`, `LevelSplitWriter`, `TeeWriter`,
11//!   `RollingFileWriter`, `NonBlockingWriter`.
12
13pub mod fanout;
14mod in_memory;
15mod ndjson;
16mod noop;
17mod stdout;
18pub(crate) mod writer;
19
20use std::{future::Future, pin::Pin};
21
22pub use self::{
23    fanout::FanOutSink,
24    in_memory::{InMemoryHandle, InMemorySink},
25    ndjson::NdjsonFileSink,
26    noop::NoopSink,
27    stdout::{FormatterStyle, StdoutSink},
28    writer::{
29        ErasedWriter, LevelSplitWriter, MakeWriter, NonBlockingHandle, NonBlockingWriter,
30        RollingFileHandle, RollingFileWriter, RollingFileWriterBuilder, RollingPolicy,
31        StderrWriter, StdoutWriter, TeeWriter, WorkerGuard,
32    },
33};
34use crate::registry::ScrubbedEnvelope;
35
36/// Pinned future returned by `Sink::flush` / `Sink::shutdown`. Spec 11 § 4.
37pub type SinkFut<'a> = Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
38
39/// A delivery destination. Called from per-tier worker tasks, never on
40/// the emit thread.
41pub trait Sink: Send + Sync + 'static {
42    /// Hand the envelope to the sink. **Must not block**; long IO is
43    /// queued internally. Spec 11 § 4 / spec 14 § 5.
44    fn deliver(&self, env: ScrubbedEnvelope<'_>);
45
46    /// Flush in-flight batches; awaits IO if needed.
47    fn flush(&self) -> SinkFut<'_> {
48        Box::pin(async {})
49    }
50
51    /// Shut down (drain + close). Idempotent.
52    fn shutdown(&self) -> SinkFut<'_> {
53        Box::pin(async {})
54    }
55}