Sinks
Route notification events to external systems
A sink is a destination for structured send events. withEventLogger calls sink.write(event) once per send — the sink decides where the event goes.
When to use a sink
Use a sink when you need a durable, structured record of every send — not just logs. Sinks are the right tool when:
- Audit trails — you need to prove a notification was sent (or failed) for compliance, billing, or support investigations.
- Analytics — you want to track delivery rates, latency distributions, or error patterns over time in a data warehouse or dashboard.
- Alerting — you want to page on-call when a route starts failing, without coupling alert logic to the send pipeline.
- Event streaming — you want to feed notification events into a Kafka topic, S3 bucket, or webhook for downstream systems to consume.
If you only need console output for debugging, the logger is simpler. If you need per-request spans with parent-child relationships, use a tracer instead. Sinks sit between the two — more structured than logs, less granular than traces.
The EventSink interface
Prop
Type
The SendEvent shape
Every event carries the same base fields:
Prop
Type
Built-in sinks
consoleEventSink
Logs events to the console. Use during local development.
import { consoleEventSink } from '@betternotify/core/sinks';
withEventLogger({ sink: consoleEventSink() });inMemoryEventSink
Collects events in an array. Use in tests to assert on what was sent.
import { inMemoryEventSink } from '@betternotify/core/sinks';
const sink = inMemoryEventSink();
// after sending:
console.log(sink.events.length);
console.log(sink.events[0].status);Custom sinks
Use createEventSink to build a sink from a write function. It wraps your function with failure isolation (a sink crash never breaks the send pipeline) and optional event filtering:
import { createEventSink } from '@betternotify/core/sinks';
const datadogSink = createEventSink({
write: async (event) => {
await fetch('https://api.datadoghq.com/api/v2/logs', {
method: 'POST',
headers: { 'DD-API-KEY': process.env.DD_API_KEY! },
body: JSON.stringify(event),
});
},
});Prop
Type
Filtering events
Ship only errors to a paging pipeline, or only successes to an analytics sink:
const errorOnlySink = createEventSink({
write: async (event) => { await alertService.send(event); },
filter: (event) => event.status === 'error',
});