pharos/sink
The pluggable sink dispatcher
Each AlertSink configured on the Config becomes one handler on the
alert event bus. The collection/detection logic stays decoupled from the
transport: it only ever notifys the bus, and every configured sink
receives the AlertEvent independently. A slow or failing sink cannot
block the others (handlers are fire-and-forget).
Sinks:
- Console logs locally via
logging(NixOSjournalctl). - Webhook POSTs a JSON body (e.g. to Slack), the direct-notification path when the Brain is unreachable.
- Brain ETF-encodes the alert and sends it to a registered process on a (possibly remote) node for native BEAM-to-BEAM delivery.
- Otlp is a documented stub until the Protobuf/gRPC exporter lands.
Values
pub fn attach_all(
bus: event_bus.EventBus,
sinks: List(config.AlertSink),
) -> List(event_bus.HandlerId)
Attach one bus handler per configured sink. Returns the handler ids of the sinks that attached successfully (a failed attach is skipped, not fatal: the agent still runs with the sinks that did attach).
pub fn handler_for(
sink: config.AlertSink,
) -> fn(alert.AlertEvent) -> Nil
Build the bus handler closure for a single sink.
pub fn json_body(event: alert.AlertEvent) -> String
JSON body for the webhook sink. Built from a string->string map and encoded
with Erlang’s built-in json module (OTP 27+), which handles escaping.
pub fn render(event: alert.AlertEvent) -> String
Human-readable one-line rendering for the console sink.