@sentry/node 10.11.0 → 10.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/index.js +10 -7
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/http.js +24 -13
- package/build/cjs/integrations/http.js.map +1 -1
- package/build/cjs/integrations/tracing/anthropic-ai/index.js +2 -2
- package/build/cjs/integrations/tracing/anthropic-ai/index.js.map +1 -1
- package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js +6 -17
- package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/connect.js +6 -1
- package/build/cjs/integrations/tracing/connect.js.map +1 -1
- package/build/cjs/integrations/tracing/express.js +1 -1
- package/build/cjs/integrations/tracing/express.js.map +1 -1
- package/build/cjs/integrations/tracing/fastify/index.js +1 -1
- package/build/cjs/integrations/tracing/fastify/index.js.map +1 -1
- package/build/cjs/integrations/tracing/firebase/otel/patches/firestore.js +3 -0
- package/build/cjs/integrations/tracing/firebase/otel/patches/firestore.js.map +1 -1
- package/build/cjs/integrations/tracing/google-genai/index.js +78 -0
- package/build/cjs/integrations/tracing/google-genai/index.js.map +1 -0
- package/build/cjs/integrations/tracing/google-genai/instrumentation.js +94 -0
- package/build/cjs/integrations/tracing/google-genai/instrumentation.js.map +1 -0
- package/build/cjs/integrations/tracing/hapi/index.js +1 -4
- package/build/cjs/integrations/tracing/hapi/index.js.map +1 -1
- package/build/cjs/integrations/tracing/index.js +3 -0
- package/build/cjs/integrations/tracing/index.js.map +1 -1
- package/build/cjs/integrations/tracing/koa.js +6 -1
- package/build/cjs/integrations/tracing/koa.js.map +1 -1
- package/build/cjs/integrations/tracing/openai/instrumentation.js +3 -3
- package/build/cjs/integrations/tracing/openai/instrumentation.js.map +1 -1
- package/build/cjs/integrations/tracing/prisma.js +117 -56
- package/build/cjs/integrations/tracing/prisma.js.map +1 -1
- package/build/cjs/integrations/tracing/vercelai/instrumentation.js +44 -46
- package/build/cjs/integrations/tracing/vercelai/instrumentation.js.map +1 -1
- package/build/cjs/sdk/initOtel.js +1 -35
- package/build/cjs/sdk/initOtel.js.map +1 -1
- package/build/esm/index.js +2 -1
- package/build/esm/index.js.map +1 -1
- package/build/esm/integrations/http.js +25 -14
- package/build/esm/integrations/http.js.map +1 -1
- package/build/esm/integrations/tracing/anthropic-ai/index.js +2 -2
- package/build/esm/integrations/tracing/anthropic-ai/index.js.map +1 -1
- package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js +7 -18
- package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/connect.js +6 -1
- package/build/esm/integrations/tracing/connect.js.map +1 -1
- package/build/esm/integrations/tracing/express.js +1 -1
- package/build/esm/integrations/tracing/express.js.map +1 -1
- package/build/esm/integrations/tracing/fastify/index.js +1 -1
- package/build/esm/integrations/tracing/fastify/index.js.map +1 -1
- package/build/esm/integrations/tracing/firebase/otel/patches/firestore.js +3 -0
- package/build/esm/integrations/tracing/firebase/otel/patches/firestore.js.map +1 -1
- package/build/esm/integrations/tracing/google-genai/index.js +75 -0
- package/build/esm/integrations/tracing/google-genai/index.js.map +1 -0
- package/build/esm/integrations/tracing/google-genai/instrumentation.js +92 -0
- package/build/esm/integrations/tracing/google-genai/instrumentation.js.map +1 -0
- package/build/esm/integrations/tracing/hapi/index.js +1 -4
- package/build/esm/integrations/tracing/hapi/index.js.map +1 -1
- package/build/esm/integrations/tracing/index.js +3 -0
- package/build/esm/integrations/tracing/index.js.map +1 -1
- package/build/esm/integrations/tracing/koa.js +6 -1
- package/build/esm/integrations/tracing/koa.js.map +1 -1
- package/build/esm/integrations/tracing/openai/instrumentation.js +4 -4
- package/build/esm/integrations/tracing/openai/instrumentation.js.map +1 -1
- package/build/esm/integrations/tracing/prisma.js +117 -56
- package/build/esm/integrations/tracing/prisma.js.map +1 -1
- package/build/esm/integrations/tracing/vercelai/instrumentation.js +45 -47
- package/build/esm/integrations/tracing/vercelai/instrumentation.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/sdk/initOtel.js +4 -36
- package/build/esm/sdk/initOtel.js.map +1 -1
- package/build/types/index.d.ts +2 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/http.d.ts +2 -2
- package/build/types/integrations/http.d.ts.map +1 -1
- package/build/types/integrations/tracing/anthropic-ai/index.d.ts +1 -2
- package/build/types/integrations/tracing/anthropic-ai/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/anthropic-ai/instrumentation.d.ts +5 -6
- package/build/types/integrations/tracing/anthropic-ai/instrumentation.d.ts.map +1 -1
- package/build/types/integrations/tracing/connect.d.ts.map +1 -1
- package/build/types/integrations/tracing/firebase/otel/patches/firestore.d.ts +4 -2
- package/build/types/integrations/tracing/firebase/otel/patches/firestore.d.ts.map +1 -1
- package/build/types/integrations/tracing/google-genai/index.d.ts +59 -0
- package/build/types/integrations/tracing/google-genai/index.d.ts.map +1 -0
- package/build/types/integrations/tracing/google-genai/instrumentation.d.ts +20 -0
- package/build/types/integrations/tracing/google-genai/instrumentation.d.ts.map +1 -0
- package/build/types/integrations/tracing/hapi/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/koa.d.ts.map +1 -1
- package/build/types/integrations/tracing/prisma.d.ts +9 -13
- package/build/types/integrations/tracing/prisma.d.ts.map +1 -1
- package/build/types/integrations/tracing/vercelai/instrumentation.d.ts.map +1 -1
- package/build/types/sdk/initOtel.d.ts +0 -2
- package/build/types/sdk/initOtel.d.ts.map +1 -1
- package/build/types-ts3.8/index.d.ts +2 -1
- package/build/types-ts3.8/integrations/http.d.ts +2 -2
- package/build/types-ts3.8/integrations/tracing/anthropic-ai/index.d.ts +1 -2
- package/build/types-ts3.8/integrations/tracing/anthropic-ai/instrumentation.d.ts +5 -6
- package/build/types-ts3.8/integrations/tracing/firebase/otel/patches/firestore.d.ts +4 -2
- package/build/types-ts3.8/integrations/tracing/google-genai/index.d.ts +59 -0
- package/build/types-ts3.8/integrations/tracing/google-genai/instrumentation.d.ts +20 -0
- package/build/types-ts3.8/integrations/tracing/prisma.d.ts +9 -13
- package/build/types-ts3.8/sdk/initOtel.d.ts +0 -2
- package/package.json +32 -32
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { GOOGLE_GENAI_INTEGRATION_NAME, defineIntegration } from '@sentry/core';
|
|
2
|
+
import { generateInstrumentOnce } from '@sentry/node-core';
|
|
3
|
+
import { SentryGoogleGenAiInstrumentation } from './instrumentation.js';
|
|
4
|
+
|
|
5
|
+
const instrumentGoogleGenAI = generateInstrumentOnce(
|
|
6
|
+
GOOGLE_GENAI_INTEGRATION_NAME,
|
|
7
|
+
options => new SentryGoogleGenAiInstrumentation(options),
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
const _googleGenAIIntegration = ((options = {}) => {
|
|
11
|
+
return {
|
|
12
|
+
name: GOOGLE_GENAI_INTEGRATION_NAME,
|
|
13
|
+
setupOnce() {
|
|
14
|
+
instrumentGoogleGenAI(options);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}) ;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Adds Sentry tracing instrumentation for the Google Generative AI SDK.
|
|
21
|
+
*
|
|
22
|
+
* This integration is enabled by default.
|
|
23
|
+
*
|
|
24
|
+
* When configured, this integration automatically instruments Google GenAI SDK client instances
|
|
25
|
+
* to capture telemetry data following OpenTelemetry Semantic Conventions for Generative AI.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```javascript
|
|
29
|
+
* import * as Sentry from '@sentry/node';
|
|
30
|
+
*
|
|
31
|
+
* Sentry.init({
|
|
32
|
+
* integrations: [Sentry.googleGenAiIntegration()],
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* ## Options
|
|
37
|
+
*
|
|
38
|
+
* - `recordInputs`: Whether to record prompt messages (default: respects `sendDefaultPii` client option)
|
|
39
|
+
* - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)
|
|
40
|
+
*
|
|
41
|
+
* ### Default Behavior
|
|
42
|
+
*
|
|
43
|
+
* By default, the integration will:
|
|
44
|
+
* - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options
|
|
45
|
+
* - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```javascript
|
|
49
|
+
* // Record inputs and outputs when sendDefaultPii is false
|
|
50
|
+
* Sentry.init({
|
|
51
|
+
* integrations: [
|
|
52
|
+
* Sentry.googleGenAiIntegration({
|
|
53
|
+
* recordInputs: true,
|
|
54
|
+
* recordOutputs: true
|
|
55
|
+
* })
|
|
56
|
+
* ],
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* // Never record inputs/outputs regardless of sendDefaultPii
|
|
60
|
+
* Sentry.init({
|
|
61
|
+
* sendDefaultPii: true,
|
|
62
|
+
* integrations: [
|
|
63
|
+
* Sentry.googleGenAiIntegration({
|
|
64
|
+
* recordInputs: false,
|
|
65
|
+
* recordOutputs: false
|
|
66
|
+
* })
|
|
67
|
+
* ],
|
|
68
|
+
* });
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
*/
|
|
72
|
+
const googleGenAIIntegration = defineIntegration(_googleGenAIIntegration);
|
|
73
|
+
|
|
74
|
+
export { googleGenAIIntegration, instrumentGoogleGenAI };
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/google-genai/index.ts"],"sourcesContent":["import type { GoogleGenAIOptions, IntegrationFn } from '@sentry/core';\nimport { defineIntegration, GOOGLE_GENAI_INTEGRATION_NAME } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { SentryGoogleGenAiInstrumentation } from './instrumentation';\n\nexport const instrumentGoogleGenAI = generateInstrumentOnce<GoogleGenAIOptions>(\n GOOGLE_GENAI_INTEGRATION_NAME,\n options => new SentryGoogleGenAiInstrumentation(options),\n);\n\nconst _googleGenAIIntegration = ((options: GoogleGenAIOptions = {}) => {\n return {\n name: GOOGLE_GENAI_INTEGRATION_NAME,\n setupOnce() {\n instrumentGoogleGenAI(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the Google Generative AI SDK.\n *\n * This integration is enabled by default.\n *\n * When configured, this integration automatically instruments Google GenAI SDK client instances\n * to capture telemetry data following OpenTelemetry Semantic Conventions for Generative AI.\n *\n * @example\n * ```javascript\n * import * as Sentry from '@sentry/node';\n *\n * Sentry.init({\n * integrations: [Sentry.googleGenAiIntegration()],\n * });\n * ```\n *\n * ## Options\n *\n * - `recordInputs`: Whether to record prompt messages (default: respects `sendDefaultPii` client option)\n * - `recordOutputs`: Whether to record response text (default: respects `sendDefaultPii` client option)\n *\n * ### Default Behavior\n *\n * By default, the integration will:\n * - Record inputs and outputs ONLY if `sendDefaultPii` is set to `true` in your Sentry client options\n * - Otherwise, inputs and outputs are NOT recorded unless explicitly enabled\n *\n * @example\n * ```javascript\n * // Record inputs and outputs when sendDefaultPii is false\n * Sentry.init({\n * integrations: [\n * Sentry.googleGenAiIntegration({\n * recordInputs: true,\n * recordOutputs: true\n * })\n * ],\n * });\n *\n * // Never record inputs/outputs regardless of sendDefaultPii\n * Sentry.init({\n * sendDefaultPii: true,\n * integrations: [\n * Sentry.googleGenAiIntegration({\n * recordInputs: false,\n * recordOutputs: false\n * })\n * ],\n * });\n * ```\n *\n */\nexport const googleGenAIIntegration = defineIntegration(_googleGenAIIntegration);\n"],"names":[],"mappings":";;;;AAKO,MAAM,qBAAA,GAAwB,sBAAsB;AAC3D,EAAE,6BAA6B;AAC/B,EAAE,WAAW,IAAI,gCAAgC,CAAC,OAAO,CAAC;AAC1D;;AAEA,MAAM,uBAAA,IAA2B,CAAC,OAAO,GAAuB,EAAE,KAAK;AACvE,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,6BAA6B;AACvC,IAAI,SAAS,GAAG;AAChB,MAAM,qBAAqB,CAAC,OAAO,CAAC;AACpC,KAAK;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,sBAAA,GAAyB,iBAAiB,CAAC,uBAAuB;;;;"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { InstrumentationBase, InstrumentationNodeModuleDefinition, InstrumentationNodeModuleFile } from '@opentelemetry/instrumentation';
|
|
2
|
+
import { SDK_VERSION, replaceExports, getClient, instrumentGoogleGenAIClient } from '@sentry/core';
|
|
3
|
+
|
|
4
|
+
const supportedVersions = ['>=0.10.0 <2'];
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents the patched shape of the Google GenAI module export.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Sentry Google GenAI instrumentation using OpenTelemetry.
|
|
12
|
+
*/
|
|
13
|
+
class SentryGoogleGenAiInstrumentation extends InstrumentationBase {
|
|
14
|
+
constructor(config = {}) {
|
|
15
|
+
super('@sentry/instrumentation-google-genai', SDK_VERSION, config);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Initializes the instrumentation by defining the modules to be patched.
|
|
20
|
+
*/
|
|
21
|
+
init() {
|
|
22
|
+
const module = new InstrumentationNodeModuleDefinition(
|
|
23
|
+
'@google/genai',
|
|
24
|
+
supportedVersions,
|
|
25
|
+
exports => this._patch(exports),
|
|
26
|
+
exports => exports,
|
|
27
|
+
// In CJS, @google/genai re-exports from (dist/node/index.cjs) file.
|
|
28
|
+
// Patching only the root module sometimes misses the real implementation or
|
|
29
|
+
// gets overwritten when that file is loaded. We add a file-level patch so that
|
|
30
|
+
// _patch runs again on the concrete implementation
|
|
31
|
+
[
|
|
32
|
+
new InstrumentationNodeModuleFile(
|
|
33
|
+
'@google/genai/dist/node/index.cjs',
|
|
34
|
+
supportedVersions,
|
|
35
|
+
exports => this._patch(exports),
|
|
36
|
+
exports => exports,
|
|
37
|
+
),
|
|
38
|
+
],
|
|
39
|
+
);
|
|
40
|
+
return module;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Core patch logic applying instrumentation to the Google GenAI client constructor.
|
|
45
|
+
*/
|
|
46
|
+
_patch(exports) {
|
|
47
|
+
const Original = exports.GoogleGenAI;
|
|
48
|
+
const config = this.getConfig();
|
|
49
|
+
|
|
50
|
+
if (typeof Original !== 'function') {
|
|
51
|
+
return exports;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const WrappedGoogleGenAI = function ( ...args) {
|
|
55
|
+
const instance = Reflect.construct(Original, args);
|
|
56
|
+
const client = getClient();
|
|
57
|
+
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
|
|
58
|
+
|
|
59
|
+
const typedConfig = config ;
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
61
|
+
const recordInputs = typedConfig?.recordInputs ?? defaultPii;
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
63
|
+
const recordOutputs = typedConfig?.recordOutputs ?? defaultPii;
|
|
64
|
+
|
|
65
|
+
return instrumentGoogleGenAIClient(instance, {
|
|
66
|
+
recordInputs,
|
|
67
|
+
recordOutputs,
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Preserve static and prototype chains
|
|
72
|
+
Object.setPrototypeOf(WrappedGoogleGenAI, Original);
|
|
73
|
+
Object.setPrototypeOf(WrappedGoogleGenAI.prototype, Original.prototype);
|
|
74
|
+
|
|
75
|
+
for (const key of Object.getOwnPropertyNames(Original)) {
|
|
76
|
+
if (!['length', 'name', 'prototype'].includes(key)) {
|
|
77
|
+
const descriptor = Object.getOwnPropertyDescriptor(Original, key);
|
|
78
|
+
if (descriptor) {
|
|
79
|
+
Object.defineProperty(WrappedGoogleGenAI, key, descriptor);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Replace google genai exports with the wrapped constructor
|
|
85
|
+
replaceExports(exports, 'GoogleGenAI', WrappedGoogleGenAI);
|
|
86
|
+
|
|
87
|
+
return exports;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { SentryGoogleGenAiInstrumentation };
|
|
92
|
+
//# sourceMappingURL=instrumentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/google-genai/instrumentation.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport {\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n} from '@opentelemetry/instrumentation';\nimport type { GoogleGenAIClient, GoogleGenAIOptions } from '@sentry/core';\nimport { getClient, instrumentGoogleGenAIClient, replaceExports, SDK_VERSION } from '@sentry/core';\n\nconst supportedVersions = ['>=0.10.0 <2'];\n\n/**\n * Represents the patched shape of the Google GenAI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n GoogleGenAI?: unknown;\n}\n\ntype GoogleGenAIInstrumentationOptions = GoogleGenAIOptions & InstrumentationConfig;\n\n/**\n * Sentry Google GenAI instrumentation using OpenTelemetry.\n */\nexport class SentryGoogleGenAiInstrumentation extends InstrumentationBase<GoogleGenAIInstrumentationOptions> {\n public constructor(config: GoogleGenAIInstrumentationOptions = {}) {\n super('@sentry/instrumentation-google-genai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n '@google/genai',\n supportedVersions,\n exports => this._patch(exports),\n exports => exports,\n // In CJS, @google/genai re-exports from (dist/node/index.cjs) file.\n // Patching only the root module sometimes misses the real implementation or\n // gets overwritten when that file is loaded. We add a file-level patch so that\n // _patch runs again on the concrete implementation\n [\n new InstrumentationNodeModuleFile(\n '@google/genai/dist/node/index.cjs',\n supportedVersions,\n exports => this._patch(exports),\n exports => exports,\n ),\n ],\n );\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the Google GenAI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.GoogleGenAI;\n const config = this.getConfig();\n\n if (typeof Original !== 'function') {\n return exports;\n }\n\n const WrappedGoogleGenAI = function (this: unknown, ...args: unknown[]): GoogleGenAIClient {\n const instance = Reflect.construct(Original, args);\n const client = getClient();\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const typedConfig = config as GoogleGenAIInstrumentationOptions;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const recordInputs = typedConfig?.recordInputs ?? defaultPii;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const recordOutputs = typedConfig?.recordOutputs ?? defaultPii;\n\n return instrumentGoogleGenAIClient(instance, {\n recordInputs,\n recordOutputs,\n });\n };\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedGoogleGenAI, Original);\n Object.setPrototypeOf(WrappedGoogleGenAI.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedGoogleGenAI, key, descriptor);\n }\n }\n }\n\n // Replace google genai exports with the wrapped constructor\n replaceExports(exports, 'GoogleGenAI', WrappedGoogleGenAI);\n\n return exports;\n }\n}\n"],"names":[],"mappings":";;;AAUA,MAAM,iBAAA,GAAoB,CAAC,aAAa,CAAC;;AAEzC;AACA;AACA;;AAQA;AACA;AACA;AACO,MAAM,gCAAA,SAAyC,mBAAmB,CAAoC;AAC7G,GAAS,WAAW,CAAC,MAAM,GAAsC,EAAE,EAAE;AACrE,IAAI,KAAK,CAAC,sCAAsC,EAAE,WAAW,EAAE,MAAM,CAAC;AACtE;;AAEA;AACA;AACA;AACA,GAAS,IAAI,GAAoC;AACjD,IAAI,MAAM,MAAA,GAAS,IAAI,mCAAmC;AAC1D,MAAM,eAAe;AACrB,MAAM,iBAAiB;AACvB,MAAM,WAAW,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;AACrC,MAAM,OAAA,IAAW,OAAO;AACxB;AACA;AACA;AACA;AACA,MAAM;AACN,QAAQ,IAAI,6BAA6B;AACzC,UAAU,mCAAmC;AAC7C,UAAU,iBAAiB;AAC3B,UAAU,WAAW,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;AACzC,UAAU,OAAA,IAAW,OAAO;AAC5B,SAAS;AACT,OAAO;AACP,KAAK;AACL,IAAI,OAAO,MAAM;AACjB;;AAEA;AACA;AACA;AACA,GAAU,MAAM,CAAC,OAAO,EAAqD;AAC7E,IAAI,MAAM,QAAA,GAAW,OAAO,CAAC,WAAW;AACxC,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,SAAS,EAAE;;AAEnC,IAAI,IAAI,OAAO,QAAA,KAAa,UAAU,EAAE;AACxC,MAAM,OAAO,OAAO;AACpB;;AAEA,IAAI,MAAM,qBAAqB,WAAyB,GAAG,IAAI,EAAgC;AAC/F,MAAM,MAAM,QAAA,GAAW,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC;AACxD,MAAM,MAAM,MAAA,GAAS,SAAS,EAAE;AAChC,MAAM,MAAM,UAAA,GAAa,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,cAAc,CAAC;;AAErE,MAAM,MAAM,WAAA,GAAc,MAAA;AAC1B;AACA,MAAM,MAAM,YAAA,GAAe,WAAW,EAAE,YAAA,IAAgB,UAAU;AAClE;AACA,MAAM,MAAM,aAAA,GAAgB,WAAW,EAAE,aAAA,IAAiB,UAAU;;AAEpE,MAAM,OAAO,2BAA2B,CAAC,QAAQ,EAAE;AACnD,QAAQ,YAAY;AACpB,QAAQ,aAAa;AACrB,OAAO,CAAC;AACR,KAAK;;AAEL;AACA,IAAI,MAAM,CAAC,cAAc,CAAC,kBAAkB,EAAE,QAAQ,CAAC;AACvD,IAAI,MAAM,CAAC,cAAc,CAAC,kBAAkB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;;AAE3E,IAAI,KAAK,MAAM,GAAA,IAAO,MAAM,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE;AAC5D,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAC1D,QAAQ,MAAM,UAAA,GAAa,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,GAAG,CAAC;AACzE,QAAQ,IAAI,UAAU,EAAE;AACxB,UAAU,MAAM,CAAC,cAAc,CAAC,kBAAkB,EAAE,GAAG,EAAE,UAAU,CAAC;AACpE;AACA;AACA;;AAEA;AACA,IAAI,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,kBAAkB,CAAC;;AAE9D,IAAI,OAAO,OAAO;AAClB;AACA;;;;"}
|
|
@@ -41,11 +41,8 @@ function isErrorEvent(event) {
|
|
|
41
41
|
function sendErrorToSentry(errorData) {
|
|
42
42
|
captureException(errorData, {
|
|
43
43
|
mechanism: {
|
|
44
|
-
type: 'hapi',
|
|
44
|
+
type: 'auto.function.hapi',
|
|
45
45
|
handled: false,
|
|
46
|
-
data: {
|
|
47
|
-
function: 'hapiErrorPlugin',
|
|
48
|
-
},
|
|
49
46
|
},
|
|
50
47
|
});
|
|
51
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/hapi/index.ts"],"sourcesContent":["import { HapiInstrumentation } from '@opentelemetry/instrumentation-hapi';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getClient,\n getDefaultIsolationScope,\n getIsolationScope,\n SDK_VERSION,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n} from '@sentry/core';\nimport { ensureIsWrapped, generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../../debug-build';\nimport type { Request, RequestEvent, Server } from './types';\n\nconst INTEGRATION_NAME = 'Hapi';\n\nexport const instrumentHapi = generateInstrumentOnce(INTEGRATION_NAME, () => new HapiInstrumentation());\n\nconst _hapiIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentHapi();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Hapi](https://hapi.dev/).\n *\n * If you also want to capture errors, you need to call `setupHapiErrorHandler(server)` after you set up your server.\n *\n * For more information, see the [hapi documentation](https://docs.sentry.io/platforms/javascript/guides/hapi/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.hapiIntegration()],\n * })\n * ```\n */\nexport const hapiIntegration = defineIntegration(_hapiIntegration);\n\nfunction isErrorEvent(event: unknown): event is RequestEvent {\n return !!(event && typeof event === 'object' && 'error' in event && event.error);\n}\n\nfunction sendErrorToSentry(errorData: object): void {\n captureException(errorData, {\n mechanism: {\n type: 'hapi',\n handled: false,\n
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/hapi/index.ts"],"sourcesContent":["import { HapiInstrumentation } from '@opentelemetry/instrumentation-hapi';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getClient,\n getDefaultIsolationScope,\n getIsolationScope,\n SDK_VERSION,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n} from '@sentry/core';\nimport { ensureIsWrapped, generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../../debug-build';\nimport type { Request, RequestEvent, Server } from './types';\n\nconst INTEGRATION_NAME = 'Hapi';\n\nexport const instrumentHapi = generateInstrumentOnce(INTEGRATION_NAME, () => new HapiInstrumentation());\n\nconst _hapiIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentHapi();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Hapi](https://hapi.dev/).\n *\n * If you also want to capture errors, you need to call `setupHapiErrorHandler(server)` after you set up your server.\n *\n * For more information, see the [hapi documentation](https://docs.sentry.io/platforms/javascript/guides/hapi/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.hapiIntegration()],\n * })\n * ```\n */\nexport const hapiIntegration = defineIntegration(_hapiIntegration);\n\nfunction isErrorEvent(event: unknown): event is RequestEvent {\n return !!(event && typeof event === 'object' && 'error' in event && event.error);\n}\n\nfunction sendErrorToSentry(errorData: object): void {\n captureException(errorData, {\n mechanism: {\n type: 'auto.function.hapi',\n handled: false,\n },\n });\n}\n\nexport const hapiErrorPlugin = {\n name: 'SentryHapiErrorPlugin',\n version: SDK_VERSION,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n register: async function (serverArg: Record<any, any>) {\n const server = serverArg as unknown as Server;\n\n server.events.on({ name: 'request', channels: ['error'] }, (request: Request, event: RequestEvent) => {\n if (getIsolationScope() !== getDefaultIsolationScope()) {\n const route = request.route;\n if (route.path) {\n getIsolationScope().setTransactionName(`${route.method.toUpperCase()} ${route.path}`);\n }\n } else {\n DEBUG_BUILD &&\n debug.warn('Isolation scope is still the default isolation scope - skipping setting transactionName');\n }\n\n if (isErrorEvent(event)) {\n sendErrorToSentry(event.error);\n }\n });\n },\n};\n\n/**\n * Add a Hapi plugin to capture errors to Sentry.\n *\n * @param server The Hapi server to attach the error handler to\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const Hapi = require('@hapi/hapi');\n *\n * const init = async () => {\n * const server = Hapi.server();\n *\n * // all your routes here\n *\n * await Sentry.setupHapiErrorHandler(server);\n *\n * await server.start();\n * };\n * ```\n */\nexport async function setupHapiErrorHandler(server: Server): Promise<void> {\n await server.register(hapiErrorPlugin);\n\n // Sadly, middleware spans do not go through `requestHook`, so we handle those here\n // We register this hook in this method, because if we register it in the integration `setup`,\n // it would always run even for users that are not even using hapi\n const client = getClient();\n if (client) {\n client.on('spanStart', span => {\n addHapiSpanAttributes(span);\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n ensureIsWrapped(server.register, 'hapi');\n}\n\nfunction addHapiSpanAttributes(span: Span): void {\n const attributes = spanToJSON(span).data;\n\n // this is one of: router, plugin, server.ext\n const type = attributes['hapi.type'];\n\n // If this is already set, or we have no Hapi span, no need to process again...\n if (attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || !type) {\n return;\n }\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.hapi',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${type}.hapi`,\n });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import { instrumentExpress, expressIntegration } from './express.js';
|
|
|
6
6
|
import { instrumentFastify, instrumentFastifyV3, fastifyIntegration } from './fastify/index.js';
|
|
7
7
|
import { instrumentFirebase, firebaseIntegration } from './firebase/firebase.js';
|
|
8
8
|
import { instrumentGenericPool, genericPoolIntegration } from './genericPool.js';
|
|
9
|
+
import { instrumentGoogleGenAI, googleGenAIIntegration } from './google-genai/index.js';
|
|
9
10
|
import { instrumentGraphql, graphqlIntegration } from './graphql.js';
|
|
10
11
|
import { instrumentHapi, hapiIntegration } from './hapi/index.js';
|
|
11
12
|
import { instrumentKafka, kafkaIntegration } from './kafka.js';
|
|
@@ -51,6 +52,7 @@ function getAutoPerformanceIntegrations() {
|
|
|
51
52
|
postgresJsIntegration(),
|
|
52
53
|
firebaseIntegration(),
|
|
53
54
|
anthropicAIIntegration(),
|
|
55
|
+
googleGenAIIntegration(),
|
|
54
56
|
];
|
|
55
57
|
}
|
|
56
58
|
|
|
@@ -86,6 +88,7 @@ function getOpenTelemetryInstrumentationToPreload() {
|
|
|
86
88
|
instrumentPostgresJs,
|
|
87
89
|
instrumentFirebase,
|
|
88
90
|
instrumentAnthropicAi,
|
|
91
|
+
instrumentGoogleGenAI,
|
|
89
92
|
];
|
|
90
93
|
}
|
|
91
94
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentOtelHttp, instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n vercelAIIntegration(),\n openAIIntegration(),\n postgresJsIntegration(),\n firebaseIntegration(),\n anthropicAIIntegration(),\n ];\n}\n\n/**\n * Get a list of methods to instrument OTEL, when preload instrumentation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => void) & { id: string })[] {\n return [\n instrumentSentryHttp,\n instrumentOtelHttp,\n instrumentExpress,\n instrumentConnect,\n instrumentFastify,\n instrumentFastifyV3,\n instrumentHapi,\n instrumentKafka,\n instrumentKoa,\n instrumentLruMemoizer,\n instrumentMongo,\n instrumentMongoose,\n instrumentMysql,\n instrumentMysql2,\n instrumentPostgres,\n instrumentHapi,\n instrumentGraphql,\n instrumentRedis,\n instrumentTedious,\n instrumentGenericPool,\n instrumentAmqplib,\n instrumentVercelAi,\n instrumentOpenAi,\n instrumentPostgresJs,\n instrumentFirebase,\n instrumentAnthropicAi,\n ];\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentOtelHttp, instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { googleGenAIIntegration, instrumentGoogleGenAI } from './google-genai';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n vercelAIIntegration(),\n openAIIntegration(),\n postgresJsIntegration(),\n firebaseIntegration(),\n anthropicAIIntegration(),\n googleGenAIIntegration(),\n ];\n}\n\n/**\n * Get a list of methods to instrument OTEL, when preload instrumentation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => void) & { id: string })[] {\n return [\n instrumentSentryHttp,\n instrumentOtelHttp,\n instrumentExpress,\n instrumentConnect,\n instrumentFastify,\n instrumentFastifyV3,\n instrumentHapi,\n instrumentKafka,\n instrumentKoa,\n instrumentLruMemoizer,\n instrumentMongo,\n instrumentMongoose,\n instrumentMysql,\n instrumentMysql2,\n instrumentPostgres,\n instrumentHapi,\n instrumentGraphql,\n instrumentRedis,\n instrumentTedious,\n instrumentGenericPool,\n instrumentAmqplib,\n instrumentVercelAi,\n instrumentOpenAi,\n instrumentPostgresJs,\n instrumentFirebase,\n instrumentAnthropicAi,\n instrumentGoogleGenAI,\n ];\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA;AACA;AACA;AACO,SAAS,8BAA8B,GAAkB;AAChE,EAAE,OAAO;AACT,IAAI,kBAAkB,EAAE;AACxB,IAAI,kBAAkB,EAAE;AACxB,IAAI,kBAAkB,EAAE;AACxB,IAAI,gBAAgB,EAAE;AACtB,IAAI,mBAAmB,EAAE;AACzB,IAAI,gBAAgB,EAAE;AACtB,IAAI,iBAAiB,EAAE;AACvB,IAAI,gBAAgB,EAAE;AACtB,IAAI,mBAAmB,EAAE;AACzB,IAAI,iBAAiB,EAAE;AACvB,IAAI,eAAe,EAAE;AACrB,IAAI,cAAc,EAAE;AACpB,IAAI,kBAAkB,EAAE;AACxB,IAAI,kBAAkB,EAAE;AACxB,IAAI,sBAAsB,EAAE;AAC5B,IAAI,gBAAgB,EAAE;AACtB,IAAI,kBAAkB,EAAE;AACxB,IAAI,sBAAsB,EAAE;AAC5B,IAAI,mBAAmB,EAAE;AACzB,IAAI,iBAAiB,EAAE;AACvB,IAAI,qBAAqB,EAAE;AAC3B,IAAI,mBAAmB,EAAE;AACzB,IAAI,sBAAsB,EAAE;AAC5B,IAAI,sBAAsB,EAAE;AAC5B,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACO,SAAS,wCAAwC,GAAmD;AAC3G,EAAE,OAAO;AACT,IAAI,oBAAoB;AACxB,IAAI,kBAAkB;AACtB,IAAI,iBAAiB;AACrB,IAAI,iBAAiB;AACrB,IAAI,iBAAiB;AACrB,IAAI,mBAAmB;AACvB,IAAI,cAAc;AAClB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,qBAAqB;AACzB,IAAI,eAAe;AACnB,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,gBAAgB;AACpB,IAAI,kBAAkB;AACtB,IAAI,cAAc;AAClB,IAAI,iBAAiB;AACrB,IAAI,eAAe;AACnB,IAAI,iBAAiB;AACrB,IAAI,qBAAqB;AACzB,IAAI,iBAAiB;AACrB,IAAI,kBAAkB;AACtB,IAAI,gBAAgB;AACpB,IAAI,oBAAoB;AACxB,IAAI,kBAAkB;AACtB,IAAI,qBAAqB;AACzB,IAAI,qBAAqB;AACzB,GAAG;AACH;;;;"}
|
|
@@ -117,7 +117,12 @@ const setupKoaErrorHandler = (app) => {
|
|
|
117
117
|
try {
|
|
118
118
|
await next();
|
|
119
119
|
} catch (error) {
|
|
120
|
-
captureException(error
|
|
120
|
+
captureException(error, {
|
|
121
|
+
mechanism: {
|
|
122
|
+
handled: false,
|
|
123
|
+
type: 'auto.middleware.koa',
|
|
124
|
+
},
|
|
125
|
+
});
|
|
121
126
|
throw error;
|
|
122
127
|
}
|
|
123
128
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"koa.js","sources":["../../../../src/integrations/tracing/koa.ts"],"sourcesContent":["import type { KoaInstrumentationConfig, KoaLayerType } from '@opentelemetry/instrumentation-koa';\nimport { KoaInstrumentation } from '@opentelemetry/instrumentation-koa';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getDefaultIsolationScope,\n getIsolationScope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n} from '@sentry/core';\nimport { addOriginToSpan, ensureIsWrapped, generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../debug-build';\n\ninterface KoaOptions {\n /**\n * Ignore layers of specified types\n */\n ignoreLayersType?: Array<'middleware' | 'router'>;\n}\n\nconst INTEGRATION_NAME = 'Koa';\n\nexport const instrumentKoa = generateInstrumentOnce(\n INTEGRATION_NAME,\n KoaInstrumentation,\n (options: KoaOptions = {}) => {\n return {\n ignoreLayersType: options.ignoreLayersType as KoaLayerType[],\n requestHook(span, info) {\n addOriginToSpan(span, 'auto.http.otel.koa');\n\n const attributes = spanToJSON(span).data;\n\n // this is one of: middleware, router\n const type = attributes['koa.type'];\n if (type) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, `${type}.koa`);\n }\n\n // Also update the name\n const name = attributes['koa.name'];\n if (typeof name === 'string') {\n // Somehow, name is sometimes `''` for middleware spans\n // See: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2220\n span.updateName(name || '< unknown >');\n }\n\n if (getIsolationScope() === getDefaultIsolationScope()) {\n DEBUG_BUILD && debug.warn('Isolation scope is default isolation scope - skipping setting transactionName');\n return;\n }\n const route = attributes[ATTR_HTTP_ROUTE];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const method = info.context?.request?.method?.toUpperCase() || 'GET';\n if (route) {\n getIsolationScope().setTransactionName(`${method} ${route}`);\n }\n },\n } satisfies KoaInstrumentationConfig;\n },\n);\n\nconst _koaIntegration = ((options: KoaOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentKoa(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Koa](https://koajs.com/).\n *\n * If you also want to capture errors, you need to call `setupKoaErrorHandler(app)` after you set up your Koa server.\n *\n * For more information, see the [koa documentation](https://docs.sentry.io/platforms/javascript/guides/koa/).\n *\n * @param {KoaOptions} options Configuration options for the Koa integration.\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.koaIntegration()],\n * })\n * ```\n *\n * @example\n * ```javascript\n * // To ignore middleware spans\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [\n * Sentry.koaIntegration({\n * ignoreLayersType: ['middleware']\n * })\n * ],\n * })\n * ```\n */\nexport const koaIntegration = defineIntegration(_koaIntegration);\n\n/**\n * Add an Koa error handler to capture errors to Sentry.\n *\n * The error handler must be before any other middleware and after all controllers.\n *\n * @param app The Express instances\n * @param options {ExpressHandlerOptions} Configuration options for the handler\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const Koa = require(\"koa\");\n *\n * const app = new Koa();\n *\n * Sentry.setupKoaErrorHandler(app);\n *\n * // Add your routes, etc.\n *\n * app.listen(3000);\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const setupKoaErrorHandler = (app: { use: (arg0: (ctx: any, next: any) => Promise<void>) => void }): void => {\n app.use(async (ctx, next) => {\n try {\n await next();\n } catch (error) {\n captureException(error);\n throw error;\n }\n });\n\n ensureIsWrapped(app.use, 'koa');\n};\n"],"names":[],"mappings":";;;;;;AAuBA,MAAM,gBAAA,GAAmB,KAAK;;AAEvB,MAAM,aAAA,GAAgB,sBAAsB;AACnD,EAAE,gBAAgB;AAClB,EAAE,kBAAkB;AACpB,EAAE,CAAC,OAAO,GAAe,EAAE,KAAK;AAChC,IAAI,OAAO;AACX,MAAM,gBAAgB,EAAE,OAAO,CAAC,gBAAA;AAChC,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE;AAC9B,QAAQ,eAAe,CAAC,IAAI,EAAE,oBAAoB,CAAC;;AAEnD,QAAQ,MAAM,aAAa,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI;;AAEhD;AACA,QAAQ,MAAM,IAAA,GAAO,UAAU,CAAC,UAAU,CAAC;AAC3C,QAAQ,IAAI,IAAI,EAAE;AAClB,UAAU,IAAI,CAAC,YAAY,CAAC,4BAA4B,EAAE,CAAC,EAAA,IAAA,CAAA,IAAA,CAAA,CAAA;AACA;;AAEA;AACA,QAAA,MAAA,IAAA,GAAA,UAAA,CAAA,UAAA,CAAA;AACA,QAAA,IAAA,OAAA,IAAA,KAAA,QAAA,EAAA;AACA;AACA;AACA,UAAA,IAAA,CAAA,UAAA,CAAA,IAAA,IAAA,aAAA,CAAA;AACA;;AAEA,QAAA,IAAA,iBAAA,EAAA,KAAA,wBAAA,EAAA,EAAA;AACA,UAAA,WAAA,IAAA,KAAA,CAAA,IAAA,CAAA,+EAAA,CAAA;AACA,UAAA;AACA;AACA,QAAA,MAAA,KAAA,GAAA,UAAA,CAAA,eAAA,CAAA;AACA;AACA,QAAA,MAAA,MAAA,GAAA,IAAA,CAAA,OAAA,EAAA,OAAA,EAAA,MAAA,EAAA,WAAA,EAAA,IAAA,KAAA;AACA,QAAA,IAAA,KAAA,EAAA;AACA,UAAA,iBAAA,EAAA,CAAA,kBAAA,CAAA,CAAA,EAAA,MAAA,CAAA,CAAA,EAAA,KAAA,CAAA,CAAA,CAAA;AACA;AACA,OAAA;AACA,KAAA;AACA,GAAA;AACA;;AAEA,MAAA,eAAA,IAAA,CAAA,OAAA,GAAA,EAAA,KAAA;AACA,EAAA,OAAA;AACA,IAAA,IAAA,EAAA,gBAAA;AACA,IAAA,SAAA,GAAA;AACA,MAAA,aAAA,CAAA,OAAA,CAAA;AACA,KAAA;AACA,GAAA;AACA,CAAA,CAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA,cAAA,GAAA,iBAAA,CAAA,eAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA,oBAAA,GAAA,CAAA,GAAA,KAAA;AACA,EAAA,GAAA,CAAA,GAAA,CAAA,OAAA,GAAA,EAAA,IAAA,KAAA;AACA,IAAA,IAAA;AACA,MAAA,MAAA,IAAA,EAAA;AACA,KAAA,CAAA,OAAA,KAAA,EAAA;AACA,MAAA,gBAAA,CAAA,KAAA,CAAA;AACA,MAAA,MAAA,KAAA;AACA;AACA,GAAA,CAAA;;AAEA,EAAA,eAAA,CAAA,GAAA,CAAA,GAAA,EAAA,KAAA,CAAA;AACA;;;;"}
|
|
1
|
+
{"version":3,"file":"koa.js","sources":["../../../../src/integrations/tracing/koa.ts"],"sourcesContent":["import type { KoaInstrumentationConfig, KoaLayerType } from '@opentelemetry/instrumentation-koa';\nimport { KoaInstrumentation } from '@opentelemetry/instrumentation-koa';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n captureException,\n debug,\n defineIntegration,\n getDefaultIsolationScope,\n getIsolationScope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n} from '@sentry/core';\nimport { addOriginToSpan, ensureIsWrapped, generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../debug-build';\n\ninterface KoaOptions {\n /**\n * Ignore layers of specified types\n */\n ignoreLayersType?: Array<'middleware' | 'router'>;\n}\n\nconst INTEGRATION_NAME = 'Koa';\n\nexport const instrumentKoa = generateInstrumentOnce(\n INTEGRATION_NAME,\n KoaInstrumentation,\n (options: KoaOptions = {}) => {\n return {\n ignoreLayersType: options.ignoreLayersType as KoaLayerType[],\n requestHook(span, info) {\n addOriginToSpan(span, 'auto.http.otel.koa');\n\n const attributes = spanToJSON(span).data;\n\n // this is one of: middleware, router\n const type = attributes['koa.type'];\n if (type) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, `${type}.koa`);\n }\n\n // Also update the name\n const name = attributes['koa.name'];\n if (typeof name === 'string') {\n // Somehow, name is sometimes `''` for middleware spans\n // See: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2220\n span.updateName(name || '< unknown >');\n }\n\n if (getIsolationScope() === getDefaultIsolationScope()) {\n DEBUG_BUILD && debug.warn('Isolation scope is default isolation scope - skipping setting transactionName');\n return;\n }\n const route = attributes[ATTR_HTTP_ROUTE];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const method = info.context?.request?.method?.toUpperCase() || 'GET';\n if (route) {\n getIsolationScope().setTransactionName(`${method} ${route}`);\n }\n },\n } satisfies KoaInstrumentationConfig;\n },\n);\n\nconst _koaIntegration = ((options: KoaOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentKoa(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for [Koa](https://koajs.com/).\n *\n * If you also want to capture errors, you need to call `setupKoaErrorHandler(app)` after you set up your Koa server.\n *\n * For more information, see the [koa documentation](https://docs.sentry.io/platforms/javascript/guides/koa/).\n *\n * @param {KoaOptions} options Configuration options for the Koa integration.\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.koaIntegration()],\n * })\n * ```\n *\n * @example\n * ```javascript\n * // To ignore middleware spans\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [\n * Sentry.koaIntegration({\n * ignoreLayersType: ['middleware']\n * })\n * ],\n * })\n * ```\n */\nexport const koaIntegration = defineIntegration(_koaIntegration);\n\n/**\n * Add an Koa error handler to capture errors to Sentry.\n *\n * The error handler must be before any other middleware and after all controllers.\n *\n * @param app The Express instances\n * @param options {ExpressHandlerOptions} Configuration options for the handler\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n * const Koa = require(\"koa\");\n *\n * const app = new Koa();\n *\n * Sentry.setupKoaErrorHandler(app);\n *\n * // Add your routes, etc.\n *\n * app.listen(3000);\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const setupKoaErrorHandler = (app: { use: (arg0: (ctx: any, next: any) => Promise<void>) => void }): void => {\n app.use(async (ctx, next) => {\n try {\n await next();\n } catch (error) {\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.middleware.koa',\n },\n });\n throw error;\n }\n });\n\n ensureIsWrapped(app.use, 'koa');\n};\n"],"names":[],"mappings":";;;;;;AAuBA,MAAM,gBAAA,GAAmB,KAAK;;AAEvB,MAAM,aAAA,GAAgB,sBAAsB;AACnD,EAAE,gBAAgB;AAClB,EAAE,kBAAkB;AACpB,EAAE,CAAC,OAAO,GAAe,EAAE,KAAK;AAChC,IAAI,OAAO;AACX,MAAM,gBAAgB,EAAE,OAAO,CAAC,gBAAA;AAChC,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE;AAC9B,QAAQ,eAAe,CAAC,IAAI,EAAE,oBAAoB,CAAC;;AAEnD,QAAQ,MAAM,aAAa,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI;;AAEhD;AACA,QAAQ,MAAM,IAAA,GAAO,UAAU,CAAC,UAAU,CAAC;AAC3C,QAAQ,IAAI,IAAI,EAAE;AAClB,UAAU,IAAI,CAAC,YAAY,CAAC,4BAA4B,EAAE,CAAC,EAAA,IAAA,CAAA,IAAA,CAAA,CAAA;AACA;;AAEA;AACA,QAAA,MAAA,IAAA,GAAA,UAAA,CAAA,UAAA,CAAA;AACA,QAAA,IAAA,OAAA,IAAA,KAAA,QAAA,EAAA;AACA;AACA;AACA,UAAA,IAAA,CAAA,UAAA,CAAA,IAAA,IAAA,aAAA,CAAA;AACA;;AAEA,QAAA,IAAA,iBAAA,EAAA,KAAA,wBAAA,EAAA,EAAA;AACA,UAAA,WAAA,IAAA,KAAA,CAAA,IAAA,CAAA,+EAAA,CAAA;AACA,UAAA;AACA;AACA,QAAA,MAAA,KAAA,GAAA,UAAA,CAAA,eAAA,CAAA;AACA;AACA,QAAA,MAAA,MAAA,GAAA,IAAA,CAAA,OAAA,EAAA,OAAA,EAAA,MAAA,EAAA,WAAA,EAAA,IAAA,KAAA;AACA,QAAA,IAAA,KAAA,EAAA;AACA,UAAA,iBAAA,EAAA,CAAA,kBAAA,CAAA,CAAA,EAAA,MAAA,CAAA,CAAA,EAAA,KAAA,CAAA,CAAA,CAAA;AACA;AACA,OAAA;AACA,KAAA;AACA,GAAA;AACA;;AAEA,MAAA,eAAA,IAAA,CAAA,OAAA,GAAA,EAAA,KAAA;AACA,EAAA,OAAA;AACA,IAAA,IAAA,EAAA,gBAAA;AACA,IAAA,SAAA,GAAA;AACA,MAAA,aAAA,CAAA,OAAA,CAAA;AACA,KAAA;AACA,GAAA;AACA,CAAA,CAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA,cAAA,GAAA,iBAAA,CAAA,eAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA,oBAAA,GAAA,CAAA,GAAA,KAAA;AACA,EAAA,GAAA,CAAA,GAAA,CAAA,OAAA,GAAA,EAAA,IAAA,KAAA;AACA,IAAA,IAAA;AACA,MAAA,MAAA,IAAA,EAAA;AACA,KAAA,CAAA,OAAA,KAAA,EAAA;AACA,MAAA,gBAAA,CAAA,KAAA,EAAA;AACA,QAAA,SAAA,EAAA;AACA,UAAA,OAAA,EAAA,KAAA;AACA,UAAA,IAAA,EAAA,qBAAA;AACA,SAAA;AACA,OAAA,CAAA;AACA,MAAA,MAAA,KAAA;AACA;AACA,GAAA,CAAA;;AAEA,EAAA,eAAA,CAAA,GAAA,CAAA,GAAA,EAAA,KAAA,CAAA;AACA;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
|
|
2
|
-
import { SDK_VERSION,
|
|
2
|
+
import { SDK_VERSION, getClient, OPENAI_INTEGRATION_NAME, instrumentOpenAiClient } from '@sentry/core';
|
|
3
3
|
|
|
4
4
|
const supportedVersions = ['>=4.0.0 <6'];
|
|
5
5
|
|
|
@@ -39,10 +39,10 @@ class SentryOpenAiInstrumentation extends InstrumentationBase {
|
|
|
39
39
|
|
|
40
40
|
const WrappedOpenAI = function ( ...args) {
|
|
41
41
|
const instance = Reflect.construct(Original, args);
|
|
42
|
-
const
|
|
43
|
-
const integration =
|
|
42
|
+
const client = getClient();
|
|
43
|
+
const integration = client?.getIntegrationByName(OPENAI_INTEGRATION_NAME);
|
|
44
44
|
const integrationOpts = integration?.options;
|
|
45
|
-
const defaultPii = Boolean(
|
|
45
|
+
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
|
|
46
46
|
|
|
47
47
|
const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);
|
|
48
48
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/openai/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n} from '@opentelemetry/instrumentation';\nimport type { Integration, OpenAiClient, OpenAiOptions } from '@sentry/core';\nimport {
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sources":["../../../../../src/integrations/tracing/openai/instrumentation.ts"],"sourcesContent":["import {\n type InstrumentationConfig,\n type InstrumentationModuleDefinition,\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n} from '@opentelemetry/instrumentation';\nimport type { Integration, OpenAiClient, OpenAiOptions } from '@sentry/core';\nimport { getClient, instrumentOpenAiClient, OPENAI_INTEGRATION_NAME, SDK_VERSION } from '@sentry/core';\n\nconst supportedVersions = ['>=4.0.0 <6'];\n\nexport interface OpenAiIntegration extends Integration {\n options: OpenAiOptions;\n}\n\n/**\n * Represents the patched shape of the OpenAI module export.\n */\ninterface PatchedModuleExports {\n [key: string]: unknown;\n OpenAI: abstract new (...args: unknown[]) => OpenAiClient;\n}\n\n/**\n * Determines telemetry recording settings.\n */\nfunction determineRecordingSettings(\n integrationOptions: OpenAiOptions | undefined,\n defaultEnabled: boolean,\n): { recordInputs: boolean; recordOutputs: boolean } {\n const recordInputs = integrationOptions?.recordInputs ?? defaultEnabled;\n const recordOutputs = integrationOptions?.recordOutputs ?? defaultEnabled;\n return { recordInputs, recordOutputs };\n}\n\n/**\n * Sentry OpenAI instrumentation using OpenTelemetry.\n */\nexport class SentryOpenAiInstrumentation extends InstrumentationBase<InstrumentationConfig> {\n public constructor(config: InstrumentationConfig = {}) {\n super('@sentry/instrumentation-openai', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the modules to be patched.\n */\n public init(): InstrumentationModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition('openai', supportedVersions, this._patch.bind(this));\n return module;\n }\n\n /**\n * Core patch logic applying instrumentation to the OpenAI client constructor.\n */\n private _patch(exports: PatchedModuleExports): PatchedModuleExports | void {\n const Original = exports.OpenAI;\n\n const WrappedOpenAI = function (this: unknown, ...args: unknown[]) {\n const instance = Reflect.construct(Original, args);\n const client = getClient();\n const integration = client?.getIntegrationByName<OpenAiIntegration>(OPENAI_INTEGRATION_NAME);\n const integrationOpts = integration?.options;\n const defaultPii = Boolean(client?.getOptions().sendDefaultPii);\n\n const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);\n\n return instrumentOpenAiClient(instance as OpenAiClient, {\n recordInputs,\n recordOutputs,\n });\n } as unknown as abstract new (...args: unknown[]) => OpenAiClient;\n\n // Preserve static and prototype chains\n Object.setPrototypeOf(WrappedOpenAI, Original);\n Object.setPrototypeOf(WrappedOpenAI.prototype, Original.prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedOpenAI, key, descriptor);\n }\n }\n }\n\n // Constructor replacement - handle read-only properties\n // The OpenAI property might have only a getter, so use defineProperty\n try {\n exports.OpenAI = WrappedOpenAI;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'OpenAI', {\n value: WrappedOpenAI,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n\n // Wrap the default export if it points to the original constructor\n // Constructor replacement - handle read-only properties\n // The OpenAI property might have only a getter, so use defineProperty\n if (exports.default === Original) {\n try {\n exports.default = WrappedOpenAI;\n } catch (error) {\n // If direct assignment fails, override the property descriptor\n Object.defineProperty(exports, 'default', {\n value: WrappedOpenAI,\n writable: true,\n configurable: true,\n enumerable: true,\n });\n }\n }\n return exports;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { trace, TraceFlags, context, SpanKind } from '@opentelemetry/api';
|
|
1
2
|
import { PrismaInstrumentation } from '@prisma/instrumentation';
|
|
2
3
|
import { defineIntegration, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, consoleSandbox } from '@sentry/core';
|
|
3
4
|
import { generateInstrumentOnce } from '@sentry/node-core';
|
|
@@ -30,38 +31,104 @@ class SentryPrismaInteropInstrumentation extends PrismaInstrumentation {
|
|
|
30
31
|
|
|
31
32
|
// The PrismaIntegration (super class) defines a global variable `global["PRISMA_INSTRUMENTATION"]` when `enable()` is called. This global variable holds a "TracingHelper" which Prisma uses internally to create tracing data. It's their way of not depending on OTEL with their main package. The sucky thing is, prisma broke the interface of the tracing helper with the v6 major update. This means that if you use Prisma 5 with the v6 instrumentation (or vice versa) Prisma just blows up, because tries to call methods on the helper that no longer exist.
|
|
32
33
|
// Because we actually want to use the v6 instrumentation and not blow up in Prisma 5 user's faces, what we're doing here is backfilling the v5 method (`createEngineSpan`) with a noop so that no longer crashes when it attempts to call that function.
|
|
33
|
-
// We still won't fully emit all the spans, but this could potentially be implemented in the future.
|
|
34
34
|
const prismaTracingHelper = getPrismaTracingHelper();
|
|
35
35
|
|
|
36
|
-
let emittedWarning = false;
|
|
37
|
-
|
|
38
36
|
if (isPrismaV6TracingHelper(prismaTracingHelper)) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
// Inspired & adjusted from https://github.com/prisma/prisma/tree/5.22.0/packages/instrumentation
|
|
38
|
+
(prismaTracingHelper ).createEngineSpan = (
|
|
39
|
+
engineSpanEvent,
|
|
40
|
+
) => {
|
|
41
|
+
const tracer = trace.getTracer('prismaV5Compatibility') ;
|
|
42
|
+
|
|
43
|
+
// Prisma v5 relies on being able to create spans with a specific span & trace ID
|
|
44
|
+
// this is no longer possible in OTEL v2, there is no public API to do this anymore
|
|
45
|
+
// So in order to kind of hack this possibility, we rely on the internal `_idGenerator` property
|
|
46
|
+
// This is used to generate the random IDs, and we overwrite this temporarily to generate static IDs
|
|
47
|
+
// This is flawed and may not work, e.g. if the code is bundled and the private property is renamed
|
|
48
|
+
// in such cases, these spans will not be captured and some Prisma spans will be missing
|
|
49
|
+
const initialIdGenerator = tracer._idGenerator;
|
|
50
|
+
|
|
51
|
+
if (!initialIdGenerator) {
|
|
52
|
+
consoleSandbox(() => {
|
|
43
53
|
// eslint-disable-next-line no-console
|
|
44
54
|
console.warn(
|
|
45
|
-
'[Sentry]
|
|
55
|
+
'[Sentry] Could not find _idGenerator on tracer, skipping Prisma v5 compatibility - some Prisma spans may be missing!',
|
|
46
56
|
);
|
|
47
|
-
}
|
|
48
|
-
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
engineSpanEvent.spans.forEach(engineSpan => {
|
|
64
|
+
const kind = engineSpanKindToOTELSpanKind(engineSpan.kind);
|
|
65
|
+
|
|
66
|
+
const parentSpanId = engineSpan.parent_span_id;
|
|
67
|
+
const spanId = engineSpan.span_id;
|
|
68
|
+
const traceId = engineSpan.trace_id;
|
|
69
|
+
|
|
70
|
+
const links = engineSpan.links?.map(link => {
|
|
71
|
+
return {
|
|
72
|
+
context: {
|
|
73
|
+
traceId: link.trace_id,
|
|
74
|
+
spanId: link.span_id,
|
|
75
|
+
traceFlags: TraceFlags.SAMPLED,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const ctx = trace.setSpanContext(context.active(), {
|
|
81
|
+
traceId,
|
|
82
|
+
spanId: parentSpanId,
|
|
83
|
+
traceFlags: TraceFlags.SAMPLED,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
context.with(ctx, () => {
|
|
87
|
+
const temporaryIdGenerator = {
|
|
88
|
+
generateTraceId: () => {
|
|
89
|
+
return traceId;
|
|
90
|
+
},
|
|
91
|
+
generateSpanId: () => {
|
|
92
|
+
return spanId;
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
tracer._idGenerator = temporaryIdGenerator;
|
|
97
|
+
|
|
98
|
+
const span = tracer.startSpan(engineSpan.name, {
|
|
99
|
+
kind,
|
|
100
|
+
links,
|
|
101
|
+
startTime: engineSpan.start_time,
|
|
102
|
+
attributes: engineSpan.attributes,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
span.end(engineSpan.end_time);
|
|
106
|
+
|
|
107
|
+
tracer._idGenerator = initialIdGenerator;
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
} finally {
|
|
111
|
+
// Ensure we always restore this at the end, even if something errors
|
|
112
|
+
tracer._idGenerator = initialIdGenerator;
|
|
113
|
+
}
|
|
49
114
|
};
|
|
50
115
|
}
|
|
51
116
|
}
|
|
52
117
|
}
|
|
53
118
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
119
|
+
function engineSpanKindToOTELSpanKind(engineSpanKind) {
|
|
120
|
+
switch (engineSpanKind) {
|
|
121
|
+
case 'client':
|
|
122
|
+
return SpanKind.CLIENT;
|
|
123
|
+
case 'internal':
|
|
124
|
+
default: // Other span kinds aren't currently supported
|
|
125
|
+
return SpanKind.INTERNAL;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
61
128
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
);
|
|
129
|
+
const instrumentPrisma = generateInstrumentOnce(INTEGRATION_NAME, _options => {
|
|
130
|
+
return new SentryPrismaInteropInstrumentation();
|
|
131
|
+
});
|
|
65
132
|
|
|
66
133
|
/**
|
|
67
134
|
* Adds Sentry tracing instrumentation for the [prisma](https://www.npmjs.com/package/prisma) library.
|
|
@@ -95,45 +162,39 @@ const instrumentPrisma = generateInstrumentOnce(
|
|
|
95
162
|
* }
|
|
96
163
|
* ```
|
|
97
164
|
*/
|
|
98
|
-
const prismaIntegration = defineIntegration(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
165
|
+
const prismaIntegration = defineIntegration((_options) => {
|
|
166
|
+
return {
|
|
167
|
+
name: INTEGRATION_NAME,
|
|
168
|
+
setupOnce() {
|
|
169
|
+
instrumentPrisma();
|
|
170
|
+
},
|
|
171
|
+
setup(client) {
|
|
172
|
+
// If no tracing helper exists, we skip any work here
|
|
173
|
+
// this means that prisma is not being used
|
|
174
|
+
if (!getPrismaTracingHelper()) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
client.on('spanStart', span => {
|
|
179
|
+
const spanJSON = spanToJSON(span);
|
|
180
|
+
if (spanJSON.description?.startsWith('prisma:')) {
|
|
181
|
+
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.prisma');
|
|
182
|
+
}
|
|
102
183
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
setupOnce() {
|
|
107
|
-
instrumentPrisma({ prismaInstrumentation });
|
|
108
|
-
},
|
|
109
|
-
setup(client) {
|
|
110
|
-
// If no tracing helper exists, we skip any work here
|
|
111
|
-
// this means that prisma is not being used
|
|
112
|
-
if (!getPrismaTracingHelper()) {
|
|
113
|
-
return;
|
|
184
|
+
// Make sure we use the query text as the span name, for ex. SELECT * FROM "User" WHERE "id" = $1
|
|
185
|
+
if (spanJSON.description === 'prisma:engine:db_query' && spanJSON.data['db.query.text']) {
|
|
186
|
+
span.updateName(spanJSON.data['db.query.text'] );
|
|
114
187
|
}
|
|
115
188
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// In Prisma v5.22+, the `db.system` attribute is automatically set
|
|
128
|
-
// On older versions, this is missing, so we add it here
|
|
129
|
-
if (spanJSON.description === 'prisma:engine:db_query' && !spanJSON.data['db.system']) {
|
|
130
|
-
span.setAttribute('db.system', 'prisma');
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
},
|
|
136
|
-
);
|
|
189
|
+
// In Prisma v5.22+, the `db.system` attribute is automatically set
|
|
190
|
+
// On older versions, this is missing, so we add it here
|
|
191
|
+
if (spanJSON.description === 'prisma:engine:db_query' && !spanJSON.data['db.system']) {
|
|
192
|
+
span.setAttribute('db.system', 'prisma');
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
});
|
|
137
198
|
|
|
138
199
|
export { instrumentPrisma, prismaIntegration };
|
|
139
200
|
//# sourceMappingURL=prisma.js.map
|