Skip to content

Custom adapter

Implement IAdapter for a destination that is not SQLite, Turso, or ClickHouse.

Updated View as Markdown
import type {
  IAdapter,
  LogbunLog,
  LogbunQueryFilters,
  LogbunQueryResult,
} from 'logbun';

class PostgresAuditAdapter implements IAdapter {
  async init(): Promise<void> {
    // Must be idempotent: ConnectionPool always calls init() after adapterFactory.
  }

  async bulkInsert(
    tenantId: string | null,
    logs: LogbunLog[],
  ): Promise<boolean> {
    // Prefer idempotent insert on log.id.
    // return true on success; false is a soft/retryable failure.
    // Prefer throwing on unexpected failures so the engine can emit error text.
    return true;
  }

  async query(
    tenantId: string | null,
    filters: LogbunQueryFilters,
    pagination: { cursor?: string; limit: number },
  ): Promise<LogbunQueryResult> {
    return { logs: [], nextCursor: null };
  }

  async prune(days: number): Promise<void> {
    // delete older than `days` (finite integer >= 1)
  }

  async close(): Promise<void> {}
}

Contract

  1. Idempotent on id so WAL replay / retries do not duplicate rows.
  2. Honor tenantId: null = unscoped; '' = tenant-less rows only; any other string = that tenant.
  3. Cursor: newest-first pages (ORDER BY id DESC) and nextCursor = last row’s id when more pages exist. pagination.limit is required on IAdapter.query.
  4. Empty bulkInsert: return true.
  5. Closed adapter: query / bulkInsert / prune must throw when closed or not initialized (do not return empty results as if no rows existed).
  6. Integrity fields: persist prevHash / contentHash when integrityChain is enabled. After restart the tip is restored from WAL, then the newest destination row (limit: 1).
  7. Prune: days is a finite number >= 1. Prefer bounded batches. Built-in SQLite/Turso throw prune_incomplete when the 10_000 × 1_000 safety cap is hit so runMaintenance() can reject and the host can schedule a follow-up.

AuditLogger.query() throws AuditLogger is not initialized — query unavailable when the logger is shut down or bootstrap failed. Built-in destination adapters throw from query / bulkInsert / prune if they are closed or not initialized.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close