Skip to main content
Version: Latest - 1.0.0-alpha.25

Query Logger

Durcno supports query logging through a configurable logger option. When set, successful queries call the logger's info() method, while failed queries call error() with the SQL string, bound arguments, and the query duration in milliseconds.

Interface

Any object implementing the QueryLogger interface can be used:

interface QueryLogger {
info(message: string, meta?: Record<string, unknown>): void;
error(message: string, meta?: Record<string, unknown>): void;
}

This interface is intentionally minimal so that any logger — Winston, Pino, a custom object — can be used without additional adapters.

Built-in Winston Logger

Durcno ships a pre-configured Winston logger via the durcno/logger sub-path export. It uses a [durcno] label, an ISO timestamp, and a box-drawing format that renders the SQL and bound arguments in a readable style.

Installation

Winston is a peer dependency. Install it alongside Durcno:

npm install winston

Usage

// durcno.config.ts
import { defineConfig } from "durcno";
import { pg } from "durcno/connectors/pg";
import { createQueryLogger } from "durcno/logger";

export default defineConfig({
schema: "db/schema.ts",
out: "migrations",
connector: pg({
dbCredentials: {
url: process.env.DATABASE_URL!,
},
logger: createQueryLogger(),
}),
});

Output Format

Each logged query is printed in a box-drawing style:

2026-04-23T10:00:00.000Z [durcno] INFO: Query executed
┌ SQL
│ SELECT "id", "name", "email"
│ FROM "public"."users"
│ WHERE "id" = $1;
├ Arguments
│ $1 = 42
├ Duration
│ 3.21ms

If a query has no bound arguments the Arguments section is omitted. The Duration section shows how long the query took to execute.

Custom Logger

Pass any object with compatible info() and error() methods. The metadata object will always contain:

KeyTypeDescription
sqlstringThe SQL string sent to the DB
arguments(string | number | null)[] | undefinedThe bound parameter values
durationMsnumberQuery execution time in milliseconds
// durcno.config.ts
import { defineConfig } from "durcno";
import { pg } from "durcno/connectors/pg";

export default defineConfig({
schema: "db/schema.ts",
connector: pg({
dbCredentials: {
url: process.env.DATABASE_URL!,
},
logger: {
info(message, meta) {
console.log(`[db] ${message}`, meta);
},
error(message, meta) {
console.error(`[db] ${message}`, meta);
},
},
}),
});

Using Pino

import pino from "pino";

const log = pino();

export default defineConfig({
schema: "db/schema.ts",
connector: pg({
dbCredentials: { url: process.env.DATABASE_URL! },
logger: {
info: (message, meta) => log.info(meta ?? {}, message),
error: (message, meta) => log.error(meta ?? {}, message),
},
}),
});

Disabling the Logger

Omit the logger option (or set it to undefined) to disable query logging entirely. No queries will be logged and there is no performance overhead.