update docs

This commit is contained in:
Alex Holovach
2025-10-05 08:19:58 -05:00
parent e77c63390a
commit 7b7dc83f7d
2 changed files with 447 additions and 293 deletions

View File

@@ -42,117 +42,148 @@ Works with any observability platform that supports OpenTelemetry including:
## Usage
There are two ways to instrument Drizzle ORM with OpenTelemetry:
### Instrument Your Drizzle Database (Recommended)
### Option 1: Instrument the Connection Pool (Recommended)
Wrap your database connection pool with `instrumentDrizzle()` before passing it to Drizzle:
Use `instrumentDrizzleClient()` to add tracing to your Drizzle database instance. This is the simplest and most straightforward approach:
```typescript
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { instrumentDrizzle } from "@kubiks/otel-drizzle";
import { drizzle } from "drizzle-orm/postgres-js";
import { instrumentDrizzleClient } from "@kubiks/otel-drizzle";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const instrumentedPool = instrumentDrizzle(pool);
const db = drizzle(instrumentedPool);
// Create your Drizzle database instance as usual
const db = drizzle(process.env.DATABASE_URL!);
// Add instrumentation with a single line
instrumentDrizzleClient(db);
// That's it! All queries are now traced automatically
const users = await db.select().from(usersTable);
```
### Option 2: Instrument an Existing Drizzle Client
### Database-Specific Examples
If you already have a Drizzle database instance or don't have access to the underlying pool, use `instrumentDrizzleClient()`. This method instruments the database at the session level, capturing all query operations:
#### PostgreSQL
```typescript
// Works with postgres-js (Postgres.js)
// PostgreSQL with postgres.js (recommended for serverless)
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import { instrumentDrizzleClient } from "@kubiks/otel-drizzle";
import * as schema from "./schema";
const db = drizzle(process.env.DATABASE_URL!, { schema });
// Using connection string directly
const db = drizzle(process.env.DATABASE_URL!);
instrumentDrizzleClient(db, { dbSystem: "postgresql" });
// Instrument the existing database instance
instrumentDrizzleClient(db);
// All queries are now traced automatically
const users = await db.select().from(schema.users);
// Direct execute calls are also traced
await db.execute("SELECT * FROM users");
// Transactions are also traced
await db.transaction(async (tx) => {
await tx.insert(schema.users).values({ name: "John" });
// Or with a client instance
const queryClient = postgres(process.env.DATABASE_URL!);
const db = drizzle({ client: queryClient });
instrumentDrizzleClient(db, {
dbSystem: "postgresql",
dbName: "myapp",
peerName: "db.example.com",
peerPort: 5432,
});
```
### Optional Configuration
```typescript
// PostgreSQL with node-postgres (pg)
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { instrumentDrizzleClient } from "@kubiks/otel-drizzle";
Both instrumentation methods accept the same configuration options:
// Using connection string directly
const db = drizzle(process.env.DATABASE_URL!);
instrumentDrizzleClient(db, { dbSystem: "postgresql" });
// Or with a pool instance
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const db = drizzle({ client: pool });
instrumentDrizzleClient(db, { dbSystem: "postgresql" });
```
#### MySQL
```typescript
// Option 1: Instrument the pool
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const instrumentedPool = instrumentDrizzle(pool, {
dbSystem: "postgresql", // Database type (default: 'postgresql')
// MySQL with mysql2
import { drizzle } from "drizzle-orm/mysql2";
import mysql from "mysql2/promise";
import { instrumentDrizzleClient } from "@kubiks/otel-drizzle";
// Using connection string directly
const db = drizzle(process.env.DATABASE_URL!);
instrumentDrizzleClient(db, { dbSystem: "mysql" });
// Or with a connection instance
const connection = await mysql.createConnection({
host: "localhost",
user: "root",
database: "mydb",
// ... other connection options
});
const db = drizzle({ client: connection });
instrumentDrizzleClient(db, {
dbSystem: "mysql",
dbName: "mydb",
peerName: "localhost",
peerPort: 3306,
});
```
#### SQLite
```typescript
// SQLite with better-sqlite3
import { drizzle } from "drizzle-orm/better-sqlite3";
import Database from "better-sqlite3";
import { instrumentDrizzleClient } from "@kubiks/otel-drizzle";
// Using file path directly
const db = drizzle("sqlite.db");
instrumentDrizzleClient(db, { dbSystem: "sqlite" });
// Or with a Database instance
const sqlite = new Database("sqlite.db");
const db = drizzle({ client: sqlite });
instrumentDrizzleClient(db, { dbSystem: "sqlite" });
```
```typescript
// SQLite with LibSQL/Turso
import { drizzle } from "drizzle-orm/libsql";
import { createClient } from "@libsql/client";
import { instrumentDrizzleClient } from "@kubiks/otel-drizzle";
// Using connection config directly
const db = drizzle({
connection: {
url: process.env.DATABASE_URL!,
authToken: process.env.DATABASE_AUTH_TOKEN,
}
});
instrumentDrizzleClient(db, { dbSystem: "sqlite" });
// Or with a client instance
const client = createClient({
url: process.env.DATABASE_URL!,
authToken: process.env.DATABASE_AUTH_TOKEN,
});
const db = drizzle({ client });
instrumentDrizzleClient(db, { dbSystem: "sqlite" });
```
### Configuration Options
```typescript
instrumentDrizzleClient(db, {
dbSystem: "postgresql", // Database type: 'postgresql' | 'mysql' | 'sqlite' (default: 'postgresql')
dbName: "myapp", // Database name for spans
captureQueryText: true, // Include SQL in traces (default: true)
maxQueryTextLength: 1000, // Max SQL length (default: 1000)
peerName: "db.example.com", // Database server hostname
peerPort: 5432, // Database server port
});
const db = drizzle(instrumentedPool);
// Option 2: Instrument the Drizzle client
const db = drizzle(pool, { schema });
instrumentDrizzleClient(db, {
dbSystem: "postgresql",
dbName: "myapp",
captureQueryText: true,
peerName: "db.example.com",
peerPort: 5432,
});
```
### Works with All Drizzle-Supported Databases
This package automatically detects and instruments **all databases that Drizzle ORM supports**. It works by detecting whether your database driver uses a `query` or `execute` method and instrumenting it appropriately. This includes:
- **PostgreSQL** (node-postgres, postgres.js, Neon, Vercel Postgres, etc.)
- **MySQL** (mysql2, PlanetScale, TiDB, etc.)
- **SQLite** (better-sqlite3, LibSQL/Turso, Cloudflare D1, etc.)
- **And any other Drizzle-supported database**
```typescript
// PostgreSQL with postgres-js (Postgres.js) - use instrumentDrizzleClient
import { drizzle } from "drizzle-orm/postgres-js";
const db = drizzle(process.env.DATABASE_URL!);
instrumentDrizzleClient(db);
// PostgreSQL with node-postgres (pg) - use instrumentDrizzle on pool
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const db = drizzle(instrumentDrizzle(pool));
// MySQL with mysql2 (uses 'execute' or 'query' method)
import { drizzle } from "drizzle-orm/mysql2";
import mysql from "mysql2/promise";
const connection = await mysql.createConnection(process.env.DATABASE_URL);
const db = drizzle(instrumentDrizzle(connection, { dbSystem: "mysql" }));
// SQLite with better-sqlite3
import { drizzle } from "drizzle-orm/better-sqlite3";
import Database from "better-sqlite3";
const sqlite = new Database("database.db");
const db = drizzle(instrumentDrizzle(sqlite, { dbSystem: "sqlite" }));
// LibSQL/Turso (uses 'execute' method)
import { drizzle } from "drizzle-orm/libsql";
import { createClient } from "@libsql/client";
const client = createClient({ url: "...", authToken: "..." });
const db = drizzle(instrumentDrizzle(client, { dbSystem: "sqlite" }));
```
## What You Get

