Skip to main content

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 base directory (defaults to ~/.accordkit/logs).
  • delivery: 'immediate' writes synchronously; 'buffered' batches events and flushes on an interval.
  • Exposes flush() and close() 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() or await 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.sendBeacon for small payloads and falls back to fetch(..., { keepalive: true }).
  • Supports in-memory buffering or IndexedDB-backed durability (durable: 'idb').
  • Flushes automatically on pagehide/beforeunload and 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

EnvironmentRecommended sink
Local developmentFileSink plus the AccordKit Viewer for inspection
CI or stagingFileSink (buffered) or HttpSink targeting a test ingest service
Production servicesHttpSink with retry + your own ingest endpoint
Browser appsBrowserSink forwarding to a serverless handler

Swap sinks via configuration, no need to change how you emit events.