Skip to content

Commit 041a882

Browse files
committed
feat: initial db instrumentation
1 parent d1646c8 commit 041a882

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

packages/nuxt/src/module.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { consoleSandbox } from '@sentry/core';
1010
import * as path from 'path';
1111
import type { SentryNuxtModuleOptions } from './common/types';
1212
import { addDynamicImportEntryFileWrapper, addSentryTopImport, addServerConfigToBuild } from './vite/addServerConfig';
13+
import { addDatabaseInstrumentation } from './vite/databaseConfig';
1314
import { addMiddlewareImports, addMiddlewareInstrumentation } from './vite/middlewareConfig';
1415
import { setupSourceMaps } from './vite/sourceMaps';
1516
import { addOTelCommonJSImportAlias, findDefaultSdkInitFile } from './vite/utils';
@@ -126,6 +127,8 @@ export default defineNuxtModule<ModuleOptions>({
126127
// Preps the the middleware instrumentation module.
127128
if (serverConfigFile) {
128129
addMiddlewareImports();
130+
131+
addDatabaseInstrumentation(nuxt);
129132
}
130133

131134
nuxt.hooks.hook('nitro:init', nitro => {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import {
2+
type SpanAttributes,
3+
captureException,
4+
debug,
5+
flushIfServerless,
6+
SEMANTIC_ATTRIBUTE_SENTRY_OP,
7+
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
8+
SPAN_STATUS_ERROR,
9+
SPAN_STATUS_OK,
10+
startSpan,
11+
} from '@sentry/core';
12+
import type { Database } from 'db0';
13+
// eslint-disable-next-line import/no-extraneous-dependencies
14+
import { defineNitroPlugin, useDatabase } from 'nitropack/runtime';
15+
16+
/**
17+
* Creates a Nitro plugin that instruments the database calls.
18+
*/
19+
export default defineNitroPlugin(() => {
20+
const db = useDatabase();
21+
22+
debug.log('@sentry/nuxt: Instrumenting database...');
23+
24+
instrumentDatabase(db);
25+
26+
debug.log('@sentry/nuxt: Database instrumented.');
27+
});
28+
29+
function instrumentDatabase(db: Database): void {
30+
db.sql = new Proxy(db.sql, {
31+
apply(target, thisArg, args: Parameters<typeof db.sql>) {
32+
const query = args[0]?.[0];
33+
const attributes = getSpanAttributes(db, query);
34+
35+
return startSpan(
36+
{
37+
name: query || 'db.query',
38+
attributes,
39+
},
40+
async span => {
41+
try {
42+
const result = await target.apply(thisArg, args);
43+
span.setStatus({ code: SPAN_STATUS_OK });
44+
45+
return result;
46+
} catch (error) {
47+
span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
48+
captureException(error, {
49+
mechanism: {
50+
handled: false,
51+
type: attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN],
52+
},
53+
});
54+
55+
// Re-throw the error to be handled by the caller
56+
throw error;
57+
} finally {
58+
await flushIfServerless();
59+
}
60+
},
61+
);
62+
},
63+
});
64+
}
65+
66+
function getSpanAttributes(db: Database, query?: string): SpanAttributes {
67+
const attributes: SpanAttributes = {
68+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.nuxt',
69+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db',
70+
'db.system': db.dialect,
71+
};
72+
73+
if (query) {
74+
attributes['db.query'] = query;
75+
}
76+
77+
return attributes;
78+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { addServerPlugin, createResolver } from '@nuxt/kit';
2+
import { consoleSandbox } from '@sentry/core';
3+
import type { Nuxt } from 'nuxt/schema';
4+
5+
/**
6+
* Sets up the database instrumentation.
7+
*/
8+
export function addDatabaseInstrumentation(nuxt: Nuxt): void {
9+
if (!nuxt.options.nitro?.database) {
10+
consoleSandbox(() => {
11+
// eslint-disable-next-line no-console
12+
console.log('[Sentry] No database configuration found. Skipping database instrumentation.');
13+
});
14+
15+
return;
16+
}
17+
18+
addServerPlugin(createResolver(import.meta.url).resolve('./runtime/plugins/database.server'));
19+
}

0 commit comments

Comments
 (0)