Skip to content

Commit 1630815

Browse files
bojbrookBridgeAR
andauthored
refactor(prisma): Prisma instrumentation rewrite (#7447)
* initial changes * Update tests * removed unsused tests * remove require * remove unhelpful comments * Update packages/datadog-plugin-prisma/test/index.spec.js Co-authored-by: Ruben Bridgewater <[email protected]> --------- Co-authored-by: Ruben Bridgewater <[email protected]>
1 parent de724d0 commit 1630815

File tree

6 files changed

+413
-319
lines changed

6 files changed

+413
-319
lines changed

packages/datadog-instrumentations/src/prisma.js

Lines changed: 19 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,38 @@
11
'use strict'
22

3-
const tracingChannel = require('dc-polyfill').tracingChannel
4-
3+
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
54
const { channel, addHook } = require('./helpers/instrument')
6-
const prismaEngineStart = channel('apm:prisma:engine:start')
7-
const clientCH = tracingChannel('apm:prisma:client')
8-
9-
const allowedClientSpanOperations = new Set([
10-
'operation',
11-
'serialize',
12-
'transaction',
13-
])
14-
15-
class DatadogTracingHelper {
16-
dbConfig = null
17-
18-
constructor (dbConfig = null) {
19-
this.dbConfig = dbConfig
20-
}
21-
22-
isEnabled () {
23-
return true
24-
}
25-
26-
// needs a sampled tracecontext to generate engine spans
27-
getTraceParent (context) {
28-
// TODO: Fix the id
29-
return '00-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bbbbbbbbbbbbbbbb-01' // valid sampled traceparent
30-
}
31-
32-
dispatchEngineSpans (spans) {
33-
for (const span of spans) {
34-
if (span.parentId === null) {
35-
prismaEngineStart.publish({ engineSpan: span, allEngineSpans: spans, dbConfig: this.dbConfig })
36-
}
37-
}
38-
}
39-
40-
getActiveContext () {
41-
// TODO: Fix context
42-
}
43-
44-
runInChildSpan (options, callback) {
45-
if (typeof options === 'string') {
46-
options = {
47-
name: options,
48-
}
49-
}
50-
51-
if (allowedClientSpanOperations.has(options.name)) {
52-
const ctx = {
53-
resourceName: options.name,
54-
attributes: options.attributes || {},
55-
}
56-
57-
if (options.name !== 'serialize') {
58-
return clientCH.tracePromise(callback, ctx, this, ...arguments)
59-
}
60-
61-
return clientCH.traceSync(callback, ctx, this, ...arguments)
62-
}
63-
return callback()
64-
}
65-
66-
setDbString (dbConfig) {
67-
this.dbConfig = dbConfig
68-
}
69-
}
5+
const prismaHelperInit = channel('apm:prisma:helper:init')
706

717
const prismaHook = (runtime, versions, name, isIitm) => {
728
const originalGetPrismaClient = runtime.getPrismaClient
739

7410
if (!originalGetPrismaClient) return runtime
75-
const datadogTracingHelper = new DatadogTracingHelper()
11+
12+
const prismaHelperCtx = {}
7613

7714
const wrappedGetPrismaClient = function (config) {
78-
const datasources = config.inlineDatasources?.db.url?.value
79-
if (datasources) {
80-
const dbConfig = parseDBString(datasources)
81-
datadogTracingHelper.setDbString(dbConfig)
15+
// Prisma config shapes vary by version/runtime entrypoint. We try a few known locations
16+
// and fall back to DATABASE_URL when present.
17+
const datasourceUrl =
18+
config?.inlineDatasources?.db?.url?.value ??
19+
config?.inlineDatasources?.db?.url ??
20+
config?.overrideDatasources?.db?.url ??
21+
config?.datasources?.db?.url ??
22+
config?.datasourceUrl ??
23+
getEnvironmentVariable('DATABASE_URL')
24+
25+
if (datasourceUrl && !prismaHelperCtx.dbConfig) {
26+
prismaHelperCtx.dbConfig = parseDBString(datasourceUrl)
8227
}
28+
prismaHelperInit.publish(prismaHelperCtx)
8329

8430
const PrismaClient = originalGetPrismaClient.call(this, config)
8531
return class WrappedPrismaClientClass extends PrismaClient {
8632
constructor (clientConfig) {
8733
super(clientConfig)
88-
this._tracingHelper = datadogTracingHelper
89-
this._engine.tracingHelper = datadogTracingHelper
34+
this._tracingHelper = prismaHelperCtx.helper
35+
this._engine.tracingHelper = prismaHelperCtx.helper
9036
}
9137
}
9238
}

packages/datadog-plugin-prisma/src/client.js

Lines changed: 0 additions & 60 deletions
This file was deleted.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
'use strict'
2+
3+
const tracingChannel = require('dc-polyfill').tracingChannel
4+
const clientCH = tracingChannel('apm:prisma')
5+
const { storage } = require('../../datadog-core')
6+
7+
const allowedClientSpanOperations = new Set([
8+
'operation',
9+
'serialize',
10+
'transaction',
11+
])
12+
13+
/**
14+
* @typedef {object} DbConfig
15+
* @property {string} [user]
16+
* @property {string} [password]
17+
* @property {string} [host]
18+
* @property {string} [port]
19+
* @property {string} [database]
20+
*/
21+
22+
class DatadogTracingHelper {
23+
#prismaClient
24+
#dbConfig
25+
26+
/**
27+
* @param {DbConfig|undefined} dbConfig
28+
* @param {import('./index')} prismaClient
29+
*/
30+
constructor (dbConfig, prismaClient) {
31+
this.#dbConfig = dbConfig
32+
this.#prismaClient = prismaClient
33+
}
34+
35+
isEnabled () {
36+
return true
37+
}
38+
39+
// needs a sampled tracecontext to generate engine spans
40+
getTraceParent (context) {
41+
const store = storage('legacy').getStore()
42+
const span = store?.span
43+
if (span?._spanContext) {
44+
const context = span._spanContext
45+
46+
const traceId = context.toTraceId(true)
47+
const spanId = context.toSpanId(true)
48+
const version = (context._traceparent && context._traceparent.version) || '00'
49+
50+
// always sampled a sampled traceparent due to the following reasons:
51+
// 1. Datadog spans are sampled on span.finish
52+
// 2. Prisma engine spans only generate spans when the trace is sampled
53+
return `${version}-${traceId}-${spanId}-01`
54+
}
55+
56+
// No active span - return sampled
57+
return '00-00000000000000000000000000000000-0000000000000000-01'
58+
}
59+
60+
dispatchEngineSpans (spans) {
61+
for (const span of spans) {
62+
if (span.parentId === null) {
63+
this.#prismaClient.startEngineSpan({ engineSpan: span, allEngineSpans: spans, dbConfig: this.#dbConfig })
64+
}
65+
}
66+
}
67+
68+
getActiveContext () {
69+
const store = storage('legacy').getStore()
70+
return store?.span?._spanContext
71+
}
72+
73+
runInChildSpan (options, callback) {
74+
if (typeof options === 'string') {
75+
options = {
76+
name: options,
77+
}
78+
}
79+
if (allowedClientSpanOperations.has(options.name)) {
80+
const ctx = {
81+
resourceName: options.name,
82+
attributes: options.attributes || {},
83+
}
84+
85+
if (options.name !== 'serialize') {
86+
return clientCH.tracePromise(callback, ctx, this, ...arguments)
87+
}
88+
89+
return clientCH.traceSync(callback, ctx, this, ...arguments)
90+
}
91+
return callback()
92+
}
93+
}
94+
95+
module.exports = DatadogTracingHelper

packages/datadog-plugin-prisma/src/engine.js

Lines changed: 0 additions & 81 deletions
This file was deleted.

0 commit comments

Comments
 (0)