Skip to content

Commit

Permalink
fix(tracing): Instrument Prisma client in constructor of integration
Browse files Browse the repository at this point in the history
  • Loading branch information
lforst committed Jun 22, 2023
1 parent da2487e commit 3483a62
Showing 1 changed file with 27 additions and 30 deletions.
57 changes: 27 additions & 30 deletions packages/tracing-internal/src/node/integrations/prisma.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { Hub } from '@sentry/core';
import { trace } from '@sentry/core';
import type { EventProcessor, Integration } from '@sentry/types';
import { logger } from '@sentry/utils';
import { getCurrentHub, trace } from '@sentry/core';
import type { Integration } from '@sentry/types';
import { addNonEnumerableProperty, logger } from '@sentry/utils';

import { shouldDisableAutoInstrumentation } from './utils/node-utils';

Expand Down Expand Up @@ -36,6 +35,7 @@ type PrismaMiddleware<T = unknown> = (
) => Promise<T>;

interface PrismaClient {
_sentryInstrumented?: boolean;
$use: (cb: PrismaMiddleware) => void;
}

Expand All @@ -55,17 +55,31 @@ export class Prisma implements Integration {
*/
public name: string = Prisma.id;

/**
* Prisma ORM Client Instance
*/
private readonly _client?: PrismaClient;

/**
* @inheritDoc
*/
public constructor(options: { client?: unknown } = {}) {
if (isValidPrismaClient(options.client)) {
this._client = options.client;
// We instrument the PrismaClient inside the constructor and not inside `setupOnce` because in some cases of server-side
// bundling (Next.js) multiple Prisma clients can be instantiated, even though users don't intend to. When instrumenting
// in setupOnce we can only ever instrument one client.
// https://github.com/getsentry/sentry-javascript/issues/7216#issuecomment-1602375012
// In the future we might explore providing a dedicated PrismaClient middleware instead of this hack.
if (isValidPrismaClient(options.client) && !options.client._sentryInstrumented) {
addNonEnumerableProperty(options.client as any, '_sentryInstrumented', true);

if (shouldDisableAutoInstrumentation(getCurrentHub)) {
__DEBUG_BUILD__ && logger.log('Prisma Integration is skipped because of instrumenter configuration.');
return;
}

options.client.$use((params, next: (params: PrismaMiddlewareParams) => Promise<unknown>) => {
const action = params.action;
const model = params.model;
return trace(
{ name: model ? `${model} ${action}` : action, op: 'db.sql.prisma', data: { 'db.system': 'prisma' } },
() => next(params),
);
});
} else {
__DEBUG_BUILD__ &&
logger.warn(
Expand All @@ -77,24 +91,7 @@ export class Prisma implements Integration {
/**
* @inheritDoc
*/
public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void {
if (!this._client) {
__DEBUG_BUILD__ && logger.error('PrismaIntegration is missing a Prisma Client Instance');
return;
}

if (shouldDisableAutoInstrumentation(getCurrentHub)) {
__DEBUG_BUILD__ && logger.log('Prisma Integration is skipped because of instrumenter configuration.');
return;
}

this._client.$use((params, next: (params: PrismaMiddlewareParams) => Promise<unknown>) => {
const action = params.action;
const model = params.model;
return trace(
{ name: model ? `${model} ${action}` : action, op: 'db.sql.prisma', data: { 'db.system': 'prisma' } },
() => next(params),
);
});
public setupOnce(): void {
// Noop - here for backwards compatibility
}
}

0 comments on commit 3483a62

Please sign in to comment.