
Product
Introducing Tier 1 Reachability: Precision CVE Triage for Enterprise Teams
Socket’s new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.
otel-instrumentation-postgres
Advanced tools
A OpenTelemetry instrumentation library for the Postgres.js
that provides observability for PostgreSQL database operations.
This instrumentation captures:
npm install otel-instrumentation-postgres
import { NodeSDK } from "@opentelemetry/sdk-node";
import { ConsoleSpanExporter } from "@opentelemetry/sdk-trace-node";
import { ConsoleMetricExporter, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
import { PostgresInstrumentation } from "otel-instrumentation-postgres";
const sdk = new NodeSDK({
traceExporter: new ConsoleSpanExporter(),
metricReader: new PeriodicExportingMetricReader({
exporter: new ConsoleMetricExporter(),
}),
instrumentations: [
new PostgresInstrumentation({
serviceName: "my-app",
collectQueryParameters: true
}),
],
});
sdk.start();
import postgres from "postgres";
import { createOTELEmitter } from "otel-instrumentation-postgres";
// Create your postgres client
const sql = postgres(process.env.DATABASE_URL);
// Wrap it with telemetry
const instrumentedSql = createOTELEmitter(sql);
// Use the instrumented client - all queries are now tracked
const users = await instrumentedSql`SELECT * FROM users WHERE active = ${true}`;
Option | Type | Default | Description |
---|---|---|---|
serviceName | string | - | Service name for telemetry attributes |
enableHistogram | boolean | true | Enable query duration histogram metrics |
histogramBuckets | number[] | [0.001, 0.01, 0.1, 0.5, 1, 2, 5, 10, 30, 60, 120, 300, 600] | Duration buckets in seconds |
collectQueryParameters | boolean | false | Include query parameters in spans |
serverAddress | string | process.env.PGHOST | Database server address |
serverPort | number | process.env.PGPORT | Database server port |
databaseName | string | process.env.PGDATABASE | Database name |
parameterSanitizer | Function | Built-in sanitizer | Custom parameter sanitization |
beforeSpan | Function | - | Hook called before span creation |
afterSpan | Function | - | Hook called after span completion |
responseHook | Function | - | Hook called with query result |
Each database query generates a span with rich attributes:
db.system.name
: "postgresql"
db.query.text
: Sanitized SQL querydb.operation.name
: SQL operation (SELECT, INSERT, etc.)db.namespace
: Database namedb.collection.name
: Extracted table namenet.peer.name
: Database server addressnet.peer.port
: Database server portexception.type
: Error type for failed queriesdb.parameter_count
: Number of query parametersdb.duration_ms
: Query duration in millisecondsdb.duration_seconds
: Query duration in secondsdb.query.has_where
: Whether query has WHERE clausedb.query.has_join
: Whether query has JOIN clausedb.query.has_order_by
: Whether query has ORDER BY clausedb.query.has_limit
: Whether query has LIMIT clausedb.query.complexity
: Estimated query complexity (low/medium/high)db.query.type
: Query type (read/write/schema/unknown)db.result.row_count
: Number of rows returned (for arrays)db.query.parameter.0
, db.query.parameter.1
, etc.: Individual query parameters (sanitized)db.client.operations.duration
: Histogram of query durationsdb.client.requests
: Counter of total queriesdb.client.errors
: Counter of failed queriesdb.client.connections
: Counter of database connectionsdb.client.connections.duration
: Histogram of connection durationsconst instrumentation = new PostgresInstrumentation({
parameterSanitizer: (param, index) => {
// Redact sensitive data
if (typeof param === "string") {
if (param.match(/^\d{4}-\d{4}-\d{4}-\d{4}$/)) {
return "****-****-****-" + param.slice(-4); // Credit card
}
if (param.includes("@")) {
return "[EMAIL]"; // Email addresses
}
}
// Truncate long values
const str = String(param);
return str.length > 50 ? str.substring(0, 50) + "..." : str;
},
});
const instrumentation = new PostgresInstrumentation({
serviceName: "user-service",
collectQueryParameters: true,
// Add custom attributes before span creation
beforeSpan: (span, event) => {
span.setAttribute("user.id", getCurrentUserId());
span.setAttribute("request.id", getRequestId());
},
// Monitor slow queries
afterSpan: (span, event) => {
if (event.durationMs > 1000) {
console.warn(`Slow query detected: ${event.sql} (${event.durationMs}ms)`);
}
},
// Analyze query results
responseHook: (span, result) => {
if (Array.isArray(result)) {
span.setAttribute("db.result.count", result.length);
if (result.length === 0) {
span.setAttribute("db.result.empty", true);
}
}
},
});
The library automatically analyzes your SQL queries:
// This query will generate:
// - operation: "SELECT"
// - table: "users"
// - has_where: true
// - has_order_by: true
// - has_limit: true
// - complexity: "medium"
// - type: "read"
const users = await instrumentedSql`
SELECT * FROM users
WHERE active = ${true}
ORDER BY created_at DESC
LIMIT 10
`;
// This query will generate:
// - operation: "INSERT"
// - table: "users"
// - has_where: false
// - complexity: "low"
// - type: "write"
await instrumentedSql`
INSERT INTO users (name, email)
VALUES (${name}, ${email})
`;
# Clone the repository
git clone https://github.com/wataruoguchi/otel-instrumentation-postgres.git
cd otel-instrumentation-postgres
# Install dependencies
cd lib && npm install
cd ../example && npm install
# Run tests
cd ../lib && npm test
# Build the package
npm run build
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
FAQs
OpenTelemetry instrumentation for postgres.js
We found that otel-instrumentation-postgres demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket’s new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.
Research
/Security News
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.
Security News
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.