@sentry/node 9.38.0 → 9.40.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 +9 -7
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integrations/http/index.js +4 -1
- package/build/cjs/integrations/http/index.js.map +1 -1
- package/build/cjs/integrations/tracing/express-v5/utils.js +1 -1
- package/build/cjs/integrations/tracing/express-v5/utils.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 +2 -2
- package/build/cjs/integrations/tracing/fastify/index.js.map +1 -1
- package/build/cjs/integrations/tracing/hapi/index.js +1 -1
- 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 +1 -1
- package/build/cjs/integrations/tracing/koa.js.map +1 -1
- package/build/cjs/integrations/tracing/openai/index.js +79 -0
- package/build/cjs/integrations/tracing/openai/index.js.map +1 -0
- package/build/cjs/integrations/tracing/openai/instrumentation.js +81 -0
- package/build/cjs/integrations/tracing/openai/instrumentation.js.map +1 -0
- package/build/cjs/integrations/tracing/postgresjs.js +1 -1
- package/build/cjs/integrations/tracing/postgresjs.js.map +1 -1
- package/build/cjs/sdk/index.js +2 -0
- package/build/cjs/sdk/index.js.map +1 -1
- package/build/cjs/sdk/initOtel.js +5 -5
- package/build/cjs/sdk/initOtel.js.map +1 -1
- package/build/cjs/utils/redisCache.js +2 -2
- package/build/cjs/utils/redisCache.js.map +1 -1
- package/build/esm/index.js +1 -0
- package/build/esm/index.js.map +1 -1
- package/build/esm/integrations/http/index.js +4 -1
- package/build/esm/integrations/http/index.js.map +1 -1
- package/build/esm/integrations/tracing/express-v5/utils.js +1 -1
- package/build/esm/integrations/tracing/express-v5/utils.js.map +1 -1
- package/build/esm/integrations/tracing/express.js +2 -2
- package/build/esm/integrations/tracing/express.js.map +1 -1
- package/build/esm/integrations/tracing/fastify/index.js +3 -3
- package/build/esm/integrations/tracing/fastify/index.js.map +1 -1
- package/build/esm/integrations/tracing/hapi/index.js +2 -2
- 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 +2 -2
- package/build/esm/integrations/tracing/koa.js.map +1 -1
- package/build/esm/integrations/tracing/openai/index.js +76 -0
- package/build/esm/integrations/tracing/openai/index.js.map +1 -0
- package/build/esm/integrations/tracing/openai/instrumentation.js +79 -0
- package/build/esm/integrations/tracing/openai/instrumentation.js.map +1 -0
- package/build/esm/integrations/tracing/postgresjs.js +2 -2
- package/build/esm/integrations/tracing/postgresjs.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/sdk/index.js +3 -1
- package/build/esm/sdk/index.js.map +1 -1
- package/build/esm/sdk/initOtel.js +9 -9
- package/build/esm/sdk/initOtel.js.map +1 -1
- package/build/esm/utils/redisCache.js +2 -2
- package/build/esm/utils/redisCache.js.map +1 -1
- package/build/types/index.d.ts +1 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integrations/http/index.d.ts +1 -1
- package/build/types/integrations/http/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/index.d.ts.map +1 -1
- package/build/types/integrations/tracing/openai/index.d.ts +60 -0
- package/build/types/integrations/tracing/openai/index.d.ts.map +1 -0
- package/build/types/integrations/tracing/openai/instrumentation.d.ts +20 -0
- package/build/types/integrations/tracing/openai/instrumentation.d.ts.map +1 -0
- package/build/types/sdk/index.d.ts.map +1 -1
- package/build/types-ts3.8/index.d.ts +1 -0
- package/build/types-ts3.8/integrations/http/index.d.ts +1 -1
- package/build/types-ts3.8/integrations/tracing/openai/index.d.ts +60 -0
- package/build/types-ts3.8/integrations/tracing/openai/instrumentation.d.ts +20 -0
- package/package.json +4 -4
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const instrumentation = require('@opentelemetry/instrumentation');
|
|
4
|
+
const core = require('@sentry/core');
|
|
5
|
+
|
|
6
|
+
const supportedVersions = ['>=4.0.0 <6'];
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Determines telemetry recording settings.
|
|
10
|
+
*/
|
|
11
|
+
function determineRecordingSettings(
|
|
12
|
+
integrationOptions,
|
|
13
|
+
defaultEnabled,
|
|
14
|
+
) {
|
|
15
|
+
const recordInputs = integrationOptions?.recordInputs ?? defaultEnabled;
|
|
16
|
+
const recordOutputs = integrationOptions?.recordOutputs ?? defaultEnabled;
|
|
17
|
+
return { recordInputs, recordOutputs };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Sentry OpenAI instrumentation using OpenTelemetry.
|
|
22
|
+
*/
|
|
23
|
+
class SentryOpenAiInstrumentation extends instrumentation.InstrumentationBase {
|
|
24
|
+
constructor(config = {}) {
|
|
25
|
+
super('@sentry/instrumentation-openai', core.SDK_VERSION, config);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Initializes the instrumentation by defining the modules to be patched.
|
|
30
|
+
*/
|
|
31
|
+
init() {
|
|
32
|
+
const module = new instrumentation.InstrumentationNodeModuleDefinition('openai', supportedVersions, this._patch.bind(this));
|
|
33
|
+
return module;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Core patch logic applying instrumentation to the OpenAI client constructor.
|
|
38
|
+
*/
|
|
39
|
+
_patch(exports) {
|
|
40
|
+
const Original = exports.OpenAI;
|
|
41
|
+
|
|
42
|
+
const WrappedOpenAI = function ( ...args) {
|
|
43
|
+
const instance = Reflect.construct(Original, args);
|
|
44
|
+
const scopeClient = core.getCurrentScope().getClient();
|
|
45
|
+
const integration = scopeClient?.getIntegrationByName(core.OPENAI_INTEGRATION_NAME);
|
|
46
|
+
const integrationOpts = integration?.options;
|
|
47
|
+
const defaultPii = Boolean(scopeClient?.getOptions().sendDefaultPii);
|
|
48
|
+
|
|
49
|
+
const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);
|
|
50
|
+
|
|
51
|
+
return core.instrumentOpenAiClient(instance , {
|
|
52
|
+
recordInputs,
|
|
53
|
+
recordOutputs,
|
|
54
|
+
});
|
|
55
|
+
} ;
|
|
56
|
+
|
|
57
|
+
// Preserve static and prototype chains
|
|
58
|
+
Object.setPrototypeOf(WrappedOpenAI, Original);
|
|
59
|
+
Object.setPrototypeOf(WrappedOpenAI.prototype, Original.prototype);
|
|
60
|
+
|
|
61
|
+
for (const key of Object.getOwnPropertyNames(Original)) {
|
|
62
|
+
if (!['length', 'name', 'prototype'].includes(key)) {
|
|
63
|
+
const descriptor = Object.getOwnPropertyDescriptor(Original, key);
|
|
64
|
+
if (descriptor) {
|
|
65
|
+
Object.defineProperty(WrappedOpenAI, key, descriptor);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const isESM = Object.prototype.toString.call(exports) === '[object Module]';
|
|
71
|
+
if (isESM) {
|
|
72
|
+
exports.OpenAI = WrappedOpenAI;
|
|
73
|
+
return exports;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return { ...exports, OpenAI: WrappedOpenAI };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
exports.SentryOpenAiInstrumentation = SentryOpenAiInstrumentation;
|
|
81
|
+
//# sourceMappingURL=instrumentation.js.map
|
|
@@ -0,0 +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 { getCurrentScope, 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 scopeClient = getCurrentScope().getClient();\n const integration = scopeClient?.getIntegrationByName<OpenAiIntegration>(OPENAI_INTEGRATION_NAME);\n const integrationOpts = integration?.options;\n const defaultPii = Boolean(scopeClient?.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 const isESM = Object.prototype.toString.call(exports) === '[object Module]';\n if (isESM) {\n exports.OpenAI = WrappedOpenAI;\n return exports;\n }\n\n return { ...exports, OpenAI: WrappedOpenAI };\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","getCurrentScope","OPENAI_INTEGRATION_NAME","instrumentOpenAiClient"],"mappings":";;;;;AASA,MAAM,iBAAA,GAAoB,CAAC,YAAY,CAAC;;AAcxC;AACA;AACA;AACA,SAAS,0BAA0B;AACnC,EAAE,kBAAkB;AACpB,EAAE,cAAc;AAChB,EAAqD;AACrD,EAAE,MAAM,YAAA,GAAe,kBAAkB,EAAE,YAAA,IAAgB,cAAc;AACzE,EAAE,MAAM,aAAA,GAAgB,kBAAkB,EAAE,aAAA,IAAiB,cAAc;AAC3E,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe;AACxC;;AAEA;AACA;AACA;AACO,MAAM,2BAAA,SAAoCA,mCAAmB,CAAwB;AAC5F,GAAS,WAAW,CAAC,MAAM,GAA0B,EAAE,EAAE;AACzD,IAAI,KAAK,CAAC,gCAAgC,EAAEC,gBAAW,EAAE,MAAM,CAAC;AAChE;;AAEA;AACA;AACA;AACA,GAAS,IAAI,GAAoC;AACjD,IAAI,MAAM,MAAA,GAAS,IAAIC,mDAAmC,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/G,IAAI,OAAO,MAAM;AACjB;;AAEA;AACA;AACA;AACA,GAAU,MAAM,CAAC,OAAO,EAAqD;AAC7E,IAAI,MAAM,QAAA,GAAW,OAAO,CAAC,MAAM;;AAEnC,IAAI,MAAM,gBAAgB,WAAyB,GAAG,IAAI,EAAa;AACvE,MAAM,MAAM,QAAA,GAAW,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC;AACxD,MAAM,MAAM,cAAcC,oBAAe,EAAE,CAAC,SAAS,EAAE;AACvD,MAAM,MAAM,cAAc,WAAW,EAAE,oBAAoB,CAAoBC,4BAAuB,CAAC;AACvG,MAAM,MAAM,eAAA,GAAkB,WAAW,EAAE,OAAO;AAClD,MAAM,MAAM,UAAA,GAAa,OAAO,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,cAAc,CAAC;;AAE1E,MAAM,MAAM,EAAE,YAAY,EAAE,aAAA,EAAc,GAAI,0BAA0B,CAAC,eAAe,EAAE,UAAU,CAAC;;AAErG,MAAM,OAAOC,2BAAsB,CAAC,QAAA,GAA0B;AAC9D,QAAQ,YAAY;AACpB,QAAQ,aAAa;AACrB,OAAO,CAAC;AACR,KAAI;;AAEJ;AACA,IAAI,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,QAAQ,CAAC;AAClD,IAAI,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;;AAEtE,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,aAAa,EAAE,GAAG,EAAE,UAAU,CAAC;AAC/D;AACA;AACA;;AAEA,IAAI,MAAM,KAAA,GAAQ,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAA,KAAM,iBAAiB;AAC/E,IAAI,IAAI,KAAK,EAAE;AACf,MAAM,OAAO,CAAC,MAAA,GAAS,aAAa;AACpC,MAAM,OAAO,OAAO;AACpB;;AAEA,IAAI,OAAO,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,eAAe;AAChD;AACA;;;;"}
|
|
@@ -162,7 +162,7 @@ class PostgresJsInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
162
162
|
() => requestHook(span, sanitizedSqlQuery, postgresConnectionContext),
|
|
163
163
|
error => {
|
|
164
164
|
if (error) {
|
|
165
|
-
core.
|
|
165
|
+
core.debug.error(`Error in requestHook for ${INTEGRATION_NAME} integration:`, error);
|
|
166
166
|
}
|
|
167
167
|
},
|
|
168
168
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgresjs.js","sources":["../../../../src/integrations/tracing/postgresjs.ts"],"sourcesContent":["// Instrumentation for https://github.com/porsager/postgres\nimport { context, trace } from '@opentelemetry/api';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n safeExecuteInTheMiddle,\n} from '@opentelemetry/instrumentation';\nimport {\n ATTR_DB_NAMESPACE,\n ATTR_DB_OPERATION_NAME,\n ATTR_DB_QUERY_TEXT,\n ATTR_DB_RESPONSE_STATUS_CODE,\n ATTR_DB_SYSTEM_NAME,\n ATTR_ERROR_TYPE,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n} from '@opentelemetry/semantic-conventions';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n defineIntegration,\n getCurrentScope,\n logger,\n SDK_VERSION,\n SPAN_STATUS_ERROR,\n startSpanManual,\n} from '@sentry/core';\nimport { addOriginToSpan, generateInstrumentOnce } from '@sentry/node-core';\n\nconst INTEGRATION_NAME = 'PostgresJs';\nconst SUPPORTED_VERSIONS = ['>=3.0.0 <4'];\n\ntype PostgresConnectionContext = {\n ATTR_DB_NAMESPACE?: string; // Database name\n ATTR_SERVER_ADDRESS?: string; // Hostname or IP address of the database server\n ATTR_SERVER_PORT?: string; // Port number of the database server\n};\n\ntype PostgresJsInstrumentationConfig = InstrumentationConfig & {\n /**\n * Whether to require a parent span for the instrumentation.\n * If set to true, the instrumentation will only create spans if there is a parent span\n * available in the current scope.\n * @default true\n */\n requireParentSpan?: boolean;\n /**\n * Hook to modify the span before it is started.\n * This can be used to set additional attributes or modify the span in any way.\n */\n requestHook?: (span: Span, sanitizedSqlQuery: string, postgresConnectionContext?: PostgresConnectionContext) => void;\n};\n\nexport const instrumentPostgresJs = generateInstrumentOnce(\n INTEGRATION_NAME,\n (options?: PostgresJsInstrumentationConfig) =>\n new PostgresJsInstrumentation({\n requireParentSpan: options?.requireParentSpan ?? true,\n requestHook: options?.requestHook,\n }),\n);\n\n/**\n * Instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n * This instrumentation captures postgresjs queries and their attributes,\n */\nexport class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsInstrumentationConfig> {\n public constructor(config: PostgresJsInstrumentationConfig) {\n super('sentry-postgres-js', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation.\n */\n public init(): InstrumentationNodeModuleDefinition[] {\n const instrumentationModule = new InstrumentationNodeModuleDefinition('postgres', SUPPORTED_VERSIONS);\n\n ['src', 'cf/src', 'cjs/src'].forEach(path => {\n instrumentationModule.files.push(\n new InstrumentationNodeModuleFile(\n `postgres/${path}/connection.js`,\n ['*'],\n this._patchConnection.bind(this),\n this._unwrap.bind(this),\n ),\n );\n\n instrumentationModule.files.push(\n new InstrumentationNodeModuleFile(\n `postgres/${path}/query.js`,\n SUPPORTED_VERSIONS,\n this._patchQuery.bind(this),\n this._unwrap.bind(this),\n ),\n );\n });\n\n return [instrumentationModule];\n }\n\n /**\n * Determines whether a span should be created based on the current context.\n * If `requireParentSpan` is set to true in the configuration, a span will\n * only be created if there is a parent span available.\n */\n private _shouldCreateSpans(): boolean {\n const config = this.getConfig();\n const hasParentSpan = trace.getSpan(context.active()) !== undefined;\n return hasParentSpan || !config.requireParentSpan;\n }\n\n /**\n * Patches the reject method of the Query class to set the span status and end it\n */\n private _patchReject(rejectTarget: any, span: Span): any {\n return new Proxy(rejectTarget, {\n apply: (\n rejectTarget,\n rejectThisArg,\n rejectArgs: {\n message?: string;\n code?: string;\n name?: string;\n }[],\n ) => {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n // This message is the error message from the rejectArgs, when available\n // e.g \"relation 'User' does not exist\"\n message: rejectArgs?.[0]?.message || 'unknown_error',\n });\n\n const result = Reflect.apply(rejectTarget, rejectThisArg, rejectArgs);\n\n // This status code is PG error code, e.g. '42P01' for \"relation does not exist\"\n // https://www.postgresql.org/docs/current/errcodes-appendix.html\n span.setAttribute(ATTR_DB_RESPONSE_STATUS_CODE, rejectArgs?.[0]?.code || 'Unknown error');\n // This is the error type, e.g. 'PostgresError' for a Postgres error\n span.setAttribute(ATTR_ERROR_TYPE, rejectArgs?.[0]?.name || 'Unknown error');\n\n span.end();\n return result;\n },\n });\n }\n\n /**\n * Patches the resolve method of the Query class to end the span when the query is resolved.\n */\n private _patchResolve(resolveTarget: any, span: Span): any {\n return new Proxy(resolveTarget, {\n apply: (resolveTarget, resolveThisArg, resolveArgs: [{ command?: string }]) => {\n const result = Reflect.apply(resolveTarget, resolveThisArg, resolveArgs);\n const sqlCommand = resolveArgs?.[0]?.command;\n\n if (sqlCommand) {\n // SQL command is only available when the query is resolved successfully\n span.setAttribute(ATTR_DB_OPERATION_NAME, sqlCommand);\n }\n span.end();\n return result;\n },\n });\n }\n\n /**\n * Patches the Query class to instrument the handle method.\n */\n private _patchQuery(moduleExports: {\n Query: {\n prototype: {\n handle: any;\n };\n };\n }): any {\n moduleExports.Query.prototype.handle = new Proxy(moduleExports.Query.prototype.handle, {\n apply: async (\n handleTarget,\n handleThisArg: {\n resolve: any;\n reject: any;\n strings?: string[];\n },\n handleArgs,\n ) => {\n if (!this._shouldCreateSpans()) {\n // If we don't need to create spans, just call the original method\n return Reflect.apply(handleTarget, handleThisArg, handleArgs);\n }\n\n const sanitizedSqlQuery = this._sanitizeSqlQuery(handleThisArg.strings?.[0]);\n\n return startSpanManual(\n {\n name: sanitizedSqlQuery || 'postgresjs.query',\n op: 'db',\n },\n (span: Span) => {\n const scope = getCurrentScope();\n const postgresConnectionContext = scope.getScopeData().contexts['postgresjsConnection'] as\n | PostgresConnectionContext\n | undefined;\n\n addOriginToSpan(span, 'auto.db.otel.postgres');\n\n const { requestHook } = this.getConfig();\n\n if (requestHook) {\n safeExecuteInTheMiddle(\n () => requestHook(span, sanitizedSqlQuery, postgresConnectionContext),\n error => {\n if (error) {\n logger.error(`Error in requestHook for ${INTEGRATION_NAME} integration:`, error);\n }\n },\n );\n }\n\n // ATTR_DB_NAMESPACE is used to indicate the database name and the schema name\n // It's only the database name as we don't have the schema information\n const databaseName = postgresConnectionContext?.ATTR_DB_NAMESPACE || '<unknown database>';\n const databaseHost = postgresConnectionContext?.ATTR_SERVER_ADDRESS || '<unknown host>';\n const databasePort = postgresConnectionContext?.ATTR_SERVER_PORT || '<unknown port>';\n\n span.setAttribute(ATTR_DB_SYSTEM_NAME, 'postgres');\n span.setAttribute(ATTR_DB_NAMESPACE, databaseName);\n span.setAttribute(ATTR_SERVER_ADDRESS, databaseHost);\n span.setAttribute(ATTR_SERVER_PORT, databasePort);\n span.setAttribute(ATTR_DB_QUERY_TEXT, sanitizedSqlQuery);\n\n handleThisArg.resolve = this._patchResolve(handleThisArg.resolve, span);\n handleThisArg.reject = this._patchReject(handleThisArg.reject, span);\n\n try {\n return Reflect.apply(handleTarget, handleThisArg, handleArgs);\n } catch (error) {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n });\n span.end();\n throw error; // Re-throw the error to propagate it\n }\n },\n );\n },\n });\n\n return moduleExports;\n }\n\n /**\n * Patches the Connection class to set the database, host, and port attributes\n * when a new connection is created.\n */\n private _patchConnection(Connection: any): any {\n return new Proxy(Connection, {\n apply: (connectionTarget, thisArg, connectionArgs: { database: string; host: string[]; port: number[] }[]) => {\n const databaseName = connectionArgs[0]?.database || '<unknown database>';\n const databaseHost = connectionArgs[0]?.host?.[0] || '<unknown host>';\n const databasePort = connectionArgs[0]?.port?.[0] || '<unknown port>';\n\n const scope = getCurrentScope();\n scope.setContext('postgresjsConnection', {\n ATTR_DB_NAMESPACE: databaseName,\n ATTR_SERVER_ADDRESS: databaseHost,\n ATTR_SERVER_PORT: databasePort,\n });\n\n return Reflect.apply(connectionTarget, thisArg, connectionArgs);\n },\n });\n }\n\n /**\n * Sanitize SQL query as per the OTEL semantic conventions\n * https://opentelemetry.io/docs/specs/semconv/database/database-spans/#sanitization-of-dbquerytext\n */\n private _sanitizeSqlQuery(sqlQuery: string | undefined): string {\n if (!sqlQuery) {\n return 'Unknown SQL Query';\n }\n\n return (\n sqlQuery\n .replace(/\\s+/g, ' ')\n .trim() // Remove extra spaces including newlines and trim\n .substring(0, 1024) // Truncate to 1024 characters\n .replace(/--.*?(\\r?\\n|$)/g, '') // Single line comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Multi-line comments\n .replace(/;\\s*$/, '') // Remove trailing semicolons\n .replace(/\\b\\d+\\b/g, '?') // Replace standalone numbers\n // Collapse whitespace to a single space\n .replace(/\\s+/g, ' ')\n // Collapse IN and in clauses\n // eg. IN (?, ?, ?, ?) to IN (?)\n .replace(/\\bIN\\b\\s*\\(\\s*\\?(?:\\s*,\\s*\\?)*\\s*\\)/g, 'IN (?)')\n );\n }\n}\n\nconst _postgresJsIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentPostgresJs();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n *\n * For more information, see the [`postgresIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/postgres/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.postgresJsIntegration()],\n * });\n * ```\n */\n\nexport const postgresJsIntegration = defineIntegration(_postgresJsIntegration);\n"],"names":["generateInstrumentOnce","InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","InstrumentationNodeModuleFile","trace","context","SPAN_STATUS_ERROR","ATTR_DB_RESPONSE_STATUS_CODE","ATTR_ERROR_TYPE","ATTR_DB_OPERATION_NAME","startSpanManual","getCurrentScope","addOriginToSpan","safeExecuteInTheMiddle","logger","ATTR_DB_SYSTEM_NAME","ATTR_DB_NAMESPACE","ATTR_SERVER_ADDRESS","ATTR_SERVER_PORT","ATTR_DB_QUERY_TEXT","defineIntegration"],"mappings":";;;;;;;;AAAA;;AA8BA,MAAM,gBAAA,GAAmB,YAAY;AACrC,MAAM,kBAAA,GAAqB,CAAC,YAAY,CAAC;;AAuBlC,MAAM,oBAAA,GAAuBA,+BAAsB;AAC1D,EAAE,gBAAgB;AAClB,EAAE,CAAC,OAAO;AACV,IAAI,IAAI,yBAAyB,CAAC;AAClC,MAAM,iBAAiB,EAAE,OAAO,EAAE,iBAAA,IAAqB,IAAI;AAC3D,MAAM,WAAW,EAAE,OAAO,EAAE,WAAW;AACvC,KAAK,CAAC;AACN;;AAEA;AACA;AACA;AACA;AACO,MAAM,yBAAA,SAAkCC,mCAAmB,CAAkC;AACpG,GAAS,WAAW,CAAC,MAAM,EAAmC;AAC9D,IAAI,KAAK,CAAC,oBAAoB,EAAEC,gBAAW,EAAE,MAAM,CAAC;AACpD;;AAEA;AACA;AACA;AACA,GAAS,IAAI,GAA0C;AACvD,IAAI,MAAM,wBAAwB,IAAIC,mDAAmC,CAAC,UAAU,EAAE,kBAAkB,CAAC;;AAEzG,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,IAAA,IAAQ;AACjD,MAAM,qBAAqB,CAAC,KAAK,CAAC,IAAI;AACtC,QAAQ,IAAIC,6CAA6B;AACzC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC;AAC1C,UAAU,CAAC,GAAG,CAAC;AACf,UAAU,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;AAC1C,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,SAAS;AACT,OAAO;;AAEP,MAAM,qBAAqB,CAAC,KAAK,CAAC,IAAI;AACtC,QAAQ,IAAIA,6CAA6B;AACzC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC;AACrC,UAAU,kBAAkB;AAC5B,UAAU,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;AACrC,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,SAAS;AACT,OAAO;AACP,KAAK,CAAC;;AAEN,IAAI,OAAO,CAAC,qBAAqB,CAAC;AAClC;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAU,kBAAkB,GAAY;AACxC,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,SAAS,EAAE;AACnC,IAAI,MAAM,aAAA,GAAgBC,SAAK,CAAC,OAAO,CAACC,WAAO,CAAC,MAAM,EAAE,CAAA,KAAM,SAAS;AACvE,IAAI,OAAO,aAAA,IAAiB,CAAC,MAAM,CAAC,iBAAiB;AACrD;;AAEA;AACA;AACA;AACA,GAAU,YAAY,CAAC,YAAY,EAAO,IAAI,EAAa;AAC3D,IAAI,OAAO,IAAI,KAAK,CAAC,YAAY,EAAE;AACnC,MAAM,KAAK,EAAE;AACb,QAAQ,YAAY;AACpB,QAAQ,aAAa;AACrB,QAAQ;;AAIA;AACR,WAAW;AACX,QAAQ,IAAI,CAAC,SAAS,CAAC;AACvB,UAAU,IAAI,EAAEC,sBAAiB;AACjC;AACA;AACA,UAAU,OAAO,EAAE,UAAU,GAAG,CAAC,CAAC,EAAE,OAAA,IAAW,eAAe;AAC9D,SAAS,CAAC;;AAEV,QAAQ,MAAM,MAAA,GAAS,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,aAAa,EAAE,UAAU,CAAC;;AAE7E;AACA;AACA,QAAQ,IAAI,CAAC,YAAY,CAACC,gDAA4B,EAAE,UAAU,GAAG,CAAC,CAAC,EAAE,IAAA,IAAQ,eAAe,CAAC;AACjG;AACA,QAAQ,IAAI,CAAC,YAAY,CAACC,mCAAe,EAAE,UAAU,GAAG,CAAC,CAAC,EAAE,IAAA,IAAQ,eAAe,CAAC;;AAEpF,QAAQ,IAAI,CAAC,GAAG,EAAE;AAClB,QAAQ,OAAO,MAAM;AACrB,OAAO;AACP,KAAK,CAAC;AACN;;AAEA;AACA;AACA;AACA,GAAU,aAAa,CAAC,aAAa,EAAO,IAAI,EAAa;AAC7D,IAAI,OAAO,IAAI,KAAK,CAAC,aAAa,EAAE;AACpC,MAAM,KAAK,EAAE,CAAC,aAAa,EAAE,cAAc,EAAE,WAAW,KAA6B;AACrF,QAAQ,MAAM,MAAA,GAAS,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,cAAc,EAAE,WAAW,CAAC;AAChF,QAAQ,MAAM,aAAa,WAAW,GAAG,CAAC,CAAC,EAAE,OAAO;;AAEpD,QAAQ,IAAI,UAAU,EAAE;AACxB;AACA,UAAU,IAAI,CAAC,YAAY,CAACC,0CAAsB,EAAE,UAAU,CAAC;AAC/D;AACA,QAAQ,IAAI,CAAC,GAAG,EAAE;AAClB,QAAQ,OAAO,MAAM;AACrB,OAAO;AACP,KAAK,CAAC;AACN;;AAEA;AACA;AACA;AACA,GAAU,WAAW,CAAC;;AAMpB,EAAQ;AACV,IAAI,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,IAAI,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE;AAC3F,MAAM,KAAK,EAAE;AACb,QAAQ,YAAY;AACpB,QAAQ;;AAIA;AACR,QAAQ,UAAU;AAClB,WAAW;AACX,QAAQ,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE;AACxC;AACA,UAAU,OAAO,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,aAAa,EAAE,UAAU,CAAC;AACvE;;AAEA,QAAQ,MAAM,iBAAA,GAAoB,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;;AAEpF,QAAQ,OAAOC,oBAAe;AAC9B,UAAU;AACV,YAAY,IAAI,EAAE,iBAAA,IAAqB,kBAAkB;AACzD,YAAY,EAAE,EAAE,IAAI;AACpB,WAAW;AACX,UAAU,CAAC,IAAI,KAAW;AAC1B,YAAY,MAAM,KAAA,GAAQC,oBAAe,EAAE;AAC3C,YAAY,MAAM,yBAAA,GAA4B,KAAK,CAAC,YAAY,EAAE,CAAC,QAAQ,CAAC,sBAAsB;;AAEpF;;AAEd,YAAYC,wBAAe,CAAC,IAAI,EAAE,uBAAuB,CAAC;;AAE1D,YAAY,MAAM,EAAE,WAAA,EAAY,GAAI,IAAI,CAAC,SAAS,EAAE;;AAEpD,YAAY,IAAI,WAAW,EAAE;AAC7B,cAAcC,sCAAsB;AACpC,gBAAgB,MAAM,WAAW,CAAC,IAAI,EAAE,iBAAiB,EAAE,yBAAyB,CAAC;AACrF,gBAAgB,SAAS;AACzB,kBAAkB,IAAI,KAAK,EAAE;AAC7B,oBAAoBC,WAAM,CAAC,KAAK,CAAC,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC;AACpG;AACA,iBAAiB;AACjB,eAAe;AACf;;AAEA;AACA;AACA,YAAY,MAAM,YAAA,GAAe,yBAAyB,EAAE,iBAAA,IAAqB,oBAAoB;AACrG,YAAY,MAAM,YAAA,GAAe,yBAAyB,EAAE,mBAAA,IAAuB,gBAAgB;AACnG,YAAY,MAAM,YAAA,GAAe,yBAAyB,EAAE,gBAAA,IAAoB,gBAAgB;;AAEhG,YAAY,IAAI,CAAC,YAAY,CAACC,uCAAmB,EAAE,UAAU,CAAC;AAC9D,YAAY,IAAI,CAAC,YAAY,CAACC,qCAAiB,EAAE,YAAY,CAAC;AAC9D,YAAY,IAAI,CAAC,YAAY,CAACC,uCAAmB,EAAE,YAAY,CAAC;AAChE,YAAY,IAAI,CAAC,YAAY,CAACC,oCAAgB,EAAE,YAAY,CAAC;AAC7D,YAAY,IAAI,CAAC,YAAY,CAACC,sCAAkB,EAAE,iBAAiB,CAAC;;AAEpE,YAAY,aAAa,CAAC,OAAA,GAAU,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC;AACnF,YAAY,aAAa,CAAC,MAAA,GAAS,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC;;AAEhF,YAAY,IAAI;AAChB,cAAc,OAAO,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,aAAa,EAAE,UAAU,CAAC;AAC3E,aAAY,CAAE,OAAO,KAAK,EAAE;AAC5B,cAAc,IAAI,CAAC,SAAS,CAAC;AAC7B,gBAAgB,IAAI,EAAEb,sBAAiB;AACvC,eAAe,CAAC;AAChB,cAAc,IAAI,CAAC,GAAG,EAAE;AACxB,cAAc,MAAM,KAAK,CAAA;AACzB;AACA,WAAW;AACX,SAAS;AACT,OAAO;AACP,KAAK,CAAC;;AAEN,IAAI,OAAO,aAAa;AACxB;;AAEA;AACA;AACA;AACA;AACA,GAAU,gBAAgB,CAAC,UAAU,EAAY;AACjD,IAAI,OAAO,IAAI,KAAK,CAAC,UAAU,EAAE;AACjC,MAAM,KAAK,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,cAAc,KAA6D;AACpH,QAAQ,MAAM,YAAA,GAAe,cAAc,CAAC,CAAC,CAAC,EAAE,QAAA,IAAY,oBAAoB;AAChF,QAAQ,MAAM,YAAA,GAAe,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAA,IAAK,gBAAgB;AAC7E,QAAQ,MAAM,YAAA,GAAe,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAA,IAAK,gBAAgB;;AAE7E,QAAQ,MAAM,KAAA,GAAQK,oBAAe,EAAE;AACvC,QAAQ,KAAK,CAAC,UAAU,CAAC,sBAAsB,EAAE;AACjD,UAAU,iBAAiB,EAAE,YAAY;AACzC,UAAU,mBAAmB,EAAE,YAAY;AAC3C,UAAU,gBAAgB,EAAE,YAAY;AACxC,SAAS,CAAC;;AAEV,QAAQ,OAAO,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,OAAO,EAAE,cAAc,CAAC;AACvE,OAAO;AACP,KAAK,CAAC;AACN;;AAEA;AACA;AACA;AACA;AACA,GAAU,iBAAiB,CAAC,QAAQ,EAA8B;AAClE,IAAI,IAAI,CAAC,QAAQ,EAAE;AACnB,MAAM,OAAO,mBAAmB;AAChC;;AAEA,IAAI;AACJ,MAAM;AACN,SAAS,OAAO,CAAC,MAAM,EAAE,GAAG;AAC5B,SAAS,IAAI,EAAC;AACd,SAAS,SAAS,CAAC,CAAC,EAAE,IAAI,CAAA;AAC1B,SAAS,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAA;AACtC,SAAS,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAA;AACxC,SAAS,OAAO,CAAC,OAAO,EAAE,EAAE,CAAA;AAC5B,SAAS,OAAO,CAAC,UAAU,EAAE,GAAG,CAAA;AAChC;AACA,SAAS,OAAO,CAAC,MAAM,EAAE,GAAG;AAC5B;AACA;AACA,SAAS,OAAO,CAAC,sCAAsC,EAAE,QAAQ;AACjE;AACA;AACA;;AAEA,MAAM,sBAAA,IAA0B,MAAM;AACtC,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,SAAS,GAAG;AAChB,MAAM,oBAAoB,EAAE;AAC5B,KAAK;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;MAEa,qBAAA,GAAwBS,sBAAiB,CAAC,sBAAsB;;;;;;"}
|
|
1
|
+
{"version":3,"file":"postgresjs.js","sources":["../../../../src/integrations/tracing/postgresjs.ts"],"sourcesContent":["// Instrumentation for https://github.com/porsager/postgres\nimport { context, trace } from '@opentelemetry/api';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n safeExecuteInTheMiddle,\n} from '@opentelemetry/instrumentation';\nimport {\n ATTR_DB_NAMESPACE,\n ATTR_DB_OPERATION_NAME,\n ATTR_DB_QUERY_TEXT,\n ATTR_DB_RESPONSE_STATUS_CODE,\n ATTR_DB_SYSTEM_NAME,\n ATTR_ERROR_TYPE,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n} from '@opentelemetry/semantic-conventions';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n debug,\n defineIntegration,\n getCurrentScope,\n SDK_VERSION,\n SPAN_STATUS_ERROR,\n startSpanManual,\n} from '@sentry/core';\nimport { addOriginToSpan, generateInstrumentOnce } from '@sentry/node-core';\n\nconst INTEGRATION_NAME = 'PostgresJs';\nconst SUPPORTED_VERSIONS = ['>=3.0.0 <4'];\n\ntype PostgresConnectionContext = {\n ATTR_DB_NAMESPACE?: string; // Database name\n ATTR_SERVER_ADDRESS?: string; // Hostname or IP address of the database server\n ATTR_SERVER_PORT?: string; // Port number of the database server\n};\n\ntype PostgresJsInstrumentationConfig = InstrumentationConfig & {\n /**\n * Whether to require a parent span for the instrumentation.\n * If set to true, the instrumentation will only create spans if there is a parent span\n * available in the current scope.\n * @default true\n */\n requireParentSpan?: boolean;\n /**\n * Hook to modify the span before it is started.\n * This can be used to set additional attributes or modify the span in any way.\n */\n requestHook?: (span: Span, sanitizedSqlQuery: string, postgresConnectionContext?: PostgresConnectionContext) => void;\n};\n\nexport const instrumentPostgresJs = generateInstrumentOnce(\n INTEGRATION_NAME,\n (options?: PostgresJsInstrumentationConfig) =>\n new PostgresJsInstrumentation({\n requireParentSpan: options?.requireParentSpan ?? true,\n requestHook: options?.requestHook,\n }),\n);\n\n/**\n * Instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n * This instrumentation captures postgresjs queries and their attributes,\n */\nexport class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsInstrumentationConfig> {\n public constructor(config: PostgresJsInstrumentationConfig) {\n super('sentry-postgres-js', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation.\n */\n public init(): InstrumentationNodeModuleDefinition[] {\n const instrumentationModule = new InstrumentationNodeModuleDefinition('postgres', SUPPORTED_VERSIONS);\n\n ['src', 'cf/src', 'cjs/src'].forEach(path => {\n instrumentationModule.files.push(\n new InstrumentationNodeModuleFile(\n `postgres/${path}/connection.js`,\n ['*'],\n this._patchConnection.bind(this),\n this._unwrap.bind(this),\n ),\n );\n\n instrumentationModule.files.push(\n new InstrumentationNodeModuleFile(\n `postgres/${path}/query.js`,\n SUPPORTED_VERSIONS,\n this._patchQuery.bind(this),\n this._unwrap.bind(this),\n ),\n );\n });\n\n return [instrumentationModule];\n }\n\n /**\n * Determines whether a span should be created based on the current context.\n * If `requireParentSpan` is set to true in the configuration, a span will\n * only be created if there is a parent span available.\n */\n private _shouldCreateSpans(): boolean {\n const config = this.getConfig();\n const hasParentSpan = trace.getSpan(context.active()) !== undefined;\n return hasParentSpan || !config.requireParentSpan;\n }\n\n /**\n * Patches the reject method of the Query class to set the span status and end it\n */\n private _patchReject(rejectTarget: any, span: Span): any {\n return new Proxy(rejectTarget, {\n apply: (\n rejectTarget,\n rejectThisArg,\n rejectArgs: {\n message?: string;\n code?: string;\n name?: string;\n }[],\n ) => {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n // This message is the error message from the rejectArgs, when available\n // e.g \"relation 'User' does not exist\"\n message: rejectArgs?.[0]?.message || 'unknown_error',\n });\n\n const result = Reflect.apply(rejectTarget, rejectThisArg, rejectArgs);\n\n // This status code is PG error code, e.g. '42P01' for \"relation does not exist\"\n // https://www.postgresql.org/docs/current/errcodes-appendix.html\n span.setAttribute(ATTR_DB_RESPONSE_STATUS_CODE, rejectArgs?.[0]?.code || 'Unknown error');\n // This is the error type, e.g. 'PostgresError' for a Postgres error\n span.setAttribute(ATTR_ERROR_TYPE, rejectArgs?.[0]?.name || 'Unknown error');\n\n span.end();\n return result;\n },\n });\n }\n\n /**\n * Patches the resolve method of the Query class to end the span when the query is resolved.\n */\n private _patchResolve(resolveTarget: any, span: Span): any {\n return new Proxy(resolveTarget, {\n apply: (resolveTarget, resolveThisArg, resolveArgs: [{ command?: string }]) => {\n const result = Reflect.apply(resolveTarget, resolveThisArg, resolveArgs);\n const sqlCommand = resolveArgs?.[0]?.command;\n\n if (sqlCommand) {\n // SQL command is only available when the query is resolved successfully\n span.setAttribute(ATTR_DB_OPERATION_NAME, sqlCommand);\n }\n span.end();\n return result;\n },\n });\n }\n\n /**\n * Patches the Query class to instrument the handle method.\n */\n private _patchQuery(moduleExports: {\n Query: {\n prototype: {\n handle: any;\n };\n };\n }): any {\n moduleExports.Query.prototype.handle = new Proxy(moduleExports.Query.prototype.handle, {\n apply: async (\n handleTarget,\n handleThisArg: {\n resolve: any;\n reject: any;\n strings?: string[];\n },\n handleArgs,\n ) => {\n if (!this._shouldCreateSpans()) {\n // If we don't need to create spans, just call the original method\n return Reflect.apply(handleTarget, handleThisArg, handleArgs);\n }\n\n const sanitizedSqlQuery = this._sanitizeSqlQuery(handleThisArg.strings?.[0]);\n\n return startSpanManual(\n {\n name: sanitizedSqlQuery || 'postgresjs.query',\n op: 'db',\n },\n (span: Span) => {\n const scope = getCurrentScope();\n const postgresConnectionContext = scope.getScopeData().contexts['postgresjsConnection'] as\n | PostgresConnectionContext\n | undefined;\n\n addOriginToSpan(span, 'auto.db.otel.postgres');\n\n const { requestHook } = this.getConfig();\n\n if (requestHook) {\n safeExecuteInTheMiddle(\n () => requestHook(span, sanitizedSqlQuery, postgresConnectionContext),\n error => {\n if (error) {\n debug.error(`Error in requestHook for ${INTEGRATION_NAME} integration:`, error);\n }\n },\n );\n }\n\n // ATTR_DB_NAMESPACE is used to indicate the database name and the schema name\n // It's only the database name as we don't have the schema information\n const databaseName = postgresConnectionContext?.ATTR_DB_NAMESPACE || '<unknown database>';\n const databaseHost = postgresConnectionContext?.ATTR_SERVER_ADDRESS || '<unknown host>';\n const databasePort = postgresConnectionContext?.ATTR_SERVER_PORT || '<unknown port>';\n\n span.setAttribute(ATTR_DB_SYSTEM_NAME, 'postgres');\n span.setAttribute(ATTR_DB_NAMESPACE, databaseName);\n span.setAttribute(ATTR_SERVER_ADDRESS, databaseHost);\n span.setAttribute(ATTR_SERVER_PORT, databasePort);\n span.setAttribute(ATTR_DB_QUERY_TEXT, sanitizedSqlQuery);\n\n handleThisArg.resolve = this._patchResolve(handleThisArg.resolve, span);\n handleThisArg.reject = this._patchReject(handleThisArg.reject, span);\n\n try {\n return Reflect.apply(handleTarget, handleThisArg, handleArgs);\n } catch (error) {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n });\n span.end();\n throw error; // Re-throw the error to propagate it\n }\n },\n );\n },\n });\n\n return moduleExports;\n }\n\n /**\n * Patches the Connection class to set the database, host, and port attributes\n * when a new connection is created.\n */\n private _patchConnection(Connection: any): any {\n return new Proxy(Connection, {\n apply: (connectionTarget, thisArg, connectionArgs: { database: string; host: string[]; port: number[] }[]) => {\n const databaseName = connectionArgs[0]?.database || '<unknown database>';\n const databaseHost = connectionArgs[0]?.host?.[0] || '<unknown host>';\n const databasePort = connectionArgs[0]?.port?.[0] || '<unknown port>';\n\n const scope = getCurrentScope();\n scope.setContext('postgresjsConnection', {\n ATTR_DB_NAMESPACE: databaseName,\n ATTR_SERVER_ADDRESS: databaseHost,\n ATTR_SERVER_PORT: databasePort,\n });\n\n return Reflect.apply(connectionTarget, thisArg, connectionArgs);\n },\n });\n }\n\n /**\n * Sanitize SQL query as per the OTEL semantic conventions\n * https://opentelemetry.io/docs/specs/semconv/database/database-spans/#sanitization-of-dbquerytext\n */\n private _sanitizeSqlQuery(sqlQuery: string | undefined): string {\n if (!sqlQuery) {\n return 'Unknown SQL Query';\n }\n\n return (\n sqlQuery\n .replace(/\\s+/g, ' ')\n .trim() // Remove extra spaces including newlines and trim\n .substring(0, 1024) // Truncate to 1024 characters\n .replace(/--.*?(\\r?\\n|$)/g, '') // Single line comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Multi-line comments\n .replace(/;\\s*$/, '') // Remove trailing semicolons\n .replace(/\\b\\d+\\b/g, '?') // Replace standalone numbers\n // Collapse whitespace to a single space\n .replace(/\\s+/g, ' ')\n // Collapse IN and in clauses\n // eg. IN (?, ?, ?, ?) to IN (?)\n .replace(/\\bIN\\b\\s*\\(\\s*\\?(?:\\s*,\\s*\\?)*\\s*\\)/g, 'IN (?)')\n );\n }\n}\n\nconst _postgresJsIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentPostgresJs();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n *\n * For more information, see the [`postgresIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/postgres/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.postgresJsIntegration()],\n * });\n * ```\n */\n\nexport const postgresJsIntegration = defineIntegration(_postgresJsIntegration);\n"],"names":["generateInstrumentOnce","InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","InstrumentationNodeModuleFile","trace","context","SPAN_STATUS_ERROR","ATTR_DB_RESPONSE_STATUS_CODE","ATTR_ERROR_TYPE","ATTR_DB_OPERATION_NAME","startSpanManual","getCurrentScope","addOriginToSpan","safeExecuteInTheMiddle","debug","ATTR_DB_SYSTEM_NAME","ATTR_DB_NAMESPACE","ATTR_SERVER_ADDRESS","ATTR_SERVER_PORT","ATTR_DB_QUERY_TEXT","defineIntegration"],"mappings":"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"}
|
package/build/cjs/sdk/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/sdk/index.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport { hasSpansEnabled } from '@sentry/core';\nimport type { NodeClient } from '@sentry/node-core';\nimport {\n getDefaultIntegrations as getNodeCoreDefaultIntegrations,\n init as initNodeCore,\n validateOpenTelemetrySetup,\n} from '@sentry/node-core';\nimport { httpIntegration } from '../integrations/http';\nimport { nativeNodeFetchIntegration } from '../integrations/node-fetch';\nimport { getAutoPerformanceIntegrations } from '../integrations/tracing';\nimport type { NodeOptions } from '../types';\nimport { initOpenTelemetry } from './initOtel';\n\n/**\n * Get default integrations, excluding performance.\n */\nexport function getDefaultIntegrationsWithoutPerformance(): Integration[] {\n const nodeCoreIntegrations = getNodeCoreDefaultIntegrations();\n\n // Filter out the node-core HTTP and NodeFetch integrations and replace them with Node SDK's composite versions\n return nodeCoreIntegrations\n .filter(integration => integration.name !== 'Http' && integration.name !== 'NodeFetch')\n .concat(httpIntegration(), nativeNodeFetchIntegration());\n}\n\n/** Get the default integrations for the Node SDK. */\nexport function getDefaultIntegrations(options: Options): Integration[] {\n return [\n ...getDefaultIntegrationsWithoutPerformance(),\n // We only add performance integrations if tracing is enabled\n // Note that this means that without tracing enabled, e.g. `expressIntegration()` will not be added\n // This means that generally request isolation will work (because that is done by httpIntegration)\n // But `transactionName` will not be set automatically\n ...(hasSpansEnabled(options) ? getAutoPerformanceIntegrations() : []),\n ];\n}\n\n/**\n * Initialize Sentry for Node.\n */\nexport function init(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Internal initialization function.\n */\nfunction _init(\n options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClient | undefined {\n const client = initNodeCore({\n ...options,\n // Only use Node SDK defaults if none provided\n defaultIntegrations: options.defaultIntegrations ?? getDefaultIntegrationsImpl(options),\n });\n\n // Add Node SDK specific OpenTelemetry setup\n if (client && !options.skipOpenTelemetrySetup) {\n initOpenTelemetry(client, {\n spanProcessors: options.openTelemetrySpanProcessors,\n });\n validateOpenTelemetrySetup();\n }\n\n return client;\n}\n\n/**\n * Initialize Sentry for Node, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, () => []);\n}\n"],"names":["getNodeCoreDefaultIntegrations","httpIntegration","nativeNodeFetchIntegration","hasSpansEnabled","getAutoPerformanceIntegrations","initNodeCore","initOpenTelemetry","validateOpenTelemetrySetup"],"mappings":";;;;;;;;;AAcA;AACA;AACA;AACO,SAAS,wCAAwC,GAAkB;AAC1E,EAAE,MAAM,oBAAA,GAAuBA,+BAA8B,EAAE;;AAE/D;AACA,EAAE,OAAO;AACT,KAAK,MAAM,CAAC,WAAA,IAAe,WAAW,CAAC,IAAA,KAAS,UAAU,WAAW,CAAC,IAAA,KAAS,WAAW;AAC1F,KAAK,MAAM,CAACC,uBAAe,EAAE,EAAEC,kCAA0B,EAAE,CAAC;AAC5D;;AAEA;AACO,SAAS,sBAAsB,CAAC,OAAO,EAA0B;AACxE,EAAE,OAAO;AACT,IAAI,GAAG,wCAAwC,EAAE;AACjD;AACA;AACA;AACA;AACA,IAAI,IAAIC,oBAAe,CAAC,OAAO,CAAA,GAAIC,oCAA8B,EAAC,GAAI,EAAE,CAAC;AACzE,GAAG;AACH;;AAEA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,GAA4B,EAAE,EAA0B;AACpF,EAAE,OAAO,KAAK,CAAC,OAAO,EAAE,sBAAsB,CAAC;AAC/C;;AAEA;AACA;AACA;AACA,SAAS,KAAK;AACd,EAAE,OAAO,GAA4B,EAAE;AACvC,EAAE,0BAA0B;AAC5B,EAA0B;AAC1B,EAAE,MAAM,MAAA,GAASC,aAAY,CAAC;AAC9B,IAAI,GAAG,OAAO;AACd;AACA,IAAI,mBAAmB,EAAE,OAAO,CAAC,uBAAuB,0BAA0B,CAAC,OAAO,CAAC;AAC3F,GAAG,CAAC;;AAEJ;AACA,EAAE,IAAI,MAAA,IAAU,CAAC,OAAO,CAAC,sBAAsB,EAAE;AACjD,IAAIC,0BAAiB,CAAC,MAAM,EAAE;AAC9B,MAAM,cAAc,EAAE,OAAO,CAAC,2BAA2B;AACzD,KAAK,CAAC;AACN,IAAIC,mCAA0B,EAAE;AAChC;;AAEA,EAAE,OAAO,MAAM;AACf;;AAEA;AACA;AACA;AACO,SAAS,8BAA8B,CAAC,OAAO,GAA4B,EAAE,EAA0B;AAC9G,EAAE,OAAO,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;AACjC;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/sdk/index.ts"],"sourcesContent":["import type { Integration, Options } from '@sentry/core';\nimport { applySdkMetadata, hasSpansEnabled } from '@sentry/core';\nimport type { NodeClient } from '@sentry/node-core';\nimport {\n getDefaultIntegrations as getNodeCoreDefaultIntegrations,\n init as initNodeCore,\n validateOpenTelemetrySetup,\n} from '@sentry/node-core';\nimport { httpIntegration } from '../integrations/http';\nimport { nativeNodeFetchIntegration } from '../integrations/node-fetch';\nimport { getAutoPerformanceIntegrations } from '../integrations/tracing';\nimport type { NodeOptions } from '../types';\nimport { initOpenTelemetry } from './initOtel';\n\n/**\n * Get default integrations, excluding performance.\n */\nexport function getDefaultIntegrationsWithoutPerformance(): Integration[] {\n const nodeCoreIntegrations = getNodeCoreDefaultIntegrations();\n\n // Filter out the node-core HTTP and NodeFetch integrations and replace them with Node SDK's composite versions\n return nodeCoreIntegrations\n .filter(integration => integration.name !== 'Http' && integration.name !== 'NodeFetch')\n .concat(httpIntegration(), nativeNodeFetchIntegration());\n}\n\n/** Get the default integrations for the Node SDK. */\nexport function getDefaultIntegrations(options: Options): Integration[] {\n return [\n ...getDefaultIntegrationsWithoutPerformance(),\n // We only add performance integrations if tracing is enabled\n // Note that this means that without tracing enabled, e.g. `expressIntegration()` will not be added\n // This means that generally request isolation will work (because that is done by httpIntegration)\n // But `transactionName` will not be set automatically\n ...(hasSpansEnabled(options) ? getAutoPerformanceIntegrations() : []),\n ];\n}\n\n/**\n * Initialize Sentry for Node.\n */\nexport function init(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, getDefaultIntegrations);\n}\n\n/**\n * Internal initialization function.\n */\nfunction _init(\n options: NodeOptions | undefined = {},\n getDefaultIntegrationsImpl: (options: Options) => Integration[],\n): NodeClient | undefined {\n applySdkMetadata(options, 'node');\n\n const client = initNodeCore({\n ...options,\n // Only use Node SDK defaults if none provided\n defaultIntegrations: options.defaultIntegrations ?? getDefaultIntegrationsImpl(options),\n });\n\n // Add Node SDK specific OpenTelemetry setup\n if (client && !options.skipOpenTelemetrySetup) {\n initOpenTelemetry(client, {\n spanProcessors: options.openTelemetrySpanProcessors,\n });\n validateOpenTelemetrySetup();\n }\n\n return client;\n}\n\n/**\n * Initialize Sentry for Node, without any integrations added by default.\n */\nexport function initWithoutDefaultIntegrations(options: NodeOptions | undefined = {}): NodeClient | undefined {\n return _init(options, () => []);\n}\n"],"names":["getNodeCoreDefaultIntegrations","httpIntegration","nativeNodeFetchIntegration","hasSpansEnabled","getAutoPerformanceIntegrations","applySdkMetadata","initNodeCore","initOpenTelemetry","validateOpenTelemetrySetup"],"mappings":";;;;;;;;;AAcA;AACA;AACA;AACO,SAAS,wCAAwC,GAAkB;AAC1E,EAAE,MAAM,oBAAA,GAAuBA,+BAA8B,EAAE;;AAE/D;AACA,EAAE,OAAO;AACT,KAAK,MAAM,CAAC,WAAA,IAAe,WAAW,CAAC,IAAA,KAAS,UAAU,WAAW,CAAC,IAAA,KAAS,WAAW;AAC1F,KAAK,MAAM,CAACC,uBAAe,EAAE,EAAEC,kCAA0B,EAAE,CAAC;AAC5D;;AAEA;AACO,SAAS,sBAAsB,CAAC,OAAO,EAA0B;AACxE,EAAE,OAAO;AACT,IAAI,GAAG,wCAAwC,EAAE;AACjD;AACA;AACA;AACA;AACA,IAAI,IAAIC,oBAAe,CAAC,OAAO,CAAA,GAAIC,oCAA8B,EAAC,GAAI,EAAE,CAAC;AACzE,GAAG;AACH;;AAEA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,GAA4B,EAAE,EAA0B;AACpF,EAAE,OAAO,KAAK,CAAC,OAAO,EAAE,sBAAsB,CAAC;AAC/C;;AAEA;AACA;AACA;AACA,SAAS,KAAK;AACd,EAAE,OAAO,GAA4B,EAAE;AACvC,EAAE,0BAA0B;AAC5B,EAA0B;AAC1B,EAAEC,qBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC;;AAEnC,EAAE,MAAM,MAAA,GAASC,aAAY,CAAC;AAC9B,IAAI,GAAG,OAAO;AACd;AACA,IAAI,mBAAmB,EAAE,OAAO,CAAC,uBAAuB,0BAA0B,CAAC,OAAO,CAAC;AAC3F,GAAG,CAAC;;AAEJ;AACA,EAAE,IAAI,MAAA,IAAU,CAAC,OAAO,CAAC,sBAAsB,EAAE;AACjD,IAAIC,0BAAiB,CAAC,MAAM,EAAE;AAC9B,MAAM,cAAc,EAAE,OAAO,CAAC,2BAA2B;AACzD,KAAK,CAAC;AACN,IAAIC,mCAA0B,EAAE;AAChC;;AAEA,EAAE,OAAO,MAAM;AACf;;AAEA;AACA;AACA;AACO,SAAS,8BAA8B,CAAC,OAAO,GAA4B,EAAE,EAA0B;AAC9G,EAAE,OAAO,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;AACjC;;;;;;;"}
|
|
@@ -43,7 +43,7 @@ function maybeInitializeEsmLoader() {
|
|
|
43
43
|
transferList: [addHookMessagePort],
|
|
44
44
|
});
|
|
45
45
|
} catch (error) {
|
|
46
|
-
core.
|
|
46
|
+
core.debug.warn('Failed to register ESM hook', error);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
} else {
|
|
@@ -65,7 +65,7 @@ function preloadOpenTelemetry(options = {}) {
|
|
|
65
65
|
const { debug } = options;
|
|
66
66
|
|
|
67
67
|
if (debug) {
|
|
68
|
-
core.
|
|
68
|
+
core.debug.enable();
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
if (!nodeCore.isCjs()) {
|
|
@@ -77,7 +77,7 @@ function preloadOpenTelemetry(options = {}) {
|
|
|
77
77
|
fn();
|
|
78
78
|
|
|
79
79
|
if (debug) {
|
|
80
|
-
core.
|
|
80
|
+
core.debug.log(`[Sentry] Preloaded ${fn.id} instrumentation`);
|
|
81
81
|
}
|
|
82
82
|
});
|
|
83
83
|
}
|
|
@@ -130,10 +130,10 @@ function _clampSpanProcessorTimeout(maxSpanWaitDuration) {
|
|
|
130
130
|
// So if this value is too large, this would fail
|
|
131
131
|
if (maxSpanWaitDuration > MAX_MAX_SPAN_WAIT_DURATION) {
|
|
132
132
|
debugBuild.DEBUG_BUILD &&
|
|
133
|
-
core.
|
|
133
|
+
core.debug.warn(`\`maxSpanWaitDuration\` is too high, using the maximum value of ${MAX_MAX_SPAN_WAIT_DURATION}`);
|
|
134
134
|
return MAX_MAX_SPAN_WAIT_DURATION;
|
|
135
135
|
} else if (maxSpanWaitDuration <= 0 || Number.isNaN(maxSpanWaitDuration)) {
|
|
136
|
-
debugBuild.DEBUG_BUILD && core.
|
|
136
|
+
debugBuild.DEBUG_BUILD && core.debug.warn('`maxSpanWaitDuration` must be a positive number, using default value instead.');
|
|
137
137
|
return undefined;
|
|
138
138
|
}
|
|
139
139
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initOtel.js","sources":["../../../src/sdk/initOtel.ts"],"sourcesContent":["import { context, propagation, trace } from '@opentelemetry/api';\nimport { Resource } from '@opentelemetry/resources';\nimport type { SpanProcessor } from '@opentelemetry/sdk-trace-base';\nimport { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n SEMRESATTRS_SERVICE_NAMESPACE,\n} from '@opentelemetry/semantic-conventions';\nimport { consoleSandbox,
|
|
1
|
+
{"version":3,"file":"initOtel.js","sources":["../../../src/sdk/initOtel.ts"],"sourcesContent":["import { context, propagation, trace } from '@opentelemetry/api';\nimport { Resource } from '@opentelemetry/resources';\nimport type { SpanProcessor } from '@opentelemetry/sdk-trace-base';\nimport { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n SEMRESATTRS_SERVICE_NAMESPACE,\n} from '@opentelemetry/semantic-conventions';\nimport { consoleSandbox, debug as coreDebug, GLOBAL_OBJ, SDK_VERSION } from '@sentry/core';\nimport { type NodeClient, isCjs, SentryContextManager, setupOpenTelemetryLogger } from '@sentry/node-core';\nimport { SentryPropagator, SentrySampler, SentrySpanProcessor } from '@sentry/opentelemetry';\nimport { createAddHookMessageChannel } from 'import-in-the-middle';\nimport moduleModule from 'module';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { getOpenTelemetryInstrumentationToPreload } from '../integrations/tracing';\n\n// About 277h - this must fit into new Array(len)!\nconst MAX_MAX_SPAN_WAIT_DURATION = 1_000_000;\n\ninterface AdditionalOpenTelemetryOptions {\n /** Additional SpanProcessor instances that should be used. */\n spanProcessors?: SpanProcessor[];\n}\n\n/**\n * Initialize OpenTelemetry for Node.\n */\nexport function initOpenTelemetry(client: NodeClient, options: AdditionalOpenTelemetryOptions = {}): void {\n if (client.getOptions().debug) {\n setupOpenTelemetryLogger();\n }\n\n const provider = setupOtel(client, options);\n client.traceProvider = provider;\n}\n\n/** Initialize the ESM loader. */\nexport function maybeInitializeEsmLoader(): void {\n const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number);\n\n // Register hook was added in v20.6.0 and v18.19.0\n if (nodeMajor >= 21 || (nodeMajor === 20 && nodeMinor >= 6) || (nodeMajor === 18 && nodeMinor >= 19)) {\n if (!GLOBAL_OBJ._sentryEsmLoaderHookRegistered) {\n try {\n const { addHookMessagePort } = createAddHookMessageChannel();\n // @ts-expect-error register is available in these versions\n moduleModule.register('import-in-the-middle/hook.mjs', import.meta.url, {\n data: { addHookMessagePort, include: [] },\n transferList: [addHookMessagePort],\n });\n } catch (error) {\n coreDebug.warn('Failed to register ESM hook', error);\n }\n }\n } else {\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] You are using Node.js v${process.versions.node} in ESM mode (\"import syntax\"). The Sentry Node.js SDK is not compatible with ESM in Node.js versions before 18.19.0 or before 20.6.0. Please either build your application with CommonJS (\"require() syntax\"), or upgrade your Node.js version.`,\n );\n });\n }\n}\n\ninterface NodePreloadOptions {\n debug?: boolean;\n integrations?: string[];\n}\n\n/**\n * Preload OpenTelemetry for Node.\n * This can be used to preload instrumentation early, but set up Sentry later.\n * By preloading the OTEL instrumentation wrapping still happens early enough that everything works.\n */\nexport function preloadOpenTelemetry(options: NodePreloadOptions = {}): void {\n const { debug } = options;\n\n if (debug) {\n coreDebug.enable();\n }\n\n if (!isCjs()) {\n maybeInitializeEsmLoader();\n }\n\n // These are all integrations that we need to pre-load to ensure they are set up before any other code runs\n getPreloadMethods(options.integrations).forEach(fn => {\n fn();\n\n if (debug) {\n coreDebug.log(`[Sentry] Preloaded ${fn.id} instrumentation`);\n }\n });\n}\n\nfunction getPreloadMethods(integrationNames?: string[]): ((() => void) & { id: string })[] {\n const instruments = getOpenTelemetryInstrumentationToPreload();\n\n if (!integrationNames) {\n return instruments;\n }\n\n return instruments.filter(instrumentation => integrationNames.includes(instrumentation.id));\n}\n\n/** Just exported for tests. */\nexport function setupOtel(client: NodeClient, options: AdditionalOpenTelemetryOptions = {}): BasicTracerProvider {\n // Create and configure NodeTracerProvider\n const provider = new BasicTracerProvider({\n sampler: new SentrySampler(client),\n resource: new Resource({\n [ATTR_SERVICE_NAME]: 'node',\n // eslint-disable-next-line deprecation/deprecation\n [SEMRESATTRS_SERVICE_NAMESPACE]: 'sentry',\n [ATTR_SERVICE_VERSION]: SDK_VERSION,\n }),\n forceFlushTimeoutMillis: 500,\n spanProcessors: [\n new SentrySpanProcessor({\n timeout: _clampSpanProcessorTimeout(client.getOptions().maxSpanWaitDuration),\n }),\n ...(options.spanProcessors || []),\n ],\n });\n\n // Register as globals\n trace.setGlobalTracerProvider(provider);\n propagation.setGlobalPropagator(new SentryPropagator());\n context.setGlobalContextManager(new SentryContextManager());\n\n return provider;\n}\n\n/** Just exported for tests. */\nexport function _clampSpanProcessorTimeout(maxSpanWaitDuration: number | undefined): number | undefined {\n if (maxSpanWaitDuration == null) {\n return undefined;\n }\n\n // We guard for a max. value here, because we create an array with this length\n // So if this value is too large, this would fail\n if (maxSpanWaitDuration > MAX_MAX_SPAN_WAIT_DURATION) {\n DEBUG_BUILD &&\n coreDebug.warn(`\\`maxSpanWaitDuration\\` is too high, using the maximum value of ${MAX_MAX_SPAN_WAIT_DURATION}`);\n return MAX_MAX_SPAN_WAIT_DURATION;\n } else if (maxSpanWaitDuration <= 0 || Number.isNaN(maxSpanWaitDuration)) {\n DEBUG_BUILD && coreDebug.warn('`maxSpanWaitDuration` must be a positive number, using default value instead.');\n return undefined;\n }\n\n return maxSpanWaitDuration;\n}\n"],"names":["setupOpenTelemetryLogger","GLOBAL_OBJ","createAddHookMessageChannel","moduleModule","coreDebug","consoleSandbox","isCjs","getOpenTelemetryInstrumentationToPreload","BasicTracerProvider","SentrySampler","Resource","ATTR_SERVICE_NAME","SEMRESATTRS_SERVICE_NAMESPACE","ATTR_SERVICE_VERSION","SDK_VERSION","SentrySpanProcessor","trace","propagation","SentryPropagator","context","SentryContextManager","DEBUG_BUILD"],"mappings":"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"}
|
|
@@ -53,7 +53,7 @@ function getCacheKeySafely(redisCommand, cmdArgs) {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
return flatten(cmdArgs.map(arg => processArg(arg)));
|
|
56
|
-
} catch
|
|
56
|
+
} catch {
|
|
57
57
|
return undefined;
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -82,7 +82,7 @@ function calculateCacheItemSize(response) {
|
|
|
82
82
|
else if (typeof value === 'number') return value.toString().length;
|
|
83
83
|
else if (value === null || value === undefined) return 0;
|
|
84
84
|
return JSON.stringify(value).length;
|
|
85
|
-
} catch
|
|
85
|
+
} catch {
|
|
86
86
|
return undefined;
|
|
87
87
|
}
|
|
88
88
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redisCache.js","sources":["../../../src/utils/redisCache.ts"],"sourcesContent":["import type { CommandArgs as IORedisCommandArgs } from '@opentelemetry/instrumentation-ioredis';\n\nconst SINGLE_ARG_COMMANDS = ['get', 'set', 'setex'];\n\nexport const GET_COMMANDS = ['get', 'mget'];\nexport const SET_COMMANDS = ['set', 'setex'];\n// todo: del, expire\n\n/** Checks if a given command is in the list of redis commands.\n * Useful because commands can come in lowercase or uppercase (depending on the library). */\nexport function isInCommands(redisCommands: string[], command: string): boolean {\n return redisCommands.includes(command.toLowerCase());\n}\n\n/** Determine cache operation based on redis statement */\nexport function getCacheOperation(\n command: string,\n): 'cache.get' | 'cache.put' | 'cache.remove' | 'cache.flush' | undefined {\n if (isInCommands(GET_COMMANDS, command)) {\n return 'cache.get';\n } else if (isInCommands(SET_COMMANDS, command)) {\n return 'cache.put';\n } else {\n return undefined;\n }\n}\n\nfunction keyHasPrefix(key: string, prefixes: string[]): boolean {\n return prefixes.some(prefix => key.startsWith(prefix));\n}\n\n/** Safely converts a redis key to a string (comma-separated if there are multiple keys) */\nexport function getCacheKeySafely(redisCommand: string, cmdArgs: IORedisCommandArgs): string[] | undefined {\n try {\n if (cmdArgs.length === 0) {\n return undefined;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const processArg = (arg: string | Buffer | number | any[]): string[] => {\n if (typeof arg === 'string' || typeof arg === 'number' || Buffer.isBuffer(arg)) {\n return [arg.toString()];\n } else if (Array.isArray(arg)) {\n return flatten(arg.map(arg => processArg(arg)));\n } else {\n return ['<unknown>'];\n }\n };\n\n const firstArg = cmdArgs[0];\n if (isInCommands(SINGLE_ARG_COMMANDS, redisCommand) && firstArg != null) {\n return processArg(firstArg);\n }\n\n return flatten(cmdArgs.map(arg => processArg(arg)));\n } catch
|
|
1
|
+
{"version":3,"file":"redisCache.js","sources":["../../../src/utils/redisCache.ts"],"sourcesContent":["import type { CommandArgs as IORedisCommandArgs } from '@opentelemetry/instrumentation-ioredis';\n\nconst SINGLE_ARG_COMMANDS = ['get', 'set', 'setex'];\n\nexport const GET_COMMANDS = ['get', 'mget'];\nexport const SET_COMMANDS = ['set', 'setex'];\n// todo: del, expire\n\n/** Checks if a given command is in the list of redis commands.\n * Useful because commands can come in lowercase or uppercase (depending on the library). */\nexport function isInCommands(redisCommands: string[], command: string): boolean {\n return redisCommands.includes(command.toLowerCase());\n}\n\n/** Determine cache operation based on redis statement */\nexport function getCacheOperation(\n command: string,\n): 'cache.get' | 'cache.put' | 'cache.remove' | 'cache.flush' | undefined {\n if (isInCommands(GET_COMMANDS, command)) {\n return 'cache.get';\n } else if (isInCommands(SET_COMMANDS, command)) {\n return 'cache.put';\n } else {\n return undefined;\n }\n}\n\nfunction keyHasPrefix(key: string, prefixes: string[]): boolean {\n return prefixes.some(prefix => key.startsWith(prefix));\n}\n\n/** Safely converts a redis key to a string (comma-separated if there are multiple keys) */\nexport function getCacheKeySafely(redisCommand: string, cmdArgs: IORedisCommandArgs): string[] | undefined {\n try {\n if (cmdArgs.length === 0) {\n return undefined;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const processArg = (arg: string | Buffer | number | any[]): string[] => {\n if (typeof arg === 'string' || typeof arg === 'number' || Buffer.isBuffer(arg)) {\n return [arg.toString()];\n } else if (Array.isArray(arg)) {\n return flatten(arg.map(arg => processArg(arg)));\n } else {\n return ['<unknown>'];\n }\n };\n\n const firstArg = cmdArgs[0];\n if (isInCommands(SINGLE_ARG_COMMANDS, redisCommand) && firstArg != null) {\n return processArg(firstArg);\n }\n\n return flatten(cmdArgs.map(arg => processArg(arg)));\n } catch {\n return undefined;\n }\n}\n\n/** Determines whether a redis operation should be considered as \"cache operation\" by checking if a key is prefixed.\n * We only support certain commands (such as 'set', 'get', 'mget'). */\nexport function shouldConsiderForCache(redisCommand: string, keys: string[], prefixes: string[]): boolean {\n if (!getCacheOperation(redisCommand)) {\n return false;\n }\n\n for (const key of keys) {\n if (keyHasPrefix(key, prefixes)) {\n return true;\n }\n }\n return false;\n}\n\n/** Calculates size based on the cache response value */\nexport function calculateCacheItemSize(response: unknown): number | undefined {\n const getSize = (value: unknown): number | undefined => {\n try {\n if (Buffer.isBuffer(value)) return value.byteLength;\n else if (typeof value === 'string') return value.length;\n else if (typeof value === 'number') return value.toString().length;\n else if (value === null || value === undefined) return 0;\n return JSON.stringify(value).length;\n } catch {\n return undefined;\n }\n };\n\n return Array.isArray(response)\n ? response.reduce((acc: number | undefined, curr) => {\n const size = getSize(curr);\n return typeof size === 'number' ? (acc !== undefined ? acc + size : size) : acc;\n }, 0)\n : getSize(response);\n}\n\ntype NestedArray<T> = Array<NestedArray<T> | T>;\n\nfunction flatten<T>(input: NestedArray<T>): T[] {\n const result: T[] = [];\n\n const flattenHelper = (input: NestedArray<T>): void => {\n input.forEach((el: T | NestedArray<T>) => {\n if (Array.isArray(el)) {\n flattenHelper(el as NestedArray<T>);\n } else {\n result.push(el as T);\n }\n });\n };\n\n flattenHelper(input);\n return result;\n}\n"],"names":[],"mappings":"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"}
|
package/build/esm/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export { genericPoolIntegration } from './integrations/tracing/genericPool.js';
|
|
|
23
23
|
export { dataloaderIntegration } from './integrations/tracing/dataloader.js';
|
|
24
24
|
export { amqplibIntegration } from './integrations/tracing/amqplib.js';
|
|
25
25
|
export { vercelAIIntegration } from './integrations/tracing/vercelai/index.js';
|
|
26
|
+
export { openAIIntegration } from './integrations/tracing/openai/index.js';
|
|
26
27
|
export { buildLaunchDarklyFlagUsedHandlerShim as buildLaunchDarklyFlagUsedHandler, launchDarklyIntegrationShim as launchDarklyIntegration } from './integrations/featureFlagShims/launchDarkly.js';
|
|
27
28
|
export { OpenFeatureIntegrationHookShim as OpenFeatureIntegrationHook, openFeatureIntegrationShim as openFeatureIntegration } from './integrations/featureFlagShims/openFeature.js';
|
|
28
29
|
export { statsigIntegrationShim as statsigIntegration } from './integrations/featureFlagShims/statsig.js';
|
package/build/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -57,7 +57,10 @@ function _shouldInstrumentSpans(options, clientOptions = {}) {
|
|
|
57
57
|
* It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.
|
|
58
58
|
*/
|
|
59
59
|
const httpIntegration = defineIntegration((options = {}) => {
|
|
60
|
-
const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [
|
|
60
|
+
const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [
|
|
61
|
+
[401, 404],
|
|
62
|
+
[300, 399],
|
|
63
|
+
];
|
|
61
64
|
|
|
62
65
|
return {
|
|
63
66
|
name: INTEGRATION_NAME,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/integrations/http/index.ts"],"sourcesContent":["import type { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } from 'node:http';\nimport { diag } from '@opentelemetry/api';\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport type { Span } from '@sentry/core';\nimport { defineIntegration, getClient, hasSpansEnabled } from '@sentry/core';\nimport type { HTTPModuleRequestIncomingMessage, NodeClient } from '@sentry/node-core';\nimport {\n type SentryHttpInstrumentationOptions,\n addOriginToSpan,\n generateInstrumentOnce,\n getRequestUrl,\n NODE_VERSION,\n SentryHttpInstrumentation,\n} from '@sentry/node-core';\nimport type { NodeClientOptions } from '../../types';\n\nconst INTEGRATION_NAME = 'Http';\n\nconst INSTRUMENTATION_NAME = '@opentelemetry_sentry-patched/instrumentation-http';\n\ninterface HttpOptions {\n /**\n * Whether breadcrumbs should be recorded for outgoing requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default HttpInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for request isolation is applied.\n *\n * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`.\n */\n spans?: boolean;\n\n /**\n * Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.\n * Read more about Release Health: https://docs.sentry.io/product/releases/health/\n *\n * Defaults to `true`.\n */\n trackIncomingRequestsAsSessions?: boolean;\n\n /**\n * Number of milliseconds until sessions tracked with `trackIncomingRequestsAsSessions` will be flushed as a session aggregate.\n *\n * Defaults to `60000` (60s).\n */\n sessionFlushingDelayMS?: number;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n *\n * The `url` param contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * For example: `'https://someService.com/users/details?id=123'`\n *\n * The `request` param contains the original {@type RequestOptions} object used to make the outgoing request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests to URLs where the given callback returns `true`.\n * Spans will be non recording if tracing is disabled.\n *\n * The `urlPath` param consists of the URL path and query string (if any) of the incoming request.\n * For example: `'/users/details?id=123'`\n *\n * The `request` param contains the original {@type IncomingMessage} object of the incoming request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreIncomingRequests?: (urlPath: string, request: IncomingMessage) => boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with 404 status code are ignored.\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[404]`\n */\n dropSpansForIncomingRequestStatusCodes?: (number | [number, number])[];\n\n /**\n * Do not capture the request body for incoming HTTP requests to URLs where the given callback returns `true`.\n * This can be useful for long running requests where the body is not needed and we want to avoid capturing it.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the incoming request.\n * @param request Contains the {@type RequestOptions} object used to make the incoming request.\n */\n ignoreIncomingRequestBody?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Controls the maximum size of incoming HTTP request bodies attached to events.\n *\n * Available options:\n * - 'none': No request bodies will be attached\n * - 'small': Request bodies up to 1,000 bytes will be attached\n * - 'medium': Request bodies up to 10,000 bytes will be attached (default)\n * - 'always': Request bodies will always be attached\n *\n * Note that even with 'always' setting, bodies exceeding 1MB will never be attached\n * for performance and security reasons.\n *\n * @default 'medium'\n */\n maxIncomingRequestBodySize?: 'none' | 'small' | 'medium' | 'always';\n\n /**\n * If true, do not generate spans for incoming requests at all.\n * This is used by Remix to avoid generating spans for incoming requests, as it generates its own spans.\n */\n disableIncomingRequestSpans?: boolean;\n\n /**\n * Additional instrumentation options that are passed to the underlying HttpInstrumentation.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: ClientRequest | HTTPModuleRequestIncomingMessage) => void;\n responseHook?: (span: Span, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => void;\n\n /**\n * You can pass any configuration through to the underlying instrumentation.\n * Note that there are no semver guarantees for this!\n */\n _experimentalConfig?: ConstructorParameters<typeof HttpInstrumentation>[0];\n };\n}\n\nconst instrumentSentryHttp = generateInstrumentOnce<SentryHttpInstrumentationOptions>(\n `${INTEGRATION_NAME}.sentry`,\n options => {\n return new SentryHttpInstrumentation(options);\n },\n);\n\nexport const instrumentOtelHttp = generateInstrumentOnce<HttpInstrumentationConfig>(INTEGRATION_NAME, config => {\n const instrumentation = new HttpInstrumentation(config);\n\n // We want to update the logger namespace so we can better identify what is happening here\n try {\n instrumentation['_diag'] = diag.createComponentLogger({\n namespace: INSTRUMENTATION_NAME,\n });\n // @ts-expect-error We are writing a read-only property here...\n instrumentation.instrumentationName = INSTRUMENTATION_NAME;\n } catch {\n // ignore errors here...\n }\n\n return instrumentation;\n});\n\n/** Exported only for tests. */\nexport function _shouldInstrumentSpans(options: HttpOptions, clientOptions: Partial<NodeClientOptions> = {}): boolean {\n // If `spans` is passed in, it takes precedence\n // Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled\n if (typeof options.spans === 'boolean') {\n return options.spans;\n }\n\n if (clientOptions.skipOpenTelemetrySetup) {\n return false;\n }\n\n // IMPORTANT: We only disable span instrumentation when spans are not enabled _and_ we are on Node 22+,\n // as otherwise the necessary diagnostics channel is not available yet\n if (!hasSpansEnabled(clientOptions) && NODE_VERSION.major >= 22) {\n return false;\n }\n\n return true;\n}\n\n/**\n * The http integration instruments Node's internal http and https modules.\n * It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.\n */\nexport const httpIntegration = defineIntegration((options: HttpOptions = {}) => {\n const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [404];\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n const instrumentSpans = _shouldInstrumentSpans(options, getClient<NodeClient>()?.getOptions());\n\n // This is Sentry-specific instrumentation for request isolation and breadcrumbs\n instrumentSentryHttp({\n ...options,\n // If spans are not instrumented, it means the HttpInstrumentation has not been added\n // In that case, we want to handle incoming trace extraction ourselves\n extractIncomingTraceFromHeader: !instrumentSpans,\n // If spans are not instrumented, it means the HttpInstrumentation has not been added\n // In that case, we want to handle trace propagation ourselves\n propagateTraceInOutgoingRequests: !instrumentSpans,\n });\n\n // This is the \"regular\" OTEL instrumentation that emits spans\n if (instrumentSpans) {\n const instrumentationConfig = getConfigWithDefaults(options);\n instrumentOtelHttp(instrumentationConfig);\n }\n },\n processEvent(event) {\n // Drop transaction if it has a status code that should be ignored\n if (event.type === 'transaction') {\n const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];\n if (\n typeof statusCode === 'number' &&\n dropSpansForIncomingRequestStatusCodes.some(code => {\n if (typeof code === 'number') {\n return code === statusCode;\n }\n\n const [min, max] = code;\n return statusCode >= min && statusCode <= max;\n })\n ) {\n return null;\n }\n }\n\n return event;\n },\n };\n});\n\n/**\n * Determines if @param req is a ClientRequest, meaning the request was created within the express app\n * and it's an outgoing request.\n * Checking for properties instead of using `instanceOf` to avoid importing the request classes.\n */\nfunction _isClientRequest(req: ClientRequest | HTTPModuleRequestIncomingMessage): req is ClientRequest {\n return 'outputData' in req && 'outputSize' in req && !('client' in req) && !('statusCode' in req);\n}\n\n/**\n * Detects if an incoming request is a prefetch request.\n */\nfunction isKnownPrefetchRequest(req: HTTPModuleRequestIncomingMessage): boolean {\n // Currently only handles Next.js prefetch requests but may check other frameworks in the future.\n return req.headers['next-router-prefetch'] === '1';\n}\n\nfunction getConfigWithDefaults(options: Partial<HttpOptions> = {}): HttpInstrumentationConfig {\n const instrumentationConfig = {\n ...options.instrumentation?._experimentalConfig,\n\n disableIncomingRequestInstrumentation: options.disableIncomingRequestSpans,\n\n ignoreOutgoingRequestHook: request => {\n const url = getRequestUrl(request);\n\n if (!url) {\n return false;\n }\n\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n if (_ignoreOutgoingRequests?.(url, request)) {\n return true;\n }\n\n return false;\n },\n\n ignoreIncomingRequestHook: request => {\n // request.url is the only property that holds any information about the url\n // it only consists of the URL path and query string (if any)\n const urlPath = request.url;\n\n const method = request.method?.toUpperCase();\n // We do not capture OPTIONS/HEAD requests as transactions\n if (method === 'OPTIONS' || method === 'HEAD') {\n return true;\n }\n\n const _ignoreIncomingRequests = options.ignoreIncomingRequests;\n if (urlPath && _ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n },\n\n requireParentforOutgoingSpans: false,\n requireParentforIncomingSpans: false,\n requestHook: (span, req) => {\n addOriginToSpan(span, 'auto.http.otel.http');\n if (!_isClientRequest(req) && isKnownPrefetchRequest(req)) {\n span.setAttribute('sentry.http.prefetch', true);\n }\n\n options.instrumentation?.requestHook?.(span, req);\n },\n responseHook: (span, res) => {\n options.instrumentation?.responseHook?.(span, res);\n },\n applyCustomAttributesOnSpan: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => {\n options.instrumentation?.applyCustomAttributesOnSpan?.(span, request, response);\n },\n } satisfies HttpInstrumentationConfig;\n\n return instrumentationConfig;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/integrations/http/index.ts"],"sourcesContent":["import type { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } from 'node:http';\nimport { diag } from '@opentelemetry/api';\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';\nimport { HttpInstrumentation } from '@opentelemetry/instrumentation-http';\nimport type { Span } from '@sentry/core';\nimport { defineIntegration, getClient, hasSpansEnabled } from '@sentry/core';\nimport type { HTTPModuleRequestIncomingMessage, NodeClient } from '@sentry/node-core';\nimport {\n type SentryHttpInstrumentationOptions,\n addOriginToSpan,\n generateInstrumentOnce,\n getRequestUrl,\n NODE_VERSION,\n SentryHttpInstrumentation,\n} from '@sentry/node-core';\nimport type { NodeClientOptions } from '../../types';\n\nconst INTEGRATION_NAME = 'Http';\n\nconst INSTRUMENTATION_NAME = '@opentelemetry_sentry-patched/instrumentation-http';\n\ninterface HttpOptions {\n /**\n * Whether breadcrumbs should be recorded for outgoing requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default HttpInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for request isolation is applied.\n *\n * If `skipOpenTelemetrySetup: true` is configured, this defaults to `false`, otherwise it defaults to `true`.\n */\n spans?: boolean;\n\n /**\n * Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.\n * Read more about Release Health: https://docs.sentry.io/product/releases/health/\n *\n * Defaults to `true`.\n */\n trackIncomingRequestsAsSessions?: boolean;\n\n /**\n * Number of milliseconds until sessions tracked with `trackIncomingRequestsAsSessions` will be flushed as a session aggregate.\n *\n * Defaults to `60000` (60s).\n */\n sessionFlushingDelayMS?: number;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n *\n * The `url` param contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * For example: `'https://someService.com/users/details?id=123'`\n *\n * The `request` param contains the original {@type RequestOptions} object used to make the outgoing request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests to URLs where the given callback returns `true`.\n * Spans will be non recording if tracing is disabled.\n *\n * The `urlPath` param consists of the URL path and query string (if any) of the incoming request.\n * For example: `'/users/details?id=123'`\n *\n * The `request` param contains the original {@type IncomingMessage} object of the incoming request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreIncomingRequests?: (urlPath: string, request: IncomingMessage) => boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with 404 status code are ignored.\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [300, 399]]`\n */\n dropSpansForIncomingRequestStatusCodes?: (number | [number, number])[];\n\n /**\n * Do not capture the request body for incoming HTTP requests to URLs where the given callback returns `true`.\n * This can be useful for long running requests where the body is not needed and we want to avoid capturing it.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the incoming request.\n * @param request Contains the {@type RequestOptions} object used to make the incoming request.\n */\n ignoreIncomingRequestBody?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Controls the maximum size of incoming HTTP request bodies attached to events.\n *\n * Available options:\n * - 'none': No request bodies will be attached\n * - 'small': Request bodies up to 1,000 bytes will be attached\n * - 'medium': Request bodies up to 10,000 bytes will be attached (default)\n * - 'always': Request bodies will always be attached\n *\n * Note that even with 'always' setting, bodies exceeding 1MB will never be attached\n * for performance and security reasons.\n *\n * @default 'medium'\n */\n maxIncomingRequestBodySize?: 'none' | 'small' | 'medium' | 'always';\n\n /**\n * If true, do not generate spans for incoming requests at all.\n * This is used by Remix to avoid generating spans for incoming requests, as it generates its own spans.\n */\n disableIncomingRequestSpans?: boolean;\n\n /**\n * Additional instrumentation options that are passed to the underlying HttpInstrumentation.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: ClientRequest | HTTPModuleRequestIncomingMessage) => void;\n responseHook?: (span: Span, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => void;\n\n /**\n * You can pass any configuration through to the underlying instrumentation.\n * Note that there are no semver guarantees for this!\n */\n _experimentalConfig?: ConstructorParameters<typeof HttpInstrumentation>[0];\n };\n}\n\nconst instrumentSentryHttp = generateInstrumentOnce<SentryHttpInstrumentationOptions>(\n `${INTEGRATION_NAME}.sentry`,\n options => {\n return new SentryHttpInstrumentation(options);\n },\n);\n\nexport const instrumentOtelHttp = generateInstrumentOnce<HttpInstrumentationConfig>(INTEGRATION_NAME, config => {\n const instrumentation = new HttpInstrumentation(config);\n\n // We want to update the logger namespace so we can better identify what is happening here\n try {\n instrumentation['_diag'] = diag.createComponentLogger({\n namespace: INSTRUMENTATION_NAME,\n });\n // @ts-expect-error We are writing a read-only property here...\n instrumentation.instrumentationName = INSTRUMENTATION_NAME;\n } catch {\n // ignore errors here...\n }\n\n return instrumentation;\n});\n\n/** Exported only for tests. */\nexport function _shouldInstrumentSpans(options: HttpOptions, clientOptions: Partial<NodeClientOptions> = {}): boolean {\n // If `spans` is passed in, it takes precedence\n // Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled\n if (typeof options.spans === 'boolean') {\n return options.spans;\n }\n\n if (clientOptions.skipOpenTelemetrySetup) {\n return false;\n }\n\n // IMPORTANT: We only disable span instrumentation when spans are not enabled _and_ we are on Node 22+,\n // as otherwise the necessary diagnostics channel is not available yet\n if (!hasSpansEnabled(clientOptions) && NODE_VERSION.major >= 22) {\n return false;\n }\n\n return true;\n}\n\n/**\n * The http integration instruments Node's internal http and https modules.\n * It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.\n */\nexport const httpIntegration = defineIntegration((options: HttpOptions = {}) => {\n const dropSpansForIncomingRequestStatusCodes = options.dropSpansForIncomingRequestStatusCodes ?? [\n [401, 404],\n [300, 399],\n ];\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n const instrumentSpans = _shouldInstrumentSpans(options, getClient<NodeClient>()?.getOptions());\n\n // This is Sentry-specific instrumentation for request isolation and breadcrumbs\n instrumentSentryHttp({\n ...options,\n // If spans are not instrumented, it means the HttpInstrumentation has not been added\n // In that case, we want to handle incoming trace extraction ourselves\n extractIncomingTraceFromHeader: !instrumentSpans,\n // If spans are not instrumented, it means the HttpInstrumentation has not been added\n // In that case, we want to handle trace propagation ourselves\n propagateTraceInOutgoingRequests: !instrumentSpans,\n });\n\n // This is the \"regular\" OTEL instrumentation that emits spans\n if (instrumentSpans) {\n const instrumentationConfig = getConfigWithDefaults(options);\n instrumentOtelHttp(instrumentationConfig);\n }\n },\n processEvent(event) {\n // Drop transaction if it has a status code that should be ignored\n if (event.type === 'transaction') {\n const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];\n if (\n typeof statusCode === 'number' &&\n dropSpansForIncomingRequestStatusCodes.some(code => {\n if (typeof code === 'number') {\n return code === statusCode;\n }\n\n const [min, max] = code;\n return statusCode >= min && statusCode <= max;\n })\n ) {\n return null;\n }\n }\n\n return event;\n },\n };\n});\n\n/**\n * Determines if @param req is a ClientRequest, meaning the request was created within the express app\n * and it's an outgoing request.\n * Checking for properties instead of using `instanceOf` to avoid importing the request classes.\n */\nfunction _isClientRequest(req: ClientRequest | HTTPModuleRequestIncomingMessage): req is ClientRequest {\n return 'outputData' in req && 'outputSize' in req && !('client' in req) && !('statusCode' in req);\n}\n\n/**\n * Detects if an incoming request is a prefetch request.\n */\nfunction isKnownPrefetchRequest(req: HTTPModuleRequestIncomingMessage): boolean {\n // Currently only handles Next.js prefetch requests but may check other frameworks in the future.\n return req.headers['next-router-prefetch'] === '1';\n}\n\nfunction getConfigWithDefaults(options: Partial<HttpOptions> = {}): HttpInstrumentationConfig {\n const instrumentationConfig = {\n ...options.instrumentation?._experimentalConfig,\n\n disableIncomingRequestInstrumentation: options.disableIncomingRequestSpans,\n\n ignoreOutgoingRequestHook: request => {\n const url = getRequestUrl(request);\n\n if (!url) {\n return false;\n }\n\n const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;\n if (_ignoreOutgoingRequests?.(url, request)) {\n return true;\n }\n\n return false;\n },\n\n ignoreIncomingRequestHook: request => {\n // request.url is the only property that holds any information about the url\n // it only consists of the URL path and query string (if any)\n const urlPath = request.url;\n\n const method = request.method?.toUpperCase();\n // We do not capture OPTIONS/HEAD requests as transactions\n if (method === 'OPTIONS' || method === 'HEAD') {\n return true;\n }\n\n const _ignoreIncomingRequests = options.ignoreIncomingRequests;\n if (urlPath && _ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n },\n\n requireParentforOutgoingSpans: false,\n requireParentforIncomingSpans: false,\n requestHook: (span, req) => {\n addOriginToSpan(span, 'auto.http.otel.http');\n if (!_isClientRequest(req) && isKnownPrefetchRequest(req)) {\n span.setAttribute('sentry.http.prefetch', true);\n }\n\n options.instrumentation?.requestHook?.(span, req);\n },\n responseHook: (span, res) => {\n options.instrumentation?.responseHook?.(span, res);\n },\n applyCustomAttributesOnSpan: (\n span: Span,\n request: ClientRequest | HTTPModuleRequestIncomingMessage,\n response: HTTPModuleRequestIncomingMessage | ServerResponse,\n ) => {\n options.instrumentation?.applyCustomAttributesOnSpan?.(span, request, response);\n },\n } satisfies HttpInstrumentationConfig;\n\n return instrumentationConfig;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../../../src/integrations/tracing/express-v5/utils.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-assertion */\n/* eslint-disable @typescript-eslint/explicit-function-return-type */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n\n/*\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Attributes } from '@opentelemetry/api';\nimport { AttributeNames } from './enums/AttributeNames';\nimport { ExpressLayerType } from './enums/ExpressLayerType';\nimport type { ExpressLayer, PatchedRequest } from './internal-types';\nimport { _LAYERS_STORE_PROPERTY } from './internal-types';\nimport type { ExpressInstrumentationConfig, IgnoreMatcher, LayerPathSegment } from './types';\n\n/**\n * Store layers path in the request to be able to construct route later\n * @param request The request where\n * @param [value] the value to push into the array\n */\nexport const storeLayerPath = (request: PatchedRequest, value?: string): void => {\n if (Array.isArray(request[_LAYERS_STORE_PROPERTY]) === false) {\n Object.defineProperty(request, _LAYERS_STORE_PROPERTY, {\n enumerable: false,\n value: [],\n });\n }\n if (value === undefined) return;\n (request[_LAYERS_STORE_PROPERTY] as string[]).push(value);\n};\n\n/**\n * Recursively search the router path from layer stack\n * @param path The path to reconstruct\n * @param layer The layer to reconstruct from\n * @returns The reconstructed path\n */\nexport const getRouterPath = (path: string, layer: ExpressLayer): string => {\n const stackLayer = layer.handle?.stack?.[0];\n\n if (stackLayer?.route?.path) {\n return `${path}${stackLayer.route.path}`;\n }\n\n if (stackLayer?.handle?.stack) {\n return getRouterPath(path, stackLayer);\n }\n\n return path;\n};\n\n/**\n * Parse express layer context to retrieve a name and attributes.\n * @param route The route of the layer\n * @param layer Express layer\n * @param [layerPath] if present, the path on which the layer has been mounted\n */\nexport const getLayerMetadata = (\n route: string,\n layer: ExpressLayer,\n layerPath?: string,\n): {\n attributes: Attributes;\n name: string;\n} => {\n if (layer.name === 'router') {\n const maybeRouterPath = getRouterPath('', layer);\n const extractedRouterPath = maybeRouterPath ? maybeRouterPath : layerPath || route || '/';\n\n return {\n attributes: {\n [AttributeNames.EXPRESS_NAME]: extractedRouterPath,\n [AttributeNames.EXPRESS_TYPE]: ExpressLayerType.ROUTER,\n },\n name: `router - ${extractedRouterPath}`,\n };\n } else if (layer.name === 'bound dispatch' || layer.name === 'handle') {\n return {\n attributes: {\n [AttributeNames.EXPRESS_NAME]: (route || layerPath) ?? 'request handler',\n [AttributeNames.EXPRESS_TYPE]: ExpressLayerType.REQUEST_HANDLER,\n },\n name: `request handler${layer.path ? ` - ${route || layerPath}` : ''}`,\n };\n } else {\n return {\n attributes: {\n [AttributeNames.EXPRESS_NAME]: layer.name,\n [AttributeNames.EXPRESS_TYPE]: ExpressLayerType.MIDDLEWARE,\n },\n name: `middleware - ${layer.name}`,\n };\n }\n};\n\n/**\n * Check whether the given obj match pattern\n * @param constant e.g URL of request\n * @param obj obj to inspect\n * @param pattern Match pattern\n */\nconst satisfiesPattern = (constant: string, pattern: IgnoreMatcher): boolean => {\n if (typeof pattern === 'string') {\n return pattern === constant;\n } else if (pattern instanceof RegExp) {\n return pattern.test(constant);\n } else if (typeof pattern === 'function') {\n return pattern(constant);\n } else {\n throw new TypeError('Pattern is in unsupported datatype');\n }\n};\n\n/**\n * Check whether the given request is ignored by configuration\n * It will not re-throw exceptions from `list` provided by the client\n * @param constant e.g URL of request\n * @param [list] List of ignore patterns\n * @param [onException] callback for doing something when an exception has\n * occurred\n */\nexport const isLayerIgnored = (\n name: string,\n type: ExpressLayerType,\n config?: ExpressInstrumentationConfig,\n): boolean => {\n if (Array.isArray(config?.ignoreLayersType) && config?.ignoreLayersType?.includes(type)) {\n return true;\n }\n if (Array.isArray(config?.ignoreLayers) === false) return false;\n try {\n for (const pattern of config!.ignoreLayers!) {\n if (satisfiesPattern(name, pattern)) {\n return true;\n }\n }\n } catch
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../../../src/integrations/tracing/express-v5/utils.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-assertion */\n/* eslint-disable @typescript-eslint/explicit-function-return-type */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n\n/*\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Attributes } from '@opentelemetry/api';\nimport { AttributeNames } from './enums/AttributeNames';\nimport { ExpressLayerType } from './enums/ExpressLayerType';\nimport type { ExpressLayer, PatchedRequest } from './internal-types';\nimport { _LAYERS_STORE_PROPERTY } from './internal-types';\nimport type { ExpressInstrumentationConfig, IgnoreMatcher, LayerPathSegment } from './types';\n\n/**\n * Store layers path in the request to be able to construct route later\n * @param request The request where\n * @param [value] the value to push into the array\n */\nexport const storeLayerPath = (request: PatchedRequest, value?: string): void => {\n if (Array.isArray(request[_LAYERS_STORE_PROPERTY]) === false) {\n Object.defineProperty(request, _LAYERS_STORE_PROPERTY, {\n enumerable: false,\n value: [],\n });\n }\n if (value === undefined) return;\n (request[_LAYERS_STORE_PROPERTY] as string[]).push(value);\n};\n\n/**\n * Recursively search the router path from layer stack\n * @param path The path to reconstruct\n * @param layer The layer to reconstruct from\n * @returns The reconstructed path\n */\nexport const getRouterPath = (path: string, layer: ExpressLayer): string => {\n const stackLayer = layer.handle?.stack?.[0];\n\n if (stackLayer?.route?.path) {\n return `${path}${stackLayer.route.path}`;\n }\n\n if (stackLayer?.handle?.stack) {\n return getRouterPath(path, stackLayer);\n }\n\n return path;\n};\n\n/**\n * Parse express layer context to retrieve a name and attributes.\n * @param route The route of the layer\n * @param layer Express layer\n * @param [layerPath] if present, the path on which the layer has been mounted\n */\nexport const getLayerMetadata = (\n route: string,\n layer: ExpressLayer,\n layerPath?: string,\n): {\n attributes: Attributes;\n name: string;\n} => {\n if (layer.name === 'router') {\n const maybeRouterPath = getRouterPath('', layer);\n const extractedRouterPath = maybeRouterPath ? maybeRouterPath : layerPath || route || '/';\n\n return {\n attributes: {\n [AttributeNames.EXPRESS_NAME]: extractedRouterPath,\n [AttributeNames.EXPRESS_TYPE]: ExpressLayerType.ROUTER,\n },\n name: `router - ${extractedRouterPath}`,\n };\n } else if (layer.name === 'bound dispatch' || layer.name === 'handle') {\n return {\n attributes: {\n [AttributeNames.EXPRESS_NAME]: (route || layerPath) ?? 'request handler',\n [AttributeNames.EXPRESS_TYPE]: ExpressLayerType.REQUEST_HANDLER,\n },\n name: `request handler${layer.path ? ` - ${route || layerPath}` : ''}`,\n };\n } else {\n return {\n attributes: {\n [AttributeNames.EXPRESS_NAME]: layer.name,\n [AttributeNames.EXPRESS_TYPE]: ExpressLayerType.MIDDLEWARE,\n },\n name: `middleware - ${layer.name}`,\n };\n }\n};\n\n/**\n * Check whether the given obj match pattern\n * @param constant e.g URL of request\n * @param obj obj to inspect\n * @param pattern Match pattern\n */\nconst satisfiesPattern = (constant: string, pattern: IgnoreMatcher): boolean => {\n if (typeof pattern === 'string') {\n return pattern === constant;\n } else if (pattern instanceof RegExp) {\n return pattern.test(constant);\n } else if (typeof pattern === 'function') {\n return pattern(constant);\n } else {\n throw new TypeError('Pattern is in unsupported datatype');\n }\n};\n\n/**\n * Check whether the given request is ignored by configuration\n * It will not re-throw exceptions from `list` provided by the client\n * @param constant e.g URL of request\n * @param [list] List of ignore patterns\n * @param [onException] callback for doing something when an exception has\n * occurred\n */\nexport const isLayerIgnored = (\n name: string,\n type: ExpressLayerType,\n config?: ExpressInstrumentationConfig,\n): boolean => {\n if (Array.isArray(config?.ignoreLayersType) && config?.ignoreLayersType?.includes(type)) {\n return true;\n }\n if (Array.isArray(config?.ignoreLayers) === false) return false;\n try {\n for (const pattern of config!.ignoreLayers!) {\n if (satisfiesPattern(name, pattern)) {\n return true;\n }\n }\n } catch {\n /* catch block */\n }\n\n return false;\n};\n\n/**\n * Converts a user-provided error value into an error and error message pair\n *\n * @param error - User-provided error value\n * @returns Both an Error or string representation of the value and an error message\n */\nexport const asErrorAndMessage = (error: unknown): [error: string | Error, message: string] =>\n error instanceof Error ? [error, error.message] : [String(error), String(error)];\n\n/**\n * Extracts the layer path from the route arguments\n *\n * @param args - Arguments of the route\n * @returns The layer path\n */\nexport const getLayerPath = (args: [LayerPathSegment | LayerPathSegment[], ...unknown[]]): string | undefined => {\n const firstArg = args[0];\n\n if (Array.isArray(firstArg)) {\n return firstArg.map(arg => extractLayerPathSegment(arg) || '').join(',');\n }\n\n return extractLayerPathSegment(firstArg);\n};\n\nconst extractLayerPathSegment = (arg: LayerPathSegment) => {\n if (typeof arg === 'string') {\n return arg;\n }\n\n if (arg instanceof RegExp || typeof arg === 'number') {\n return arg.toString();\n }\n\n return;\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
|
|
2
|
-
import { defineIntegration, getIsolationScope, getDefaultIsolationScope,
|
|
2
|
+
import { defineIntegration, getIsolationScope, getDefaultIsolationScope, debug, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, httpRequestToRequestData, captureException } from '@sentry/core';
|
|
3
3
|
import { generateInstrumentOnce, addOriginToSpan, ensureIsWrapped } from '@sentry/node-core';
|
|
4
4
|
import { DEBUG_BUILD } from '../../debug-build.js';
|
|
5
5
|
import { ExpressInstrumentationV5 } from './express-v5/instrumentation.js';
|
|
@@ -27,7 +27,7 @@ function requestHook(span) {
|
|
|
27
27
|
|
|
28
28
|
function spanNameHook(info, defaultName) {
|
|
29
29
|
if (getIsolationScope() === getDefaultIsolationScope()) {
|
|
30
|
-
DEBUG_BUILD &&
|
|
30
|
+
DEBUG_BUILD && debug.warn('Isolation scope is still default isolation scope - skipping setting transactionName');
|
|
31
31
|
return defaultName;
|
|
32
32
|
}
|
|
33
33
|
if (info.layerType === 'request_handler') {
|