Proprely handle errors with drizzle-otel

This commit is contained in:
2025-11-17 22:06:53 +01:00
parent 595b6eea7c
commit 1323e5a62a
3 changed files with 21 additions and 45 deletions

View File

@@ -41,7 +41,7 @@
"@opentelemetry/sdk-trace-base": "^2.1.0", "@opentelemetry/sdk-trace-base": "^2.1.0",
"@types/node": "18.15.11", "@types/node": "18.15.11",
"@types/pg": "^8.11.10", "@types/pg": "^8.11.10",
"drizzle-orm": "^0.36.4", "drizzle-orm": "^0.44.7",
"postgres": "^3.4.7", "postgres": "^3.4.7",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"typescript": "^5", "typescript": "^5",

View File

@@ -5,6 +5,7 @@ import {
trace, trace,
type Span, type Span,
} from "@opentelemetry/api"; } from "@opentelemetry/api";
import { DrizzleQueryError } from "drizzle-orm";
const DEFAULT_TRACER_NAME = "@kubiks/otel-drizzle"; const DEFAULT_TRACER_NAME = "@kubiks/otel-drizzle";
const DEFAULT_DB_SYSTEM = "postgresql"; const DEFAULT_DB_SYSTEM = "postgresql";
@@ -130,7 +131,12 @@ function extractOperation(queryText: string): string | undefined {
*/ */
function finalizeSpan(span: Span, error?: unknown): void { function finalizeSpan(span: Span, error?: unknown): void {
if (error) { if (error) {
if (error instanceof Error) { if (error instanceof DrizzleQueryError && error.cause) {
// special handling for node-postgres
if ("detail" in error.cause && typeof error.cause.detail === "string")
error.cause.stack = error.cause.detail;
span.recordException(error.cause)
} else if (error instanceof Error) {
span.recordException(error); span.recordException(error);
} else { } else {
span.recordException(new Error(String(error))); span.recordException(new Error(String(error)));

56
pnpm-lock.yaml generated
View File

@@ -111,8 +111,8 @@ importers:
specifier: ^8.11.10 specifier: ^8.11.10
version: 8.15.5 version: 8.15.5
drizzle-orm: drizzle-orm:
specifier: ^0.36.4 specifier: ^0.44.7
version: 0.36.4(@opentelemetry/api@1.9.0)(@types/pg@8.15.5)(@types/react@18.2.46)(kysely@0.28.7)(postgres@3.4.7)(react@18.2.0) version: 0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.5)(kysely@0.28.7)(postgres@3.4.7)
postgres: postgres:
specifier: ^3.4.7 specifier: ^3.4.7
version: 3.4.7 version: 3.4.7
@@ -953,15 +953,6 @@ packages:
'@types/pg@8.15.5': '@types/pg@8.15.5':
resolution: {integrity: sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==} resolution: {integrity: sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==}
'@types/prop-types@15.7.11':
resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==}
'@types/react@18.2.46':
resolution: {integrity: sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w==}
'@types/scheduler@0.16.8':
resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==}
'@types/semver@7.5.6': '@types/semver@7.5.6':
resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==}
@@ -1270,9 +1261,6 @@ packages:
crypto-js@4.2.0: crypto-js@4.2.0:
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
csv-generate@3.4.3: csv-generate@3.4.3:
resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==}
@@ -1371,36 +1359,36 @@ packages:
resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==}
engines: {node: '>=10'} engines: {node: '>=10'}
drizzle-orm@0.36.4: drizzle-orm@0.44.7:
resolution: {integrity: sha512-1OZY3PXD7BR00Gl61UUOFihslDldfH4NFRH2MbP54Yxi0G/PKn4HfO65JYZ7c16DeP3SpM3Aw+VXVG9j6CRSXA==} resolution: {integrity: sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ==}
peerDependencies: peerDependencies:
'@aws-sdk/client-rds-data': '>=3' '@aws-sdk/client-rds-data': '>=3'
'@cloudflare/workers-types': '>=3' '@cloudflare/workers-types': '>=4'
'@electric-sql/pglite': '>=0.2.0' '@electric-sql/pglite': '>=0.2.0'
'@libsql/client': '>=0.10.0' '@libsql/client': '>=0.10.0'
'@libsql/client-wasm': '>=0.10.0' '@libsql/client-wasm': '>=0.10.0'
'@neondatabase/serverless': '>=0.10.0' '@neondatabase/serverless': '>=0.10.0'
'@op-engineering/op-sqlite': '>=2' '@op-engineering/op-sqlite': '>=2'
'@opentelemetry/api': ^1.4.1 '@opentelemetry/api': ^1.4.1
'@planetscale/database': '>=1' '@planetscale/database': '>=1.13'
'@prisma/client': '*' '@prisma/client': '*'
'@tidbcloud/serverless': '*' '@tidbcloud/serverless': '*'
'@types/better-sqlite3': '*' '@types/better-sqlite3': '*'
'@types/pg': '*' '@types/pg': '*'
'@types/react': '>=18'
'@types/sql.js': '*' '@types/sql.js': '*'
'@upstash/redis': '>=1.34.7'
'@vercel/postgres': '>=0.8.0' '@vercel/postgres': '>=0.8.0'
'@xata.io/client': '*' '@xata.io/client': '*'
better-sqlite3: '>=7' better-sqlite3: '>=7'
bun-types: '*' bun-types: '*'
expo-sqlite: '>=14.0.0' expo-sqlite: '>=14.0.0'
gel: '>=2'
knex: '*' knex: '*'
kysely: '*' kysely: '*'
mysql2: '>=2' mysql2: '>=2'
pg: '>=8' pg: '>=8'
postgres: '>=3' postgres: '>=3'
prisma: '*' prisma: '*'
react: '>=18'
sql.js: '>=1' sql.js: '>=1'
sqlite3: '>=5' sqlite3: '>=5'
peerDependenciesMeta: peerDependenciesMeta:
@@ -1430,10 +1418,10 @@ packages:
optional: true optional: true
'@types/pg': '@types/pg':
optional: true optional: true
'@types/react':
optional: true
'@types/sql.js': '@types/sql.js':
optional: true optional: true
'@upstash/redis':
optional: true
'@vercel/postgres': '@vercel/postgres':
optional: true optional: true
'@xata.io/client': '@xata.io/client':
@@ -1444,6 +1432,8 @@ packages:
optional: true optional: true
expo-sqlite: expo-sqlite:
optional: true optional: true
gel:
optional: true
knex: knex:
optional: true optional: true
kysely: kysely:
@@ -1456,8 +1446,6 @@ packages:
optional: true optional: true
prisma: prisma:
optional: true optional: true
react:
optional: true
sql.js: sql.js:
optional: true optional: true
sqlite3: sqlite3:
@@ -3599,19 +3587,6 @@ snapshots:
pg-protocol: 1.10.3 pg-protocol: 1.10.3
pg-types: 2.2.0 pg-types: 2.2.0
'@types/prop-types@15.7.11':
optional: true
'@types/react@18.2.46':
dependencies:
'@types/prop-types': 15.7.11
'@types/scheduler': 0.16.8
csstype: 3.1.3
optional: true
'@types/scheduler@0.16.8':
optional: true
'@types/semver@7.5.6': {} '@types/semver@7.5.6': {}
'@types/webidl-conversions@7.0.3': {} '@types/webidl-conversions@7.0.3': {}
@@ -3936,9 +3911,6 @@ snapshots:
crypto-js@4.2.0: {} crypto-js@4.2.0: {}
csstype@3.1.3:
optional: true
csv-generate@3.4.3: {} csv-generate@3.4.3: {}
csv-parse@4.16.3: {} csv-parse@4.16.3: {}
@@ -4028,14 +4000,12 @@ snapshots:
dotenv@8.6.0: {} dotenv@8.6.0: {}
drizzle-orm@0.36.4(@opentelemetry/api@1.9.0)(@types/pg@8.15.5)(@types/react@18.2.46)(kysely@0.28.7)(postgres@3.4.7)(react@18.2.0): drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(@types/pg@8.15.5)(kysely@0.28.7)(postgres@3.4.7):
optionalDependencies: optionalDependencies:
'@opentelemetry/api': 1.9.0 '@opentelemetry/api': 1.9.0
'@types/pg': 8.15.5 '@types/pg': 8.15.5
'@types/react': 18.2.46
kysely: 0.28.7 kysely: 0.28.7
postgres: 3.4.7 postgres: 3.4.7
react: 18.2.0
e2b@2.6.2: e2b@2.6.2:
dependencies: dependencies: