@sentry/node
Version:
Sentry Node SDK using OpenTelemetry for performance instrumentation
110 lines (106 loc) • 4.21 kB
JavaScript
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