1
1
import { Hub } from '@sentry/hub' ;
2
2
import { EventProcessor , Integration } from '@sentry/types' ;
3
- import { fill , isThenable , loadModule , logger } from '@sentry/utils' ;
3
+ import { isThenable , logger } from '@sentry/utils' ;
4
4
5
5
import { IS_DEBUG_BUILD } from '../../flags' ;
6
6
7
+ type PrismaAction =
8
+ | 'findUnique'
9
+ | 'findMany'
10
+ | 'findFirst'
11
+ | 'create'
12
+ | 'createMany'
13
+ | 'update'
14
+ | 'updateMany'
15
+ | 'upsert'
16
+ | 'delete'
17
+ | 'deleteMany'
18
+ | 'executeRaw'
19
+ | 'queryRaw'
20
+ | 'aggregate'
21
+ | 'count'
22
+ | 'runCommandRaw' ;
23
+
24
+ interface PrismaMiddlewareParams {
25
+ model ?: any ;
26
+ action : PrismaAction ;
27
+ args : any ;
28
+ dataPath : string [ ] ;
29
+ runInTransaction : boolean ;
30
+ }
31
+
32
+ type PrismaMiddleware < T = any > = (
33
+ params : PrismaMiddlewareParams ,
34
+ next : ( params : PrismaMiddlewareParams ) => Promise < T > ,
35
+ ) => Promise < T > ;
36
+
7
37
interface PrismaClient {
8
- prototype : {
9
- query : ( ) => void | Promise < unknown > ;
10
- } ;
38
+ $use : ( cb : PrismaMiddleware ) => void ;
11
39
}
12
40
13
41
/** Tracing integration for @prisma/client package */
@@ -22,38 +50,50 @@ export class Prisma implements Integration {
22
50
*/
23
51
public name : string = Prisma . id ;
24
52
53
+ /**
54
+ * Prisma ORM Client Instance
55
+ */
56
+ private readonly _client ?: PrismaClient ;
57
+
25
58
/**
26
59
* @inheritDoc
27
60
*/
28
- public setupOnce ( _ : ( callback : EventProcessor ) => void , getCurrentHub : ( ) => Hub ) : void {
29
- const pkg = loadModule < { PrismaClient : PrismaClient } > ( '@prisma/client' ) ;
61
+ public constructor ( options : { client ?: PrismaClient } = { } ) {
62
+ this . _client = options . client ;
63
+ }
30
64
31
- if ( ! pkg ) {
32
- IS_DEBUG_BUILD && logger . error ( 'Prisma integration was unable to require `@prisma/client` package.' ) ;
65
+ /**
66
+ * @inheritDoc
67
+ */
68
+ public setupOnce ( _ : ( callback : EventProcessor ) => void , getCurrentHub : ( ) => Hub ) : void {
69
+ if ( ! this . _client ) {
70
+ IS_DEBUG_BUILD && logger . error ( 'PrismaIntegration is missing a Prisma Client Instance' ) ;
33
71
return ;
34
72
}
35
73
36
- fill ( pkg . PrismaClient . prototype , '_executeRequest' , function ( orig : ( ) => void | Promise < unknown > ) {
37
- return function ( this : unknown , config : unknown ) {
38
- const scope = getCurrentHub ( ) . getScope ( ) ;
39
- const parentSpan = scope ?. getSpan ( ) ;
40
- const span = parentSpan ?. startChild ( {
41
- description : typeof config === 'string' ? config : ( config as { clientMethod : string } ) . clientMethod ,
42
- op : 'db' ,
43
- } ) ;
74
+ this . _client . $use ( ( params : PrismaMiddlewareParams , next : ( params : PrismaMiddlewareParams ) => Promise < unknown > ) => {
75
+ const scope = getCurrentHub ( ) . getScope ( ) ;
76
+ const parentSpan = scope ?. getSpan ( ) ;
77
+
78
+ const action = params . action ;
79
+ const model = params . model ;
44
80
45
- const rv = orig . call ( this , config ) ;
81
+ const span = parentSpan ?. startChild ( {
82
+ description : `Action: ${ action } , ${ model ? `Model: ${ model } ` : '' } ` ,
83
+ op : 'prisma' ,
84
+ } ) ;
46
85
47
- if ( isThenable ( rv ) ) {
48
- return rv . then ( ( res : unknown ) => {
49
- span ?. finish ( ) ;
50
- return res ;
51
- } ) ;
52
- }
86
+ const rv = next ( params ) ;
87
+
88
+ if ( isThenable ( rv ) ) {
89
+ return rv . then ( ( res : unknown ) => {
90
+ span ?. finish ( ) ;
91
+ return res ;
92
+ } ) ;
93
+ }
53
94
54
- span ?. finish ( ) ;
55
- return rv ;
56
- } ;
95
+ span ?. finish ( ) ;
96
+ return rv ;
57
97
} ) ;
58
98
}
59
99
}
0 commit comments