PostgreSQL
errorcore instruments the pg client library automatically when IO recording is active. Queries made through pg.Client or pg.Pool appear in the IO timeline with their duration, statement text, and position relative to the error.
Setup
Initialize errorcore before creating your Postgres client or pool. The SDK patches the query path at startup, so clients created afterward are instrumented automatically.
import errorcore from "errorcore";
errorcore.init({
service: "billing-api",
transport: { type: "file", path: "./errors.ndjson" },
allowUnencrypted: true,
});
// create the pool after init()
import pg from "pg";
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });What gets recorded
Each query in the IO timeline includes:
- the SQL statement text
- query duration in milliseconds
- row count (when available)
- position in the ordered timeline relative to other IO
8ms SELECT * FROM invoices WHERE account_id = $1
14ms SELECT * FROM payments WHERE invoice_id = $1
19ms UPDATE invoices SET status = 'failed' WHERE id = $1
22ms Error thrown: insufficient balanceBind parameters
Bind parameters are not captured by default. They often contain user-specific data that does not belong in an error package. If you need them for debugging, enable them explicitly:
errorcore.init({
service: "billing-api",
transport: { type: "file", path: "./errors.ndjson" },
captureDbBindParams: true,
encryptionKey: process.env.ERRORCORE_KEY,
});Bind parameters frequently contain sensitive data (user IDs, email addresses, tokens). Only enable this with encryption and a scrub policy that covers your parameter shapes.
Scrubbing
If your SQL statements contain inline values or identifiable table names that constitute sensitive data, use the piiScrubber config to normalize them before they reach the package:
errorcore.init({
service: "billing-api",
transport: { type: "file", path: "./errors.ndjson" },
encryptionKey: process.env.ERRORCORE_KEY,
piiScrubber: (key, value) => {
if (key === "query" && typeof value === "string") {
return value.replace(/VALUES\s*\(.*?\)/gi, "VALUES (...)");
}
return value;
},
});