Trasys
Node.js SDK

Database Instrumentation

Instrument pg, Prisma, Drizzle, Mongoose, MongoDB, and Sequelize with the Trasys SDK — automatic for most clients, with manual wrappers for Prisma and Drizzle.

Database Instrumentation

Quick reference

ClientSetupNotes
pg (node-postgres)AutomaticNothing required
MongooseAutomaticNothing required
SequelizeAutomaticRequires @opentelemetry/instrumentation-sequelize
MongoDB driverOpt-inSet autoInstrument.mongodbDriver: true
PrismaManualCall sdk.wrapPrisma(client)
DrizzleManualPass sdk.drizzleLogger() to your Drizzle setup

PostgreSQL (pg / node-postgres)

Instrumented automatically via @opentelemetry/instrumentation-pg. Every pool.query() and client.query() call becomes a span. No code changes required.

const { Pool } = require('pg');
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

// Automatically traced — no changes needed
const result = await pool.query('SELECT * FROM users WHERE id = $1', [userId]);

Span attributes captured:

AttributeValue
db.systempostgresql
db.statementSQL with $1, $2 placeholders; actual values are never stored
db.operationSELECT, INSERT, UPDATE, DELETE
db.slow_querytrue when above slowQueryThresholdMs

Sequelize

Instrumented automatically, but requires two setup steps.

Step 1 — install the instrumentation package:

npm install @opentelemetry/instrumentation-sequelize

Step 2 — require the SDK before Sequelize:

// index.js — correct order
require('dotenv').config();
const { sdk } = require('./trasys');         // ← SDK first
const { Sequelize } = require('sequelize');  // ← then Sequelize

If Sequelize loads before the SDK initializes, the instrumentation patch does not apply and queries will not appear in your traces. Import order is the most common cause of missing Sequelize spans.

No changes needed to your Sequelize setup or model definitions once the import order is correct.

To disable Sequelize instrumentation:

createSdk({ autoInstrument: { sequelize: false } });

Prisma

Prisma requires a one-time manual wrapper because its instrumentation uses $use — a Prisma-specific middleware API that must be attached to each client instance.

const { PrismaClient } = require('@prisma/client');
const { sdk } = require('./trasys');

const prisma = sdk.wrapPrisma(new PrismaClient());
// TypeScript
import { PrismaClient } from '@prisma/client';
import { sdk } from './trasys';

const prisma = sdk.wrapPrisma(new PrismaClient());
export default prisma;

wrapPrisma returns the same client — no type changes, no casting required. Every query on the wrapped client is then traced:

const user   = await prisma.user.findUnique({ where: { id } });
// → span: prisma.User.findUnique

const result = await prisma.order.create({ data: { ... } });
// → span: prisma.Order.create

Span attributes captured:

AttributeExample
prisma.modelUser
prisma.actionfindUnique
db.systempostgresql
db.slow_querytrue when above threshold
prisma.in_txtrue for transactional queries

Drizzle

Drizzle exposes a logger option at construction time. Pass sdk.drizzleLogger() to wire it in:

import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
import { sdk } from './trasys';

const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const db   = drizzle(pool, { logger: sdk.drizzleLogger() });

// All queries are now traced
const users = await db.select().from(usersTable);

Mongoose

Mongoose is auto-instrumented when the mongoose package is installed. The SDK detects it at startup and registers a connection-level plugin.

const mongoose = require('mongoose');
await mongoose.connect(process.env.MONGODB_URI);
// All queries on this connection are now traced

For specific connections or manual control:

// Specific connection
const conn = await mongoose.createConnection(process.env.MONGODB_URI).asPromise();
sdk.wrapMongoose(conn);

// Per-schema plugin
const UserSchema = new mongoose.Schema({ ... });
UserSchema.plugin(sdk.mongoosePlugin());

Operations instrumented: find, findOne, findOneAndUpdate, findOneAndDelete, updateOne, updateMany, deleteOne, deleteMany, countDocuments, aggregate, and more.


MongoDB Driver (raw)

Disabled by default — Mongoose takes priority. Enable it only when using the raw driver without Mongoose:

createSdk({
  autoInstrument: {
    mongoose:      false, // disable Mongoose
    mongodbDriver: true,  // enable raw driver
  },
});

Slow query threshold

Queries exceeding database.slowQueryThresholdMs (default: 1000 ms) are flagged with db.slow_query: true in the dashboard.

createSdk({
  database: {
    slowQueryThresholdMs: 500, // flag anything over 500ms
  },
});

Sensitive column masking

Column names listed in database.maskColumns cause the SDK to mask the WHERE clause of any query that references them. The query structure is preserved; only the value context is masked.

Default masked columns: password, token, secret, card_number, ssn, api_key

createSdk({
  database: {
    maskColumns: ['password', 'token', 'recovery_code', 'totp_secret'],
  },
});

Next steps

  • Distributed Tracing — see database spans in the context of the full request trace
  • Logging — correlate log entries with database query spans

On this page