UNPKG

@sentry/node

Version:

Sentry Node SDK using OpenTelemetry for performance instrumentation

110 lines (106 loc) 4.21 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const core = require('@sentry/core'); const nodeCore = require('@sentry/node-core'); const debugBuild = require('../../../debug-build.js'); const instrumentation = require('./vendored/instrumentation.js'); const INTEGRATION_NAME = "Prisma"; function isPrismaV6TracingHelper(helper) { return !!helper && typeof helper === "object" && "dispatchEngineSpans" in helper; } function getPrismaTracingHelper() { const prismaInstrumentationObject = globalThis.PRISMA_INSTRUMENTATION; const prismaTracingHelper = prismaInstrumentationObject && typeof prismaInstrumentationObject === "object" && "helper" in prismaInstrumentationObject ? prismaInstrumentationObject.helper : void 0; return prismaTracingHelper; } const MAX_TRACKED_PRISMA_SPANS = 1e3; const prismaSpanRegistry = new core.LRUMap(MAX_TRACKED_PRISMA_SPANS); const pendingEngineSpans = []; function registerPrismaSpan(id, span) { prismaSpanRegistry.set(id, span); } function createResolvedEngineSpans() { let createdSpan = true; while (createdSpan) { createdSpan = false; for (let i = pendingEngineSpans.length - 1; i >= 0; i--) { const engineSpan = pendingEngineSpans[i]; const parentSpan = prismaSpanRegistry.get(engineSpan.parent_span_id); if (!parentSpan) { continue; } const span = core.startInactiveSpan({ name: engineSpan.name, attributes: engineSpan.attributes, kind: engineSpan.kind === "client" ? core.SPAN_KIND.CLIENT : core.SPAN_KIND.INTERNAL, startTime: engineSpan.start_time, parentSpan }); registerPrismaSpan(engineSpan.span_id, span); if (engineSpan.links) { span.addLinks( engineSpan.links.flatMap((link) => { const linkedSpan = prismaSpanRegistry.get(link.span_id); return linkedSpan ? [{ context: linkedSpan.spanContext() }] : []; }) ); } span.end(engineSpan.end_time); pendingEngineSpans.splice(i, 1); createdSpan = true; } } } class SentryPrismaInteropInstrumentation extends instrumentation.PrismaInstrumentation { constructor(options) { super(options?.instrumentationConfig); } enable() { super.enable(); const prismaTracingHelper = getPrismaTracingHelper(); if (isPrismaV6TracingHelper(prismaTracingHelper)) { prismaTracingHelper.createEngineSpan = (engineSpanEvent) => { pendingEngineSpans.push(...engineSpanEvent.spans); createResolvedEngineSpans(); const overflow = pendingEngineSpans.length - MAX_TRACKED_PRISMA_SPANS; if (overflow > 0) { debugBuild.DEBUG_BUILD && core.debug.log(`[Prisma] Dropping ${overflow} unresolved v5 engine span(s) whose parent was never registered.`); pendingEngineSpans.splice(0, overflow); } }; } } } const instrumentPrisma = nodeCore.generateInstrumentOnce(INTEGRATION_NAME, (options) => { return new SentryPrismaInteropInstrumentation(options); }); const prismaIntegration = core.defineIntegration((options) => { return { name: INTEGRATION_NAME, setupOnce() { instrumentPrisma(options); }, setup(client) { if (!getPrismaTracingHelper()) { return; } client.on("spanStart", (span) => { const spanJSON = core.spanToJSON(span); if (spanJSON.description?.startsWith("prisma:")) { span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, "auto.db.otel.prisma"); if (spanJSON.description.startsWith("prisma:client:")) { registerPrismaSpan(span.spanContext().spanId, span); } } if ((spanJSON.description === "prisma:engine:db_query" || spanJSON.description === "prisma:client:db_query") && spanJSON.data["db.query.text"]) { span.updateName(spanJSON.data["db.query.text"]); } if (spanJSON.description === "prisma:engine:db_query" && !spanJSON.data["db.system"]) { span.setAttribute("db.system", "prisma"); } }); } }; }); exports.instrumentPrisma = instrumentPrisma; exports.prismaIntegration = prismaIntegration; //# sourceMappingURL=index.js.map