View File

@@ -143,16 +143,15 @@ function finalizeSpan(span: Span, error?: unknown): void {
}
/**
* Instruments a database connection pool or client with OpenTelemetry tracing.
* Instruments a database connection pool/client with OpenTelemetry tracing.
*
* This function wraps the connection's `query` or `execute` method to automatically create
* spans for each database operation. It automatically detects which method is available
* and instruments it appropriately for any database driver.
* The instrumentation is idempotent - calling it multiple times on the same
* connection will only instrument it once.
* This function wraps the connection's `query` and `execute` methods to create spans for each database
* operation.
* The instrumentation is idempotent - calling it multiple times on the same connection will only
* instrument it once.
*
* @typeParam TClient - The type of the database connection pool or client
* @param client - The database connection pool or client to instrument (e.g., pg Pool, mysql2 Connection, LibSQL Client)
* @param client - The database connection pool or client to instrument
* @param config - Optional configuration for instrumentation behavior
* @returns The instrumented pool/client (same instance, modified in place)
*
@@ -164,19 +163,13 @@ function finalizeSpan(span: Span, error?: unknown): void {
* import { instrumentDrizzle } from '@kubiks/otel-drizzle';
*
* const pool = new Pool({ connectionString: process.env.DATABASE_URL });
* const instrumentedPool = instrumentDrizzle(pool);
* const db = drizzle(instrumentedPool);
*
* // With custom configuration
* const instrumentedPool = instrumentDrizzle(pool, {
* dbSystem: 'postgresql',
* dbName: 'myapp',
* captureQueryText: true,
* maxQueryTextLength: 1000,
* peerName: 'db.example.com',
* peerPort: 5432,
* });
* const db = drizzle(instrumentedPool);
* const db = drizzle({ client: instrumentedPool });
* ```
*
* @example
@@ -186,8 +179,13 @@ function finalizeSpan(span: Span, error?: unknown): void {
* import mysql from 'mysql2/promise';
* import { instrumentDrizzle } from '@kubiks/otel-drizzle';
*
* const connection = await mysql.createConnection(process.env.DATABASE_URL);
* const db = drizzle(instrumentDrizzle(connection, { dbSystem: 'mysql' }));
* const connection = await mysql.createConnection({
* host: 'localhost',
* user: 'root',
* database: 'mydb',
* });
* const instrumentedConnection = instrumentDrizzle(connection, { dbSystem: 'mysql' });
* const db = drizzle({ client: instrumentedConnection });
* ```
*
* @example
@@ -197,19 +195,24 @@ function finalizeSpan(span: Span, error?: unknown): void {
* import Database from 'better-sqlite3';
* import { instrumentDrizzle } from '@kubiks/otel-drizzle';
*
* const sqlite = new Database('database.db');
* const db = drizzle(instrumentDrizzle(sqlite, { dbSystem: 'sqlite' }));
* const sqlite = new Database('sqlite.db');
* const instrumentedSqlite = instrumentDrizzle(sqlite, { dbSystem: 'sqlite' });
* const db = drizzle({ client: instrumentedSqlite });
* ```
*
* @example
* ```typescript
* // LibSQL/Turso (automatically detects 'execute' method)
* // LibSQL/Turso
* import { drizzle } from 'drizzle-orm/libsql';
* import { createClient } from '@libsql/client';
* import { instrumentDrizzle } from '@kubiks/otel-drizzle';
*
* const client = createClient({ url: '...', authToken: '...' });
* const db = drizzle(instrumentDrizzle(client, { dbSystem: 'sqlite' }));
* const client = createClient({
* url: process.env.DATABASE_URL!,
* authToken: process.env.DATABASE_AUTH_TOKEN,
* });
* const instrumentedClient = instrumentDrizzle(client, { dbSystem: 'sqlite' });
* const db = drizzle({ client: instrumentedClient });
* ```
*/
export function instrumentDrizzle<TClient extends DrizzleClientLike>(
@@ -369,21 +372,10 @@ interface DrizzleDbLike {
}
/**
* Instruments an already created Drizzle database instance with OpenTelemetry tracing.
* Instruments a Drizzle database instance with OpenTelemetry tracing.
*
* This function instruments the database at the session level, intercepting:
* - `session.prepareQuery` - Used by all query builders (select, insert, update, delete)
* - `session.query` - Used for direct SQL execution
* - `$client` methods - As a fallback for underlying connection
*
* This ensures all database operations are traced, whether you use:
* - Query builders: `db.select().from(table)`
* - Direct execution: `db.execute(sql)`
* - Transactions: `db.transaction()`
*
* This is useful when you have a Drizzle database instance created with
* `const db = drizzle(connectionString)` or `const db = drizzle(pool, { schema })`
* and want to add instrumentation to it without having direct access to the underlying pool.
* This function instruments the database at the session level, automatically tracing all database
* operations including query builders, direct SQL execution, and transactions.
*
* The instrumentation is idempotent - calling it multiple times on the same
* database will only instrument it once.
@@ -395,39 +387,109 @@ interface DrizzleDbLike {
*
* @example
* ```typescript
* // When you have a pre-created Drizzle database instance
* import { drizzle } from 'drizzle-orm/node-postgres';
* import { Pool } from 'pg';
* // PostgreSQL with postgres.js
* import { drizzle } from 'drizzle-orm/postgres-js';
* import postgres from 'postgres';
* import { instrumentDrizzleClient } from '@kubiks/otel-drizzle';
* import * as schema from './schema';
*
* const pool = new Pool({ connectionString: process.env.DATABASE_URL });
* const db = drizzle(pool, { schema });
* // Using connection string
* const db = drizzle(process.env.DATABASE_URL!);
* instrumentDrizzleClient(db, { dbSystem: 'postgresql' });
*
* // Instrument the existing db instance
* instrumentDrizzleClient(db, {
* dbSystem: 'postgresql',
* dbName: 'myapp',
* captureQueryText: true,
* peerName: 'db.example.com',
* peerPort: 5432,
* });
*
* // Now all queries through db are traced
* const users = await db.select().from(schema.users);
* // Or with a client instance
* const queryClient = postgres(process.env.DATABASE_URL!);
* const db = drizzle({ client: queryClient });
* instrumentDrizzleClient(db, { dbSystem: 'postgresql' });
* ```
*
* @example
* ```typescript
* // Works with any Drizzle driver
* // PostgreSQL with node-postgres (pg)
* import { drizzle } from 'drizzle-orm/node-postgres';
* import { Pool } from 'pg';
* import { instrumentDrizzleClient } from '@kubiks/otel-drizzle';
*
* // Using connection string
* const db = drizzle(process.env.DATABASE_URL!);
* instrumentDrizzleClient(db, { dbSystem: 'postgresql' });
*
* // Or with a pool
* const pool = new Pool({ connectionString: process.env.DATABASE_URL });
* const db = drizzle({ client: pool });
* instrumentDrizzleClient(db, {
* dbSystem: 'postgresql',
* dbName: 'myapp',
* peerName: 'db.example.com',
* peerPort: 5432,
* });
* ```
*
* @example
* ```typescript
* // MySQL with mysql2
* import { drizzle } from 'drizzle-orm/mysql2';
* import mysql from 'mysql2/promise';
* import { instrumentDrizzleClient } from '@kubiks/otel-drizzle';
*
* const connection = await mysql.createConnection(process.env.DATABASE_URL);
* const db = drizzle(connection);
*
* // Using connection string
* const db = drizzle(process.env.DATABASE_URL!);
* instrumentDrizzleClient(db, { dbSystem: 'mysql' });
*
* // Or with a connection
* const connection = await mysql.createConnection({
* host: 'localhost',
* user: 'root',
* database: 'mydb',
* });
* const db = drizzle({ client: connection });
* instrumentDrizzleClient(db, {
* dbSystem: 'mysql',
* dbName: 'mydb',
* peerName: 'localhost',
* peerPort: 3306,
* });
* ```
*
* @example
* ```typescript
* // SQLite with better-sqlite3
* import { drizzle } from 'drizzle-orm/better-sqlite3';
* import Database from 'better-sqlite3';
* import { instrumentDrizzleClient } from '@kubiks/otel-drizzle';
*
* // Using file path
* const db = drizzle('sqlite.db');
* instrumentDrizzleClient(db, { dbSystem: 'sqlite' });
*
* // Or with a Database instance
* const sqlite = new Database('sqlite.db');
* const db = drizzle({ client: sqlite });
* instrumentDrizzleClient(db, { dbSystem: 'sqlite' });
* ```
*
* @example
* ```typescript
* // SQLite with LibSQL/Turso
* import { drizzle } from 'drizzle-orm/libsql';
* import { createClient } from '@libsql/client';
* import { instrumentDrizzleClient } from '@kubiks/otel-drizzle';
*
* // Using connection config
* const db = drizzle({
* connection: {
* url: process.env.DATABASE_URL!,
* authToken: process.env.DATABASE_AUTH_TOKEN,
* }
* });
* instrumentDrizzleClient(db, { dbSystem: 'sqlite' });
*
* // Or with a client instance
* const client = createClient({
* url: process.env.DATABASE_URL!,
* authToken: process.env.DATABASE_AUTH_TOKEN,
* });
* const db = drizzle({ client });
* instrumentDrizzleClient(db, { dbSystem: 'sqlite' });
* ```
*/
export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
@@ -462,21 +524,29 @@ export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
const session = (db as any).session;
// Check if session has prepareQuery method (used by select/insert/update/delete)
if (typeof session.prepareQuery === "function" && !session[INSTRUMENTED_FLAG]) {
if (
typeof session.prepareQuery === "function" &&
!session[INSTRUMENTED_FLAG]
) {
const originalPrepareQuery = session.prepareQuery;
session.prepareQuery = function(...args: any[]) {
session.prepareQuery = function (...args: any[]) {
const prepared = originalPrepareQuery.apply(this, args);
// Wrap the prepared query's execute method
if (prepared && typeof prepared.execute === "function") {
const originalPreparedExecute = prepared.execute;
prepared.execute = function(this: any, ...executeArgs: any[]) {
prepared.execute = function (this: any, ...executeArgs: any[]) {
// Extract query information from the query object
const queryObj = args[0]; // The query object passed to prepareQuery
const queryText = queryObj?.sql || queryObj?.queryString || extractQueryText(queryObj);
const operation = queryText ? extractOperation(queryText) : undefined;
const queryText =
queryObj?.sql ||
queryObj?.queryString ||
extractQueryText(queryObj);
const operation = queryText
? extractOperation(queryText)
: undefined;
const spanName = operation
? `drizzle.${operation.toLowerCase()}`
: "drizzle.query";
@@ -494,7 +564,10 @@ export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
}
if (captureQueryText && queryText !== undefined) {
const sanitized = sanitizeQueryText(queryText, maxQueryTextLength);
const sanitized = sanitizeQueryText(
queryText,
maxQueryTextLength,
);
span.setAttribute(SEMATTRS_DB_STATEMENT, sanitized);
}
@@ -537,11 +610,16 @@ export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
}
// Also instrument direct query method if exists
if (typeof session.query === "function" && !session[INSTRUMENTED_FLAG + "_query"]) {
if (
typeof session.query === "function" &&
!session[INSTRUMENTED_FLAG + "_query"]
) {
const originalQuery = session.query;
session.query = function(this: any, queryString: string, params: any[]) {
const operation = queryString ? extractOperation(queryString) : undefined;
session.query = function (this: any, queryString: string, params: any[]) {
const operation = queryString
? extractOperation(queryString)
: undefined;
const spanName = operation
? `drizzle.${operation.toLowerCase()}`
: "drizzle.query";
@@ -598,29 +676,43 @@ export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
}
// Instrument transaction method to ensure transaction sessions are also instrumented
if (typeof session.transaction === "function" && !session[INSTRUMENTED_FLAG + "_transaction"]) {
if (
typeof session.transaction === "function" &&
!session[INSTRUMENTED_FLAG + "_transaction"]
) {
const originalTransaction = session.transaction;
session.transaction = function(this: any, transactionCallback: any, ...restArgs: any[]) {
session.transaction = function (
this: any,
transactionCallback: any,
...restArgs: any[]
) {
// Wrap the transaction callback to instrument the tx object
const wrappedCallback = async function(tx: any) {
const wrappedCallback = async function (tx: any) {
// Instrument the transaction's session if it has one
if (tx && (tx.session || tx._?.session || tx)) {
const txSession = tx.session || tx._?.session || tx;
// Instrument tx.execute if it exists
if (typeof tx.execute === "function" && !tx[INSTRUMENTED_FLAG + "_execute"]) {
if (
typeof tx.execute === "function" &&
!tx[INSTRUMENTED_FLAG + "_execute"]
) {
const originalTxExecute = tx.execute;
tx.execute = function(this: any, ...executeArgs: any[]) {
tx.execute = function (this: any, ...executeArgs: any[]) {
const queryText = extractQueryText(executeArgs[0]);
const operation = queryText ? extractOperation(queryText) : undefined;
const operation = queryText
? extractOperation(queryText)
: undefined;
const spanName = operation
? `drizzle.${operation.toLowerCase()}`
: "drizzle.query";
// Start span
const span = tracer.startSpan(spanName, { kind: SpanKind.CLIENT });
const span = tracer.startSpan(spanName, {
kind: SpanKind.CLIENT,
});
span.setAttribute(SEMATTRS_DB_SYSTEM, dbSystem);
span.setAttribute("db.transaction", true);
@@ -633,7 +725,10 @@ export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
}
if (captureQueryText && queryText !== undefined) {
const sanitized = sanitizeQueryText(queryText, maxQueryTextLength);
const sanitized = sanitizeQueryText(
queryText,
maxQueryTextLength,
);
span.setAttribute(SEMATTRS_DB_STATEMENT, sanitized);
}
@@ -671,27 +766,43 @@ export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
}
// Also instrument txSession.prepareQuery if it exists
if (typeof txSession.prepareQuery === "function" && !txSession[INSTRUMENTED_FLAG + "_tx"]) {
if (
typeof txSession.prepareQuery === "function" &&
!txSession[INSTRUMENTED_FLAG + "_tx"]
) {
const originalTxPrepareQuery = txSession.prepareQuery;
txSession.prepareQuery = function(...prepareArgs: any[]) {
const prepared = originalTxPrepareQuery.apply(this, prepareArgs);
txSession.prepareQuery = function (...prepareArgs: any[]) {
const prepared = originalTxPrepareQuery.apply(
this,
prepareArgs,
);
// Wrap the prepared query's execute method
if (prepared && typeof prepared.execute === "function") {
const originalPreparedExecute = prepared.execute;
prepared.execute = function(this: any, ...executeArgs: any[]) {
prepared.execute = function (
this: any,
...executeArgs: any[]
) {
// Extract query information from the query object
const queryObj = prepareArgs[0]; // The query object passed to prepareQuery
const queryText = queryObj?.sql || queryObj?.queryString || extractQueryText(queryObj);
const operation = queryText ? extractOperation(queryText) : undefined;
const queryText =
queryObj?.sql ||
queryObj?.queryString ||
extractQueryText(queryObj);
const operation = queryText
? extractOperation(queryText)
: undefined;
const spanName = operation
? `drizzle.${operation.toLowerCase()}`
: "drizzle.query";
// Start span
const span = tracer.startSpan(spanName, { kind: SpanKind.CLIENT });
const span = tracer.startSpan(spanName, {
kind: SpanKind.CLIENT,
});
span.setAttribute(SEMATTRS_DB_SYSTEM, dbSystem);
span.setAttribute("db.transaction", true);
@@ -704,7 +815,10 @@ export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
}
if (captureQueryText && queryText !== undefined) {
const sanitized = sanitizeQueryText(queryText, maxQueryTextLength);
const sanitized = sanitizeQueryText(
queryText,
maxQueryTextLength,
);
span.setAttribute(SEMATTRS_DB_STATEMENT, sanitized);
}
@@ -721,7 +835,10 @@ export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
// Execute the prepared query
return context.with(activeContext, () => {
try {
const result = originalPreparedExecute.apply(this, executeArgs);
const result = originalPreparedExecute.apply(
this,
executeArgs,
);
return Promise.resolve(result)
.then((value) => {
finalizeSpan(span);
@@ -759,19 +876,25 @@ export function instrumentDrizzleClient<TDb extends DrizzleDbLike>(
}
}
// Second priority: Try to instrument via $client
// This handles the underlying connection pool
if (db.$client && !instrumented) {
const client = db.$client;
// Check if client has query or execute function
if (typeof client.query === "function" || typeof client.execute === "function") {
if (
typeof client.query === "function" ||
typeof client.execute === "function"
) {
instrumentDrizzle(client, config);
instrumented = true;
}
}
// Third priority: Try to instrument via session.execute as fallback
if (db._ && db._.session && typeof db._.session.execute === "function" && !instrumented) {
if (
db._ &&
db._.session &&
typeof db._.session.execute === "function" &&
!instrumented
) {
const session = db._.session;
// Check if already instrumented