Sinks
Sinks decide where events emitted by the tracer end up. @accordkit/tracer ships with ready-to-use sinks for Node.js and the browser, plus lightweight helpers for HTTP delivery. You can also implement your own by satisfying the Sink interface.
FileSink (Node.js)
file-sink.ts
import { FileSink, Tracer } from '@accordkit/tracer';
const tracer = new Tracer({
sink: new FileSink({
base: '.accordkit-logs',
delivery: 'buffered',
batchSize: 50,
}),
});
- Stores JSONL files under the
basedirectory (defaults to~/.accordkit/logs). delivery: 'immediate'writes synchronously;'buffered'batches events and flushes on an interval.- Exposes
flush()andclose()for explicit draining during shutdown.
HttpSink (Node.js or edge runtimes)
http-sink.ts
import { HttpSink, Tracer } from '@accordkit/tracer';
const tracer = new Tracer({
sink: new HttpSink({
endpoint: 'https://example.com/accordkit/ingest',
headers: { 'x-api-key': process.env.ACCORDKIT_API_KEY ?? '' },
retry: { retries: 5, baseMs: 250, maxMs: 4000 },
}),
});
- Buffers events per session and POSTs newline-delimited JSON bodies.
- Retries transient failures (network errors, 408/425/429/5xx) with exponential backoff.
- Call
await tracer.flush()orawait tracer.close()to ensure all batches are delivered. - Provide
idempotencyKey(lines, attempt)if your ingest service requires idempotency headers.
Use resolveIngestEndpoint to generate AccordKit-style URLs when you adopt the default /auto|/eu|/us/ingest pattern.
BrowserSink (web apps)
browser-sink.ts
import { BrowserSink, Tracer } from '@accordkit/tracer';
const tracer = new Tracer({
sink: new BrowserSink({
endpoint: '/api/accordkit/events',
headers: { 'x-user-id': window.userId },
delivery: 'buffered',
durable: 'idb',
batchSize: 25,
}),
});
- Uses
navigator.sendBeaconfor small payloads and falls back tofetch(..., { keepalive: true }). - Supports in-memory buffering or IndexedDB-backed durability (
durable: 'idb'). - Flushes automatically on
pagehide/beforeunloadand when the document becomes hidden. onDropBatch(lines, error)lets you observe failed deliveries without throwing.
Writing a custom sink
Sinks only need a write(sessionId, event) method. Implement BufferedSink if you also provide flush() or close() hooks.
kafka-sink.ts
import type { Sink, TracerEvent } from '@accordkit/tracer';
class KafkaSink implements Sink {
constructor(private producer: KafkaProducer) {}
async write(sessionId: string, event: TracerEvent) {
await this.producer.send({
topic: 'accordkit.events',
messages: [{ key: sessionId, value: JSON.stringify(event) }],
});
}
}
Picking the right sink
| Environment | Recommended sink |
|---|---|
| Local development | FileSink plus the AccordKit Viewer for inspection |
| CI or staging | FileSink (buffered) or HttpSink targeting a test ingest service |
| Production services | HttpSink with retry + your own ingest endpoint |
| Browser apps | BrowserSink forwarding to a serverless handler |
Swap sinks via configuration, no need to change how you emit events.