🚨 Active Supply Chain Attack:node-ipc Package Compromised.Learn More
Socket
Book a DemoSign in
Socket

@sentry/node

Package Overview
Dependencies
Maintainers
1
Versions
703
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sentry/node - npm Package Compare versions

Comparing version
10.51.0
to
10.52.0
+129
build/cjs/integrations/tracing/redis/index.js
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const core = require('@sentry/core');
const nodeCore = require('@sentry/node-core');
const redisCache = require('../../../utils/redisCache.js');
const ioredisInstrumentation = require('./vendored/ioredis-instrumentation.js');
const redisInstrumentation = require('./vendored/redis-instrumentation.js');
const redisDcSubscriber = require('./redis-dc-subscriber.js');
const INTEGRATION_NAME = 'Redis';
/* Only exported for testing purposes */
exports._redisOptions = {};
/* Only exported for testing purposes */
const cacheResponseHook = (
span,
redisCommand,
cmdArgs,
response,
) => {
const safeKey = redisCache.getCacheKeySafely(redisCommand, cmdArgs);
const cacheOperation = redisCache.getCacheOperation(redisCommand);
if (
!safeKey ||
!cacheOperation ||
!exports._redisOptions.cachePrefixes ||
!redisCache.shouldConsiderForCache(redisCommand, safeKey, exports._redisOptions.cachePrefixes)
) {
// not relevant for cache
return;
}
// otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199
// We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/
// Fall back to stable semconv attributes (server.address/server.port) when
// old-semconv ones are absent, eg OTEL_SEMCONV_STABILITY_OPT_IN=database
// set for node-redis v4/v5.
const spanData = core.spanToJSON(span).data;
const networkPeerAddress = spanData['net.peer.name'] ?? spanData['server.address'];
const networkPeerPort = spanData['net.peer.port'] ?? spanData['server.port'];
if (networkPeerPort && networkPeerAddress) {
span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });
}
const cacheItemSize = redisCache.calculateCacheItemSize(response);
if (cacheItemSize) {
span.setAttribute(core.SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);
}
if (redisCache.isInCommands(redisCache.GET_COMMANDS, redisCommand) && cacheItemSize !== undefined) {
span.setAttribute(core.SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);
}
span.setAttributes({
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,
[core.SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey,
});
// todo: change to string[] once EAP supports it
const spanDescription = safeKey.join(', ');
span.updateName(
exports._redisOptions.maxCacheKeyLength ? core.truncate(spanDescription, exports._redisOptions.maxCacheKeyLength) : spanDescription,
);
};
const instrumentIORedis = nodeCore.generateInstrumentOnce(`${INTEGRATION_NAME}.IORedis`, () => {
return new ioredisInstrumentation.IORedisInstrumentation({
responseHook: cacheResponseHook,
});
});
const instrumentRedisModule = nodeCore.generateInstrumentOnce(`${INTEGRATION_NAME}.Redis`, () => {
return new redisInstrumentation.RedisInstrumentation({
responseHook: cacheResponseHook,
});
});
/** To be able to preload all Redis OTel instrumentations with just one ID ("Redis"), all the instrumentations are generated in this one function */
const instrumentRedis = Object.assign(
() => {
instrumentIORedis();
instrumentRedisModule();
// node-redis >= 5.12.0 publishes via diagnostics_channel. The subscriber uses
// `@sentry/opentelemetry/tracing-channel`, which needs the Sentry OTel context manager
// to be registered before it can `bindStore`. `initOpenTelemetry()` runs after integration
// `setupOnce`, so defer to the next tick.
void Promise.resolve().then(() => redisDcSubscriber.subscribeRedisDiagnosticChannels(cacheResponseHook));
// todo: implement them gradually
// new LegacyRedisInstrumentation({}),
},
{ id: INTEGRATION_NAME },
);
const _redisIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
exports._redisOptions = options;
instrumentRedis();
},
};
}) ;
/**
* Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and
* [ioredis](https://www.npmjs.com/package/ioredis) libraries.
*
* For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).
*
* @example
* ```javascript
* const Sentry = require('@sentry/node');
*
* Sentry.init({
* integrations: [Sentry.redisIntegration()],
* });
* ```
*/
const redisIntegration = core.defineIntegration(_redisIntegration);
exports.cacheResponseHook = cacheResponseHook;
exports.instrumentRedis = instrumentRedis;
exports.redisIntegration = redisIntegration;
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/redis/index.ts"],"sourcesContent":["import type { Span } from '@opentelemetry/api';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n defineIntegration,\n SEMANTIC_ATTRIBUTE_CACHE_HIT,\n SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE,\n SEMANTIC_ATTRIBUTE_CACHE_KEY,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n truncate,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport type { IORedisCommandArgs } from '../../../utils/redisCache';\nimport {\n calculateCacheItemSize,\n GET_COMMANDS,\n getCacheKeySafely,\n getCacheOperation,\n isInCommands,\n shouldConsiderForCache,\n} from '../../../utils/redisCache';\nimport type { IORedisResponseCustomAttributeFunction } from './vendored/types';\nimport { IORedisInstrumentation } from './vendored/ioredis-instrumentation';\nimport { RedisInstrumentation } from './vendored/redis-instrumentation';\nimport { subscribeRedisDiagnosticChannels } from './redis-dc-subscriber';\n\ninterface RedisOptions {\n /**\n * Define cache prefixes for cache keys that should be captured as a cache span.\n *\n * Setting this to, for example, `['user:']` will capture cache keys that start with `user:`.\n */\n cachePrefixes?: string[];\n /**\n * Maximum length of the cache key added to the span description. If the key exceeds this length, it will be truncated.\n *\n * Passing `0` will use the full cache key without truncation.\n *\n * By default, the full cache key is used.\n */\n maxCacheKeyLength?: number;\n}\n\nconst INTEGRATION_NAME = 'Redis';\n\n/* Only exported for testing purposes */\nexport let _redisOptions: RedisOptions = {};\n\n/* Only exported for testing purposes */\nexport const cacheResponseHook: IORedisResponseCustomAttributeFunction = (\n span: Span,\n redisCommand: string,\n cmdArgs: IORedisCommandArgs,\n response: unknown,\n) => {\n const safeKey = getCacheKeySafely(redisCommand, cmdArgs);\n const cacheOperation = getCacheOperation(redisCommand);\n\n if (\n !safeKey ||\n !cacheOperation ||\n !_redisOptions.cachePrefixes ||\n !shouldConsiderForCache(redisCommand, safeKey, _redisOptions.cachePrefixes)\n ) {\n // not relevant for cache\n return;\n }\n\n // otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199\n // We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/\n // Fall back to stable semconv attributes (server.address/server.port) when\n // old-semconv ones are absent, eg OTEL_SEMCONV_STABILITY_OPT_IN=database\n // set for node-redis v4/v5.\n const spanData = spanToJSON(span).data;\n const networkPeerAddress = spanData['net.peer.name'] ?? spanData['server.address'];\n const networkPeerPort = spanData['net.peer.port'] ?? spanData['server.port'];\n if (networkPeerPort && networkPeerAddress) {\n span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });\n }\n\n const cacheItemSize = calculateCacheItemSize(response);\n\n if (cacheItemSize) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);\n }\n\n if (isInCommands(GET_COMMANDS, redisCommand) && cacheItemSize !== undefined) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);\n }\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,\n [SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey,\n });\n\n // todo: change to string[] once EAP supports it\n const spanDescription = safeKey.join(', ');\n\n span.updateName(\n _redisOptions.maxCacheKeyLength ? truncate(spanDescription, _redisOptions.maxCacheKeyLength) : spanDescription,\n );\n};\n\nconst instrumentIORedis = generateInstrumentOnce(`${INTEGRATION_NAME}.IORedis`, () => {\n return new IORedisInstrumentation({\n responseHook: cacheResponseHook,\n });\n});\n\nconst instrumentRedisModule = generateInstrumentOnce(`${INTEGRATION_NAME}.Redis`, () => {\n return new RedisInstrumentation({\n responseHook: cacheResponseHook,\n });\n});\n\n/** To be able to preload all Redis OTel instrumentations with just one ID (\"Redis\"), all the instrumentations are generated in this one function */\nexport const instrumentRedis = Object.assign(\n (): void => {\n instrumentIORedis();\n instrumentRedisModule();\n // node-redis >= 5.12.0 publishes via diagnostics_channel. The subscriber uses\n // `@sentry/opentelemetry/tracing-channel`, which needs the Sentry OTel context manager\n // to be registered before it can `bindStore`. `initOpenTelemetry()` runs after integration\n // `setupOnce`, so defer to the next tick.\n void Promise.resolve().then(() => subscribeRedisDiagnosticChannels(cacheResponseHook));\n\n // todo: implement them gradually\n // new LegacyRedisInstrumentation({}),\n },\n { id: INTEGRATION_NAME },\n);\n\nconst _redisIntegration = ((options: RedisOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n _redisOptions = options;\n instrumentRedis();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and\n * [ioredis](https://www.npmjs.com/package/ioredis) libraries.\n *\n * For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.redisIntegration()],\n * });\n * ```\n */\nexport const redisIntegration = defineIntegration(_redisIntegration);\n"],"names":["_redisOptions","getCacheKeySafely","getCacheOperation","shouldConsiderForCache","spanToJSON","calculateCacheItemSize","SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE","isInCommands","GET_COMMANDS","SEMANTIC_ATTRIBUTE_CACHE_HIT","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_CACHE_KEY","truncate","generateInstrumentOnce","IORedisInstrumentation","RedisInstrumentation","subscribeRedisDiagnosticChannels","defineIntegration"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const core = require('@sentry/core');
const tracingChannel = require('@sentry/opentelemetry/tracing-channel');
const redisCommon = require('./vendored/redis-common.js');
const semconv = require('./vendored/semconv.js');
// Channel names as published by node-redis >= 5.12.0.
// Hardcoded so we don't import `redis` at module-load time.
const CHANNEL_COMMAND = 'node-redis:command';
const CHANNEL_BATCH = 'node-redis:batch';
const CHANNEL_CONNECT = 'node-redis:connect';
const ORIGIN = 'auto.db.redis.diagnostic_channel';
const NOOP = () => {};
let subscribed = false;
let currentResponseHook;
/**
* Subscribe Sentry handlers to node-redis diagnostics_channel events (>= 5.12.0).
*
* Uses `@sentry/opentelemetry/tracing-channel` so OTel AsyncLocalStorage context propagates
* automatically via `bindStore` — without it, spans created in `start` would not become
* the active context for subsequent operations.
*
* Safe on every runtime that exposes `node:diagnostics_channel` (Node, Bun, Deno, Workers).
* In node-redis < 5.12.0 the channels are never published to, so subscribers are inert and
* there is no double-instrumentation against the IITM-based patcher (gated to < 5.12.0).
*/
function subscribeRedisDiagnosticChannels(responseHook) {
currentResponseHook = responseHook;
if (subscribed) return;
try {
setupCommandChannel();
setupBatchChannel();
setupConnectChannel();
subscribed = true;
} catch {
// tracingChannel from @sentry/opentelemetry requires `node:diagnostics_channel`.
// On runtimes where it isn't available, fail closed.
}
}
function setupCommandChannel() {
const channel = tracingChannel.tracingChannel(CHANNEL_COMMAND, data => {
// node-redis >= 5.12.0 includes the command name as args[0] in the DC payload.
// Strip it so serialization and cache key extraction see only the actual arguments.
const actualArgs = data.args.slice(1);
const statement = safeSerialize(data.command, actualArgs);
return core.startSpanManual(
{
name: `redis-${data.command}`,
attributes: {
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis',
[semconv.ATTR_DB_SYSTEM]: semconv.DB_SYSTEM_VALUE_REDIS,
...(statement != null ? { [semconv.ATTR_DB_STATEMENT]: statement } : {}),
...(data.serverAddress != null ? { [semconv.ATTR_NET_PEER_NAME]: data.serverAddress } : {}),
...(data.serverPort != null ? { [semconv.ATTR_NET_PEER_PORT]: data.serverPort } : {}),
},
},
span => span,
) ;
});
channel.subscribe({
start: NOOP,
asyncStart: NOOP,
end: NOOP,
asyncEnd: data => {
const span = data._sentrySpan;
// only end if error handler isn't going to
if (!span || data.error) return;
// Same slice: strip command name from args before passing to the response hook.
runResponseHook(span, data.command, data.args.slice(1), data.result);
span.end();
},
error: data => {
const span = data._sentrySpan;
if (!span) return;
if (data.error) {
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: data.error.message });
}
span.end();
},
});
}
function setupBatchChannel() {
const channel = tracingChannel.tracingChannel(CHANNEL_BATCH, data => {
const operationName = data.batchMode === 'PIPELINE' ? 'PIPELINE' : 'MULTI';
return core.startSpanManual(
{
name: operationName,
attributes: {
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis',
[semconv.ATTR_DB_SYSTEM]: semconv.DB_SYSTEM_VALUE_REDIS,
...(data.batchSize != null ? { 'db.redis.batch_size': data.batchSize } : {}),
...(data.serverAddress != null ? { [semconv.ATTR_NET_PEER_NAME]: data.serverAddress } : {}),
...(data.serverPort != null ? { [semconv.ATTR_NET_PEER_PORT]: data.serverPort } : {}),
},
},
span => span,
) ;
});
channel.subscribe({
start: NOOP,
asyncStart: NOOP,
end: NOOP,
asyncEnd: data => {
// only end if the error handler isn't going to
if (!data.error) data._sentrySpan?.end();
},
error: data => {
const span = data._sentrySpan;
if (!span) return;
if (data.error) {
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: data.error.message });
}
span.end();
},
});
}
function setupConnectChannel() {
const channel = tracingChannel.tracingChannel(CHANNEL_CONNECT, data => {
return core.startSpanManual(
{
name: 'redis-connect',
attributes: {
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis.connect',
[semconv.ATTR_DB_SYSTEM]: semconv.DB_SYSTEM_VALUE_REDIS,
...(data.serverAddress != null ? { [semconv.ATTR_NET_PEER_NAME]: data.serverAddress } : {}),
...(data.serverPort != null ? { [semconv.ATTR_NET_PEER_PORT]: data.serverPort } : {}),
},
},
span => span,
) ;
});
channel.subscribe({
start: NOOP,
asyncStart: NOOP,
end: NOOP,
asyncEnd: data => {
// only end if the error handler isn't going to
if (!data.error) data._sentrySpan?.end();
},
error: data => {
const span = data._sentrySpan;
if (!span) return;
if (data.error) {
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: data.error.message });
}
span.end();
},
});
}
function runResponseHook(span, command, args, result) {
const hook = currentResponseHook;
if (!hook) return;
try {
hook(span, command, args , result);
} catch {
// never let user hooks break instrumentation
}
}
function safeSerialize(command, args) {
try {
return redisCommon.defaultDbStatementSerializer(command, args);
} catch {
return undefined;
}
}
exports.subscribeRedisDiagnosticChannels = subscribeRedisDiagnosticChannels;
//# sourceMappingURL=redis-dc-subscriber.js.map
{"version":3,"file":"redis-dc-subscriber.js","sources":["../../../../../src/integrations/tracing/redis/redis-dc-subscriber.ts"],"sourcesContent":["import type { Span } from '@opentelemetry/api';\nimport {\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n startSpanManual,\n} from '@sentry/core';\nimport { tracingChannel, type TracingChannelContextWithSpan } from '@sentry/opentelemetry/tracing-channel';\nimport { defaultDbStatementSerializer } from './vendored/redis-common';\nimport {\n ATTR_DB_STATEMENT,\n ATTR_DB_SYSTEM,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n DB_SYSTEM_VALUE_REDIS,\n} from './vendored/semconv';\nimport type { IORedisInstrumentationConfig } from './vendored/types';\n\n// Channel names as published by node-redis >= 5.12.0.\n// Hardcoded so we don't import `redis` at module-load time.\nconst CHANNEL_COMMAND = 'node-redis:command';\nconst CHANNEL_BATCH = 'node-redis:batch';\nconst CHANNEL_CONNECT = 'node-redis:connect';\n\nconst ORIGIN = 'auto.db.redis.diagnostic_channel';\n\ninterface CommandData {\n command: string;\n args: Array<string | Buffer>;\n database?: number;\n serverAddress?: string;\n serverPort?: number;\n result?: unknown;\n error?: Error;\n}\n\ninterface BatchData {\n batchMode?: 'MULTI' | 'PIPELINE';\n batchSize?: number;\n database?: number;\n clientId?: string | number;\n serverAddress?: string;\n serverPort?: number;\n result?: unknown[];\n error?: Error;\n}\n\ninterface ConnectData {\n serverAddress?: string;\n serverPort?: number;\n url?: string;\n error?: Error;\n}\n\nconst NOOP = (): void => {};\n\nlet subscribed = false;\nlet currentResponseHook: IORedisInstrumentationConfig['responseHook'] | undefined;\n\n/**\n * Subscribe Sentry handlers to node-redis diagnostics_channel events (>= 5.12.0).\n *\n * Uses `@sentry/opentelemetry/tracing-channel` so OTel AsyncLocalStorage context propagates\n * automatically via `bindStore` — without it, spans created in `start` would not become\n * the active context for subsequent operations.\n *\n * Safe on every runtime that exposes `node:diagnostics_channel` (Node, Bun, Deno, Workers).\n * In node-redis < 5.12.0 the channels are never published to, so subscribers are inert and\n * there is no double-instrumentation against the IITM-based patcher (gated to < 5.12.0).\n */\nexport function subscribeRedisDiagnosticChannels(responseHook?: IORedisInstrumentationConfig['responseHook']): void {\n currentResponseHook = responseHook;\n if (subscribed) return;\n\n try {\n setupCommandChannel();\n setupBatchChannel();\n setupConnectChannel();\n subscribed = true;\n } catch {\n // tracingChannel from @sentry/opentelemetry requires `node:diagnostics_channel`.\n // On runtimes where it isn't available, fail closed.\n }\n}\n\nfunction setupCommandChannel(): void {\n const channel = tracingChannel<CommandData>(CHANNEL_COMMAND, data => {\n // node-redis >= 5.12.0 includes the command name as args[0] in the DC payload.\n // Strip it so serialization and cache key extraction see only the actual arguments.\n const actualArgs = data.args.slice(1);\n const statement = safeSerialize(data.command, actualArgs);\n return startSpanManual(\n {\n name: `redis-${data.command}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis',\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n ...(statement != null ? { [ATTR_DB_STATEMENT]: statement } : {}),\n ...(data.serverAddress != null ? { [ATTR_NET_PEER_NAME]: data.serverAddress } : {}),\n ...(data.serverPort != null ? { [ATTR_NET_PEER_PORT]: data.serverPort } : {}),\n },\n },\n span => span,\n ) as Span;\n });\n\n channel.subscribe({\n start: NOOP,\n asyncStart: NOOP,\n end: NOOP,\n asyncEnd: data => {\n const span = data._sentrySpan;\n // only end if error handler isn't going to\n if (!span || data.error) return;\n // Same slice: strip command name from args before passing to the response hook.\n runResponseHook(span, data.command, data.args.slice(1), data.result);\n span.end();\n },\n error: data => {\n const span = data._sentrySpan;\n if (!span) return;\n if (data.error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: data.error.message });\n }\n span.end();\n },\n });\n}\n\nfunction setupBatchChannel(): void {\n const channel = tracingChannel<BatchData>(CHANNEL_BATCH, data => {\n const operationName = data.batchMode === 'PIPELINE' ? 'PIPELINE' : 'MULTI';\n\n return startSpanManual(\n {\n name: operationName,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis',\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n ...(data.batchSize != null ? { 'db.redis.batch_size': data.batchSize } : {}),\n ...(data.serverAddress != null ? { [ATTR_NET_PEER_NAME]: data.serverAddress } : {}),\n ...(data.serverPort != null ? { [ATTR_NET_PEER_PORT]: data.serverPort } : {}),\n },\n },\n span => span,\n ) as Span;\n });\n\n channel.subscribe({\n start: NOOP,\n asyncStart: NOOP,\n end: NOOP,\n asyncEnd: data => {\n // only end if the error handler isn't going to\n if (!data.error) data._sentrySpan?.end();\n },\n error: data => {\n const span = data._sentrySpan;\n if (!span) return;\n if (data.error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: data.error.message });\n }\n span.end();\n },\n });\n}\n\nfunction setupConnectChannel(): void {\n const channel = tracingChannel<ConnectData>(CHANNEL_CONNECT, data => {\n return startSpanManual(\n {\n name: 'redis-connect',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis.connect',\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n ...(data.serverAddress != null ? { [ATTR_NET_PEER_NAME]: data.serverAddress } : {}),\n ...(data.serverPort != null ? { [ATTR_NET_PEER_PORT]: data.serverPort } : {}),\n },\n },\n span => span,\n ) as Span;\n });\n\n channel.subscribe({\n start: NOOP,\n asyncStart: NOOP,\n end: NOOP,\n asyncEnd: data => {\n // only end if the error handler isn't going to\n if (!data.error) data._sentrySpan?.end();\n },\n error: data => {\n const span = data._sentrySpan;\n if (!span) return;\n if (data.error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: data.error.message });\n }\n span.end();\n },\n });\n}\n\nfunction runResponseHook(span: Span, command: string, args: Array<string | Buffer>, result: unknown): void {\n const hook = currentResponseHook;\n if (!hook) return;\n try {\n hook(span, command, args as unknown as Parameters<typeof hook>[2], result);\n } catch {\n // never let user hooks break instrumentation\n }\n}\n\nfunction safeSerialize(command: string, args: Array<string | Buffer>): string | undefined {\n try {\n return defaultDbStatementSerializer(command, args);\n } catch {\n return undefined;\n }\n}\n\n// Test-only helper.\nexport function _resetRedisDiagnosticChannelsForTesting(): void {\n subscribed = false;\n currentResponseHook = undefined;\n}\n\n// Suppress unused-import lint when only used in types.\nexport type { TracingChannelContextWithSpan };\n"],"names":["tracingChannel","startSpanManual","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_OP","ATTR_DB_SYSTEM","DB_SYSTEM_VALUE_REDIS","ATTR_DB_STATEMENT","ATTR_NET_PEER_NAME","ATTR_NET_PEER_PORT","SPAN_STATUS_ERROR","defaultDbStatementSerializer"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const api = require('@opentelemetry/api');
const core = require('@sentry/core');
const instrumentation = require('@opentelemetry/instrumentation');
const semanticConventions = require('@opentelemetry/semantic-conventions');
const redisCommon = require('./redis-common.js');
const semconv = require('./semconv.js');
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE from the Sentry authors:
* - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-ioredis-v0.62.0/packages/instrumentation-ioredis
* - Upstream version: @opentelemetry/instrumentation-ioredis@0.62.0
* - Minor TypeScript adjustments for this repository's compiler settings
*/
/* eslint-disable -- vendored @opentelemetry/instrumentation-ioredis */
const PACKAGE_NAME = '@opentelemetry/instrumentation-ioredis';
const PACKAGE_VERSION = '0.62.0';
// ---- utils ----
function endSpan(span, err) {
if (err) {
span.recordException(err);
span.setStatus({
code: api.SpanStatusCode.ERROR,
message: err.message,
});
}
span.end();
}
// ---- IORedisInstrumentation ----
const DEFAULT_CONFIG = {
requireParentSpan: true,
};
class IORedisInstrumentation extends instrumentation.InstrumentationBase {
constructor(config = {}) {
super(PACKAGE_NAME, PACKAGE_VERSION, { ...DEFAULT_CONFIG, ...config });
this._setSemconvStabilityFromEnv();
}
_setSemconvStabilityFromEnv() {
this._netSemconvStability = instrumentation.semconvStabilityFromStr('http', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
this._dbSemconvStability = instrumentation.semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
setConfig(config = {}) {
super.setConfig({ ...DEFAULT_CONFIG, ...config });
}
init() {
return [
new instrumentation.InstrumentationNodeModuleDefinition(
'ioredis',
['>=2.0.0 <6'],
(module, moduleVersion) => {
const moduleExports =
module[Symbol.toStringTag] === 'Module'
? module.default // ESM
: module; // CommonJS
if (instrumentation.isWrapped(moduleExports.prototype.sendCommand)) {
this._unwrap(moduleExports.prototype, 'sendCommand');
}
this._wrap(moduleExports.prototype, 'sendCommand', this._patchSendCommand(moduleVersion));
if (instrumentation.isWrapped(moduleExports.prototype.connect)) {
this._unwrap(moduleExports.prototype, 'connect');
}
this._wrap(moduleExports.prototype, 'connect', this._patchConnection());
return module;
},
(module) => {
if (module === undefined) return;
const moduleExports =
module[Symbol.toStringTag] === 'Module'
? module.default // ESM
: module; // CommonJS
this._unwrap(moduleExports.prototype, 'sendCommand');
this._unwrap(moduleExports.prototype, 'connect');
},
),
];
}
_patchSendCommand(moduleVersion) {
return (original) => {
return this._traceSendCommand(original, moduleVersion);
};
}
_patchConnection() {
return (original) => {
return this._traceConnection(original);
};
}
_traceSendCommand(original, moduleVersion) {
const instrumentation$1 = this;
return function ( cmd) {
if (arguments.length < 1 || typeof cmd !== 'object') {
return original.apply(this, arguments);
}
const config = instrumentation$1.getConfig();
const dbStatementSerializer = config.dbStatementSerializer || redisCommon.defaultDbStatementSerializer;
const hasNoParentSpan = api.trace.getSpan(api.context.active()) === undefined;
if (config.requireParentSpan === true && hasNoParentSpan) {
return original.apply(this, arguments);
}
const attributes = {};
const { host, port } = this.options;
const dbQueryText = dbStatementSerializer(cmd.name, cmd.args);
if (instrumentation$1._dbSemconvStability & instrumentation.SemconvStability.OLD) {
attributes[semconv.ATTR_DB_SYSTEM] = semconv.DB_SYSTEM_VALUE_REDIS;
attributes[semconv.ATTR_DB_STATEMENT] = dbQueryText;
attributes[semconv.ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;
}
if (instrumentation$1._dbSemconvStability & instrumentation.SemconvStability.STABLE) {
attributes[semanticConventions.ATTR_DB_SYSTEM_NAME] = semconv.DB_SYSTEM_NAME_VALUE_REDIS;
attributes[semanticConventions.ATTR_DB_QUERY_TEXT] = dbQueryText;
}
if (instrumentation$1._netSemconvStability & instrumentation.SemconvStability.OLD) {
attributes[semconv.ATTR_NET_PEER_NAME] = host;
attributes[semconv.ATTR_NET_PEER_PORT] = port;
}
if (instrumentation$1._netSemconvStability & instrumentation.SemconvStability.STABLE) {
attributes[semanticConventions.ATTR_SERVER_ADDRESS] = host;
attributes[semanticConventions.ATTR_SERVER_PORT] = port;
}
attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = instrumentation$1.tracer.startSpan(cmd.name, {
kind: api.SpanKind.CLIENT,
attributes,
});
const { requestHook } = config;
if (requestHook) {
instrumentation.safeExecuteInTheMiddle(
() =>
requestHook(span, {
moduleVersion,
cmdName: cmd.name,
cmdArgs: cmd.args,
}),
(e) => {
if (e) {
api.diag.error('ioredis instrumentation: request hook failed', e);
}
},
true,
);
}
try {
const result = original.apply(this, arguments);
const origResolve = cmd.resolve;
cmd.resolve = function (result) {
instrumentation.safeExecuteInTheMiddle(
() => config.responseHook?.(span, cmd.name, cmd.args, result),
(e) => {
if (e) {
api.diag.error('ioredis instrumentation: response hook failed', e);
}
},
true,
);
endSpan(span, null);
origResolve(result);
};
const origReject = cmd.reject;
cmd.reject = function (err) {
endSpan(span, err);
origReject(err);
};
return result;
} catch (error) {
endSpan(span, error );
throw error;
}
};
}
_traceConnection(original) {
const instrumentation$1 = this;
return function () {
const hasNoParentSpan = api.trace.getSpan(api.context.active()) === undefined;
if (instrumentation$1.getConfig().requireParentSpan === true && hasNoParentSpan) {
return original.apply(this, arguments);
}
const attributes = {};
const { host, port } = this.options;
if (instrumentation$1._dbSemconvStability & instrumentation.SemconvStability.OLD) {
attributes[semconv.ATTR_DB_SYSTEM] = semconv.DB_SYSTEM_VALUE_REDIS;
attributes[semconv.ATTR_DB_STATEMENT] = 'connect';
attributes[semconv.ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;
}
if (instrumentation$1._dbSemconvStability & instrumentation.SemconvStability.STABLE) {
attributes[semanticConventions.ATTR_DB_SYSTEM_NAME] = semconv.DB_SYSTEM_NAME_VALUE_REDIS;
attributes[semanticConventions.ATTR_DB_QUERY_TEXT] = 'connect';
}
if (instrumentation$1._netSemconvStability & instrumentation.SemconvStability.OLD) {
attributes[semconv.ATTR_NET_PEER_NAME] = host;
attributes[semconv.ATTR_NET_PEER_PORT] = port;
}
if (instrumentation$1._netSemconvStability & instrumentation.SemconvStability.STABLE) {
attributes[semanticConventions.ATTR_SERVER_ADDRESS] = host;
attributes[semanticConventions.ATTR_SERVER_PORT] = port;
}
attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = instrumentation$1.tracer.startSpan('connect', {
kind: api.SpanKind.CLIENT,
attributes,
});
try {
const result = original.apply(this, arguments);
if (typeof result?.then === 'function') {
return result.then(
(value) => {
endSpan(span, null);
return value;
},
(error) => {
endSpan(span, error);
return Promise.reject(error);
},
);
}
endSpan(span, null);
return result;
} catch (error) {
endSpan(span, error );
throw error;
}
};
}
}
exports.IORedisInstrumentation = IORedisInstrumentation;
//# sourceMappingURL=ioredis-instrumentation.js.map
{"version":3,"file":"ioredis-instrumentation.js","sources":["../../../../../../src/integrations/tracing/redis/vendored/ioredis-instrumentation.ts"],"sourcesContent":["/*\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 * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-ioredis-v0.62.0/packages/instrumentation-ioredis\n * - Upstream version: @opentelemetry/instrumentation-ioredis@0.62.0\n * - Minor TypeScript adjustments for this repository's compiler settings\n */\n/* eslint-disable -- vendored @opentelemetry/instrumentation-ioredis */\n\nimport { context, diag, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';\nimport type { Span } from '@opentelemetry/api';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n isWrapped,\n safeExecuteInTheMiddle,\n SemconvStability,\n semconvStabilityFromStr,\n} from '@opentelemetry/instrumentation';\nimport {\n ATTR_DB_QUERY_TEXT,\n ATTR_DB_SYSTEM_NAME,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n} from '@opentelemetry/semantic-conventions';\n\nimport { defaultDbStatementSerializer } from './redis-common';\nimport {\n ATTR_DB_CONNECTION_STRING,\n ATTR_DB_STATEMENT,\n ATTR_DB_SYSTEM,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n DB_SYSTEM_NAME_VALUE_REDIS,\n DB_SYSTEM_VALUE_REDIS,\n} from './semconv';\nimport type { IORedisInstrumentationConfig } from './types';\n\nconst PACKAGE_NAME = '@opentelemetry/instrumentation-ioredis';\nconst PACKAGE_VERSION = '0.62.0';\n\n// ---- utils ----\n\nfunction endSpan(span: Span, err: Error | null | undefined): void {\n if (err) {\n span.recordException(err);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message,\n });\n }\n span.end();\n}\n\n// ---- IORedisInstrumentation ----\n\nconst DEFAULT_CONFIG: IORedisInstrumentationConfig = {\n requireParentSpan: true,\n};\n\nexport class IORedisInstrumentation extends InstrumentationBase<IORedisInstrumentationConfig> {\n _netSemconvStability!: SemconvStability;\n _dbSemconvStability!: SemconvStability;\n\n constructor(config: IORedisInstrumentationConfig = {}) {\n super(PACKAGE_NAME, PACKAGE_VERSION, { ...DEFAULT_CONFIG, ...config });\n this._setSemconvStabilityFromEnv();\n }\n\n _setSemconvStabilityFromEnv(): void {\n this._netSemconvStability = semconvStabilityFromStr('http', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n this._dbSemconvStability = semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n override setConfig(config: IORedisInstrumentationConfig = {}): void {\n super.setConfig({ ...DEFAULT_CONFIG, ...config });\n }\n\n init() {\n return [\n new InstrumentationNodeModuleDefinition(\n 'ioredis',\n ['>=2.0.0 <6'],\n (module: any, moduleVersion?: string) => {\n const moduleExports =\n module[Symbol.toStringTag] === 'Module'\n ? module.default // ESM\n : module; // CommonJS\n if (isWrapped(moduleExports.prototype.sendCommand)) {\n this._unwrap(moduleExports.prototype, 'sendCommand');\n }\n this._wrap(moduleExports.prototype, 'sendCommand', this._patchSendCommand(moduleVersion));\n if (isWrapped(moduleExports.prototype.connect)) {\n this._unwrap(moduleExports.prototype, 'connect');\n }\n this._wrap(moduleExports.prototype, 'connect', this._patchConnection());\n return module;\n },\n (module: any) => {\n if (module === undefined) return;\n const moduleExports =\n module[Symbol.toStringTag] === 'Module'\n ? module.default // ESM\n : module; // CommonJS\n this._unwrap(moduleExports.prototype, 'sendCommand');\n this._unwrap(moduleExports.prototype, 'connect');\n },\n ),\n ];\n }\n\n private _patchSendCommand(moduleVersion?: string) {\n return (original: Function) => {\n return this._traceSendCommand(original, moduleVersion);\n };\n }\n\n private _patchConnection() {\n return (original: Function) => {\n return this._traceConnection(original);\n };\n }\n\n private _traceSendCommand(original: Function, moduleVersion?: string) {\n const instrumentation = this;\n return function (this: any, cmd: any) {\n if (arguments.length < 1 || typeof cmd !== 'object') {\n return original.apply(this, arguments);\n }\n const config = instrumentation.getConfig();\n const dbStatementSerializer = config.dbStatementSerializer || defaultDbStatementSerializer;\n const hasNoParentSpan = trace.getSpan(context.active()) === undefined;\n if (config.requireParentSpan === true && hasNoParentSpan) {\n return original.apply(this, arguments);\n }\n const attributes: Record<string, any> = {};\n const { host, port } = this.options;\n const dbQueryText = dbStatementSerializer(cmd.name, cmd.args);\n if (instrumentation._dbSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_REDIS;\n attributes[ATTR_DB_STATEMENT] = dbQueryText;\n attributes[ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;\n }\n if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {\n attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_REDIS;\n attributes[ATTR_DB_QUERY_TEXT] = dbQueryText;\n }\n if (instrumentation._netSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_NET_PEER_NAME] = host;\n attributes[ATTR_NET_PEER_PORT] = port;\n }\n if (instrumentation._netSemconvStability & SemconvStability.STABLE) {\n attributes[ATTR_SERVER_ADDRESS] = host;\n attributes[ATTR_SERVER_PORT] = port;\n }\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = instrumentation.tracer.startSpan(cmd.name, {\n kind: SpanKind.CLIENT,\n attributes,\n });\n const { requestHook } = config;\n if (requestHook) {\n safeExecuteInTheMiddle(\n () =>\n requestHook(span, {\n moduleVersion,\n cmdName: cmd.name,\n cmdArgs: cmd.args,\n }),\n (e: Error | undefined) => {\n if (e) {\n diag.error('ioredis instrumentation: request hook failed', e);\n }\n },\n true,\n );\n }\n try {\n const result = original.apply(this, arguments);\n const origResolve = cmd.resolve;\n cmd.resolve = function (result: unknown) {\n safeExecuteInTheMiddle(\n () => config.responseHook?.(span, cmd.name, cmd.args, result),\n (e: Error | undefined) => {\n if (e) {\n diag.error('ioredis instrumentation: response hook failed', e);\n }\n },\n true,\n );\n endSpan(span, null);\n origResolve(result);\n };\n const origReject = cmd.reject;\n cmd.reject = function (err: Error) {\n endSpan(span, err);\n origReject(err);\n };\n return result;\n } catch (error) {\n endSpan(span, error as Error);\n throw error;\n }\n };\n }\n\n private _traceConnection(original: Function) {\n const instrumentation = this;\n return function (this: any) {\n const hasNoParentSpan = trace.getSpan(context.active()) === undefined;\n if (instrumentation.getConfig().requireParentSpan === true && hasNoParentSpan) {\n return original.apply(this, arguments);\n }\n const attributes: Record<string, any> = {};\n const { host, port } = this.options;\n if (instrumentation._dbSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_REDIS;\n attributes[ATTR_DB_STATEMENT] = 'connect';\n attributes[ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;\n }\n if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {\n attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_REDIS;\n attributes[ATTR_DB_QUERY_TEXT] = 'connect';\n }\n if (instrumentation._netSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_NET_PEER_NAME] = host;\n attributes[ATTR_NET_PEER_PORT] = port;\n }\n if (instrumentation._netSemconvStability & SemconvStability.STABLE) {\n attributes[ATTR_SERVER_ADDRESS] = host;\n attributes[ATTR_SERVER_PORT] = port;\n }\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = instrumentation.tracer.startSpan('connect', {\n kind: SpanKind.CLIENT,\n attributes,\n });\n try {\n const result = original.apply(this, arguments);\n if (typeof result?.then === 'function') {\n return result.then(\n (value: unknown) => {\n endSpan(span, null);\n return value;\n },\n (error: Error) => {\n endSpan(span, error);\n return Promise.reject(error);\n },\n );\n }\n endSpan(span, null);\n return result;\n } catch (error) {\n endSpan(span, error as Error);\n throw error;\n }\n };\n }\n}\n"],"names":["SpanStatusCode","InstrumentationBase","semconvStabilityFromStr","InstrumentationNodeModuleDefinition","isWrapped","instrumentation","defaultDbStatementSerializer","trace","context","SemconvStability","ATTR_DB_SYSTEM","DB_SYSTEM_VALUE_REDIS","ATTR_DB_STATEMENT","ATTR_DB_CONNECTION_STRING","ATTR_DB_SYSTEM_NAME","DB_SYSTEM_NAME_VALUE_REDIS","ATTR_DB_QUERY_TEXT","ATTR_NET_PEER_NAME","ATTR_NET_PEER_PORT","ATTR_SERVER_ADDRESS","ATTR_SERVER_PORT","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SpanKind","safeExecuteInTheMiddle","diag"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE from the Sentry authors:
* - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/redis-common
* - Upstream version: @opentelemetry/redis-common@0.38.2
* - Minor TypeScript adjustments for this repository's compiler settings
*/
/* eslint-disable -- vendored @opentelemetry/redis-common */
/**
* List of regexes and the number of arguments that should be serialized for matching commands.
* For example, HSET should serialize which key and field it's operating on, but not its value.
* Setting the subset to -1 will serialize all arguments.
* Commands without a match will have their first argument serialized.
*
* Refer to https://redis.io/commands/ for the full list.
*/
const serializationSubsets = [
{
regex: /^ECHO/i,
args: 0,
},
{
regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i,
args: 1,
},
{
regex: /^(HSET|HMSET|LSET|LINSERT)/i,
args: 2,
},
{
regex:
/^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i,
args: -1,
},
];
/**
* Given the redis command name and arguments, return a combination of the
* command name + the allowed arguments according to `serializationSubsets`.
*/
const defaultDbStatementSerializer = (
cmdName,
cmdArgs,
) => {
if (Array.isArray(cmdArgs) && cmdArgs.length) {
const nArgsToSerialize = serializationSubsets.find(({ regex }) => regex.test(cmdName))?.args ?? 0;
const argsToSerialize =
nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs.slice();
if (cmdArgs.length > argsToSerialize.length) {
argsToSerialize.push(`[${cmdArgs.length - nArgsToSerialize} other arguments]`);
}
return `${cmdName} ${argsToSerialize.join(' ')}`;
}
return cmdName;
};
exports.defaultDbStatementSerializer = defaultDbStatementSerializer;
//# sourceMappingURL=redis-common.js.map
{"version":3,"file":"redis-common.js","sources":["../../../../../../src/integrations/tracing/redis/vendored/redis-common.ts"],"sourcesContent":["/*\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 * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/redis-common\n * - Upstream version: @opentelemetry/redis-common@0.38.2\n * - Minor TypeScript adjustments for this repository's compiler settings\n */\n/* eslint-disable -- vendored @opentelemetry/redis-common */\n\n/**\n * List of regexes and the number of arguments that should be serialized for matching commands.\n * For example, HSET should serialize which key and field it's operating on, but not its value.\n * Setting the subset to -1 will serialize all arguments.\n * Commands without a match will have their first argument serialized.\n *\n * Refer to https://redis.io/commands/ for the full list.\n */\nconst serializationSubsets = [\n {\n regex: /^ECHO/i,\n args: 0,\n },\n {\n regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i,\n args: 1,\n },\n {\n regex: /^(HSET|HMSET|LSET|LINSERT)/i,\n args: 2,\n },\n {\n regex:\n /^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i,\n args: -1,\n },\n];\n\n/**\n * Given the redis command name and arguments, return a combination of the\n * command name + the allowed arguments according to `serializationSubsets`.\n */\nexport const defaultDbStatementSerializer = (\n cmdName: string,\n cmdArgs: Array<string | Buffer | number | any[]>,\n): string => {\n if (Array.isArray(cmdArgs) && cmdArgs.length) {\n const nArgsToSerialize = serializationSubsets.find(({ regex }) => regex.test(cmdName))?.args ?? 0;\n const argsToSerialize: Array<string | Buffer | number | any[]> =\n nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs.slice();\n if (cmdArgs.length > argsToSerialize.length) {\n argsToSerialize.push(`[${cmdArgs.length - nArgsToSerialize} other arguments]`);\n }\n return `${cmdName} ${argsToSerialize.join(' ')}`;\n }\n return cmdName;\n};\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,uBAAuB;AAC7B,EAAE;AACF,IAAI,KAAK,EAAE,QAAQ;AACnB,IAAI,IAAI,EAAE,CAAC;AACX,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,8DAA8D;AACzE,IAAI,IAAI,EAAE,CAAC;AACX,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,6BAA6B;AACxC,IAAI,IAAI,EAAE,CAAC;AACX,GAAG;AACH,EAAE;AACF,IAAI,KAAK;AACT,MAAM,kLAAkL;AACxL,IAAI,IAAI,EAAE,EAAE;AACZ,GAAG;AACH,CAAC;;AAED;AACA;AACA;AACA;AACO,MAAM,+BAA+B;AAC5C,EAAE,OAAO;AACT,EAAE,OAAO;AACT,KAAa;AACb,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAA,IAAK,OAAO,CAAC,MAAM,EAAE;AAChD,IAAI,MAAM,mBAAmB,oBAAoB,CAAC,IAAI,CAAC,CAAC,EAAE,KAAA,EAAO,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,IAAA,IAAQ,CAAC;AACrG,IAAI,MAAM,eAAe;AACzB,MAAM,oBAAoB,CAAA,GAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAA,GAAI,OAAO,CAAC,KAAK,EAAE;AAClF,IAAI,IAAI,OAAO,CAAC,SAAS,eAAe,CAAC,MAAM,EAAE;AACjD,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;AACpF,IAAI;AACJ,IAAI,OAAO,CAAC,EAAA,OAAA,CAAA,CAAA,EAAA,eAAA,CAAA,IAAA,CAAA,GAAA,CAAA,CAAA,CAAA;AACA,EAAA;AACA,EAAA,OAAA,OAAA;AACA;;;;"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const api = require('@opentelemetry/api');
const core = require('@sentry/core');
const instrumentation = require('@opentelemetry/instrumentation');
const semanticConventions = require('@opentelemetry/semantic-conventions');
const redisCommon = require('./redis-common.js');
const semconv = require('./semconv.js');
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE from the Sentry authors:
* - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/instrumentation-redis
* - Upstream version: @opentelemetry/instrumentation-redis@0.62.0
* - Minor TypeScript adjustments for this repository's compiler settings
*/
/* eslint-disable -- vendored @opentelemetry/instrumentation-redis */
const PACKAGE_NAME = '@opentelemetry/instrumentation-redis';
const PACKAGE_VERSION = '0.62.0';
// ---- Internal types ----
const OTEL_OPEN_SPANS = Symbol('opentelemetry.instrumentation.redis.open_spans');
const MULTI_COMMAND_OPTIONS = Symbol('opentelemetry.instrumentation.redis.multi_command_options');
// ---- v4-v5 utils ----
function removeCredentialsFromDBConnectionStringAttribute(
diagLogger,
url,
) {
if (typeof url !== 'string' || !url) {
return undefined;
}
try {
const u = new URL(url);
u.searchParams.delete('user_pwd');
u.username = '';
u.password = '';
return u.href;
} catch (err) {
diagLogger.error('failed to sanitize redis connection url', err);
}
return undefined;
}
function getClientAttributes(
diagLogger,
options,
semconvStability,
) {
const attributes = {};
if (semconvStability & instrumentation.SemconvStability.OLD) {
Object.assign(attributes, {
[semconv.ATTR_DB_SYSTEM]: semconv.DB_SYSTEM_VALUE_REDIS,
[semconv.ATTR_NET_PEER_NAME]: options?.socket?.host,
[semconv.ATTR_NET_PEER_PORT]: options?.socket?.port,
[semconv.ATTR_DB_CONNECTION_STRING]: removeCredentialsFromDBConnectionStringAttribute(diagLogger, options?.url),
});
}
if (semconvStability & instrumentation.SemconvStability.STABLE) {
Object.assign(attributes, {
[semanticConventions.ATTR_DB_SYSTEM_NAME]: semconv.DB_SYSTEM_NAME_VALUE_REDIS,
[semanticConventions.ATTR_SERVER_ADDRESS]: options?.socket?.host,
[semanticConventions.ATTR_SERVER_PORT]: options?.socket?.port,
});
}
return attributes;
}
// ---- v2-v3 utils ----
function endSpanV2(span, err) {
if (err) {
span.setStatus({
code: api.SpanStatusCode.ERROR,
message: err.message,
});
}
span.end();
}
function getTracedCreateClient(original) {
return function createClientTrace() {
const client = original.apply(this, arguments);
return api.context.bind(api.context.active(), client);
};
}
function getTracedCreateStreamTrace(original) {
return function create_stream_trace() {
if (!Object.prototype.hasOwnProperty.call(this, 'stream')) {
Object.defineProperty(this, 'stream', {
get() {
return this._patched_redis_stream;
},
set(val) {
api.context.bind(api.context.active(), val);
this._patched_redis_stream = val;
},
});
}
return original.apply(this, arguments);
};
}
// ---- RedisInstrumentationV2_V3 ----
class RedisInstrumentationV2_V3 extends instrumentation.InstrumentationBase {
static __initStatic() {this.COMPONENT = 'redis';}
constructor(config = {}) {
super(PACKAGE_NAME, PACKAGE_VERSION, config);
this._semconvStability = config.semconvStability
? config.semconvStability
: instrumentation.semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
setConfig(config = {}) {
super.setConfig(config);
this._semconvStability = config.semconvStability
? config.semconvStability
: instrumentation.semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
init() {
return [
new instrumentation.InstrumentationNodeModuleDefinition(
'redis',
['>=2.6.0 <4'],
(moduleExports) => {
if (instrumentation.isWrapped(moduleExports.RedisClient.prototype['internal_send_command'])) {
this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');
}
this._wrap(moduleExports.RedisClient.prototype, 'internal_send_command', this._getPatchInternalSendCommand());
if (instrumentation.isWrapped(moduleExports.RedisClient.prototype['create_stream'])) {
this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');
}
this._wrap(moduleExports.RedisClient.prototype, 'create_stream', this._getPatchCreateStream());
if (instrumentation.isWrapped(moduleExports.createClient)) {
this._unwrap(moduleExports, 'createClient');
}
this._wrap(moduleExports, 'createClient', this._getPatchCreateClient());
return moduleExports;
},
(moduleExports) => {
if (moduleExports === undefined) return;
this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');
this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');
this._unwrap(moduleExports, 'createClient');
},
),
];
}
_getPatchInternalSendCommand() {
const instrumentation$1 = this;
return function internal_send_command(original) {
return function internal_send_command_trace( cmd) {
if (arguments.length !== 1 || typeof cmd !== 'object') {
return original.apply(this, arguments);
}
const config = instrumentation$1.getConfig();
const hasNoParentSpan = api.trace.getSpan(api.context.active()) === undefined;
if (config.requireParentSpan === true && hasNoParentSpan) {
return original.apply(this, arguments);
}
const dbStatementSerializer = config?.dbStatementSerializer || redisCommon.defaultDbStatementSerializer;
const attributes = {};
if (instrumentation$1._semconvStability & instrumentation.SemconvStability.OLD) {
Object.assign(attributes, {
[semconv.ATTR_DB_SYSTEM]: semconv.DB_SYSTEM_VALUE_REDIS,
[semconv.ATTR_DB_STATEMENT]: dbStatementSerializer(cmd.command, cmd.args),
});
}
if (instrumentation$1._semconvStability & instrumentation.SemconvStability.STABLE) {
Object.assign(attributes, {
[semanticConventions.ATTR_DB_SYSTEM_NAME]: semconv.DB_SYSTEM_NAME_VALUE_REDIS,
[semanticConventions.ATTR_DB_OPERATION_NAME]: cmd.command,
[semanticConventions.ATTR_DB_QUERY_TEXT]: dbStatementSerializer(cmd.command, cmd.args),
});
}
attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = instrumentation$1.tracer.startSpan(`${RedisInstrumentationV2_V3.COMPONENT}-${cmd.command}`, {
kind: api.SpanKind.CLIENT,
attributes,
});
if (this.connection_options) {
const connectionAttributes = {};
if (instrumentation$1._semconvStability & instrumentation.SemconvStability.OLD) {
Object.assign(connectionAttributes, {
[semconv.ATTR_NET_PEER_NAME]: this.connection_options.host,
[semconv.ATTR_NET_PEER_PORT]: this.connection_options.port,
});
}
if (instrumentation$1._semconvStability & instrumentation.SemconvStability.STABLE) {
Object.assign(connectionAttributes, {
[semanticConventions.ATTR_SERVER_ADDRESS]: this.connection_options.host,
[semanticConventions.ATTR_SERVER_PORT]: this.connection_options.port,
});
}
span.setAttributes(connectionAttributes);
}
if (this.address && instrumentation$1._semconvStability & instrumentation.SemconvStability.OLD) {
span.setAttribute(semconv.ATTR_DB_CONNECTION_STRING, `redis://${this.address}`);
}
const originalCallback = arguments[0].callback;
if (originalCallback) {
const originalContext = api.context.active();
arguments[0].callback = function callback( err, reply) {
if (config?.responseHook) {
const responseHook = config.responseHook;
instrumentation.safeExecuteInTheMiddle(
() => {
responseHook(span, cmd.command, cmd.args, reply);
},
(e) => {
if (e) {
instrumentation$1._diag.error('Error executing responseHook', e);
}
},
true,
);
}
endSpanV2(span, err);
return api.context.with(originalContext, originalCallback, this, ...arguments);
};
}
try {
return original.apply(this, arguments);
} catch (rethrow) {
endSpanV2(span, rethrow );
throw rethrow;
}
};
};
}
_getPatchCreateClient() {
return function createClient(original) {
return getTracedCreateClient(original);
};
}
_getPatchCreateStream() {
return function createReadStream(original) {
return getTracedCreateStreamTrace(original);
};
}
} RedisInstrumentationV2_V3.__initStatic();
// ---- RedisInstrumentationV4_V5 ----
class RedisInstrumentationV4_V5 extends instrumentation.InstrumentationBase {
static __initStatic2() {this.COMPONENT = 'redis';}
constructor(config = {}) {
super(PACKAGE_NAME, PACKAGE_VERSION, config);
this._semconvStability = config.semconvStability
? config.semconvStability
: instrumentation.semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
setConfig(config = {}) {
super.setConfig(config);
this._semconvStability = config.semconvStability
? config.semconvStability
: instrumentation.semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
init() {
return [
this._getInstrumentationNodeModuleDefinition('@redis/client'),
this._getInstrumentationNodeModuleDefinition('@node-redis/client'),
];
}
_getInstrumentationNodeModuleDefinition(basePackageName) {
const commanderModuleFile = new instrumentation.InstrumentationNodeModuleFile(
`${basePackageName}/dist/lib/commander.js`,
['^1.0.0'],
(moduleExports, moduleVersion) => {
const transformCommandArguments = moduleExports.transformCommandArguments;
if (!transformCommandArguments) {
this._diag.error('internal instrumentation error, missing transformCommandArguments function');
return moduleExports;
}
const functionToPatch = moduleVersion?.startsWith('1.0.') ? 'extendWithCommands' : 'attachCommands';
if (instrumentation.isWrapped(moduleExports?.[functionToPatch])) {
this._unwrap(moduleExports, functionToPatch);
}
this._wrap(moduleExports, functionToPatch, this._getPatchExtendWithCommands(transformCommandArguments));
return moduleExports;
},
(moduleExports) => {
if (instrumentation.isWrapped(moduleExports?.extendWithCommands)) {
this._unwrap(moduleExports, 'extendWithCommands');
}
if (instrumentation.isWrapped(moduleExports?.attachCommands)) {
this._unwrap(moduleExports, 'attachCommands');
}
},
);
const multiCommanderModule = new instrumentation.InstrumentationNodeModuleFile(
`${basePackageName}/dist/lib/client/multi-command.js`,
['^1.0.0', '>=5.0.0 <5.12.0'],
(moduleExports) => {
const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;
if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.exec)) {
this._unwrap(redisClientMultiCommandPrototype, 'exec');
}
this._wrap(redisClientMultiCommandPrototype, 'exec', this._getPatchMultiCommandsExec(false));
if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {
this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');
}
this._wrap(redisClientMultiCommandPrototype, 'execAsPipeline', this._getPatchMultiCommandsExec(true));
if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.addCommand)) {
this._unwrap(redisClientMultiCommandPrototype, 'addCommand');
}
this._wrap(redisClientMultiCommandPrototype, 'addCommand', this._getPatchMultiCommandsAddCommand());
return moduleExports;
},
(moduleExports) => {
const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;
if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.exec)) {
this._unwrap(redisClientMultiCommandPrototype, 'exec');
}
if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {
this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');
}
if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.addCommand)) {
this._unwrap(redisClientMultiCommandPrototype, 'addCommand');
}
},
);
const clientIndexModule = new instrumentation.InstrumentationNodeModuleFile(
`${basePackageName}/dist/lib/client/index.js`,
['^1.0.0', '>=5.0.0 <5.12.0'],
(moduleExports) => {
const redisClientPrototype = moduleExports?.default?.prototype;
if (redisClientPrototype?.multi) {
if (instrumentation.isWrapped(redisClientPrototype?.multi)) {
this._unwrap(redisClientPrototype, 'multi');
}
this._wrap(redisClientPrototype, 'multi', this._getPatchRedisClientMulti());
}
if (redisClientPrototype?.MULTI) {
if (instrumentation.isWrapped(redisClientPrototype?.MULTI)) {
this._unwrap(redisClientPrototype, 'MULTI');
}
this._wrap(redisClientPrototype, 'MULTI', this._getPatchRedisClientMulti());
}
if (instrumentation.isWrapped(redisClientPrototype?.sendCommand)) {
this._unwrap(redisClientPrototype, 'sendCommand');
}
this._wrap(redisClientPrototype, 'sendCommand', this._getPatchRedisClientSendCommand());
if (instrumentation.isWrapped(redisClientPrototype?.connect)) {
this._unwrap(redisClientPrototype, 'connect');
}
this._wrap(redisClientPrototype, 'connect', this._getPatchedClientConnect());
return moduleExports;
},
(moduleExports) => {
const redisClientPrototype = moduleExports?.default?.prototype;
if (instrumentation.isWrapped(redisClientPrototype?.multi)) {
this._unwrap(redisClientPrototype, 'multi');
}
if (instrumentation.isWrapped(redisClientPrototype?.MULTI)) {
this._unwrap(redisClientPrototype, 'MULTI');
}
if (instrumentation.isWrapped(redisClientPrototype?.sendCommand)) {
this._unwrap(redisClientPrototype, 'sendCommand');
}
if (instrumentation.isWrapped(redisClientPrototype?.connect)) {
this._unwrap(redisClientPrototype, 'connect');
}
},
);
return new instrumentation.InstrumentationNodeModuleDefinition(
basePackageName,
['^1.0.0', '>=5.0.0 <5.12.0'],
(moduleExports) => moduleExports,
() => {},
[commanderModuleFile, multiCommanderModule, clientIndexModule],
);
}
_getPatchExtendWithCommands(transformCommandArguments) {
const plugin = this;
return function extendWithCommandsPatchWrapper(original) {
return function extendWithCommandsPatch( config) {
if (config?.BaseClass?.name !== 'RedisClient') {
return original.apply(this, arguments);
}
const origExecutor = config.executor;
config.executor = function ( command, args) {
const redisCommandArguments = transformCommandArguments(command, args).args;
return plugin._traceClientCommand(origExecutor, this, arguments, redisCommandArguments);
};
return original.apply(this, arguments);
};
};
}
_getPatchMultiCommandsExec(isPipeline) {
const plugin = this;
return function execPatchWrapper(original) {
return function execPatch() {
const execRes = original.apply(this, arguments);
if (typeof execRes?.then !== 'function') {
plugin._diag.error('non-promise result when patching exec/execAsPipeline');
return execRes;
}
return execRes
.then((redisRes) => {
const openSpans = this[OTEL_OPEN_SPANS];
plugin._endSpansWithRedisReplies(openSpans, redisRes, isPipeline);
return redisRes;
})
.catch((err) => {
const openSpans = this[OTEL_OPEN_SPANS];
if (!openSpans) {
plugin._diag.error('cannot find open spans to end for multi/pipeline');
} else {
const replies =
err.constructor.name === 'MultiErrorReply'
? (err ).replies
: new Array(openSpans.length).fill(err);
plugin._endSpansWithRedisReplies(openSpans, replies, isPipeline);
}
return Promise.reject(err);
});
};
};
}
_getPatchMultiCommandsAddCommand() {
const plugin = this;
return function addCommandWrapper(original) {
return function addCommandPatch( args) {
return plugin._traceClientCommand(original, this, arguments, args);
};
};
}
_getPatchRedisClientMulti() {
return function multiPatchWrapper(original) {
return function multiPatch() {
const multiRes = original.apply(this, arguments);
multiRes[MULTI_COMMAND_OPTIONS] = this.options;
return multiRes;
};
};
}
_getPatchRedisClientSendCommand() {
const plugin = this;
return function sendCommandWrapper(original) {
return function sendCommandPatch( args) {
return plugin._traceClientCommand(original, this, arguments, args);
};
};
}
_getPatchedClientConnect() {
const plugin = this;
return function connectWrapper(original) {
return function patchedConnect() {
const options = this.options;
const attributes = getClientAttributes(plugin._diag, options, plugin._semconvStability);
attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = plugin.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-connect`, {
kind: api.SpanKind.CLIENT,
attributes,
});
const res = api.context.with(api.trace.setSpan(api.context.active(), span), () => {
return original.apply(this);
});
return res
.then((result) => {
span.end();
return result;
})
.catch((error) => {
span.recordException(error);
span.setStatus({
code: api.SpanStatusCode.ERROR,
message: error.message,
});
span.end();
return Promise.reject(error);
});
};
};
}
_traceClientCommand(
origFunction,
origThis,
origArguments,
redisCommandArguments,
) {
const hasNoParentSpan = api.trace.getSpan(api.context.active()) === undefined;
if (hasNoParentSpan && this.getConfig().requireParentSpan) {
return origFunction.apply(origThis, origArguments);
}
const clientOptions = origThis.options || origThis[MULTI_COMMAND_OPTIONS];
const commandName = redisCommandArguments[0] ;
const commandArgs = redisCommandArguments.slice(1);
const dbStatementSerializer = this.getConfig().dbStatementSerializer || redisCommon.defaultDbStatementSerializer;
const attributes = getClientAttributes(this._diag, clientOptions, this._semconvStability);
if (this._semconvStability & instrumentation.SemconvStability.STABLE) {
attributes[semanticConventions.ATTR_DB_OPERATION_NAME] = commandName;
}
try {
const dbStatement = dbStatementSerializer(commandName, commandArgs);
if (dbStatement != null) {
if (this._semconvStability & instrumentation.SemconvStability.OLD) {
attributes[semconv.ATTR_DB_STATEMENT] = dbStatement;
}
if (this._semconvStability & instrumentation.SemconvStability.STABLE) {
attributes[semanticConventions.ATTR_DB_QUERY_TEXT] = dbStatement;
}
}
} catch (e) {
this._diag.error('dbStatementSerializer throw an exception', e, { commandName });
}
attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = this.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-${commandName}`, {
kind: api.SpanKind.CLIENT,
attributes,
});
const res = api.context.with(api.trace.setSpan(api.context.active(), span), () => {
return origFunction.apply(origThis, origArguments);
});
if (typeof res?.then === 'function') {
res.then(
(redisRes) => {
this._endSpanWithResponse(span, commandName, commandArgs, redisRes, undefined);
},
(err) => {
this._endSpanWithResponse(span, commandName, commandArgs, null, err);
},
);
} else {
const redisClientMultiCommand = res;
redisClientMultiCommand[OTEL_OPEN_SPANS] = redisClientMultiCommand[OTEL_OPEN_SPANS] || [];
redisClientMultiCommand[OTEL_OPEN_SPANS].push({
span,
commandName,
commandArgs,
});
}
return res;
}
_endSpansWithRedisReplies(openSpans, replies, isPipeline = false) {
if (!openSpans) {
return this._diag.error('cannot find open spans to end for redis multi/pipeline');
}
if (replies.length !== openSpans.length) {
return this._diag.error('number of multi command spans does not match response from redis');
}
const allCommands = openSpans.map(s => s.commandName);
const allSameCommand = allCommands.every(cmd => cmd === allCommands[0]);
const operationName = allSameCommand
? (isPipeline ? 'PIPELINE ' : 'MULTI ') + allCommands[0]
: isPipeline
? 'PIPELINE'
: 'MULTI';
for (let i = 0; i < openSpans.length; i++) {
const { span, commandArgs } = openSpans[i];
const currCommandRes = replies[i];
const [res, err] = currCommandRes instanceof Error ? [null, currCommandRes] : [currCommandRes, undefined];
if (this._semconvStability & instrumentation.SemconvStability.STABLE) {
span.setAttribute(semanticConventions.ATTR_DB_OPERATION_NAME, operationName);
}
this._endSpanWithResponse(span, allCommands[i], commandArgs, res, err);
}
}
_endSpanWithResponse(
span,
commandName,
commandArgs,
response,
error,
) {
const { responseHook } = this.getConfig();
if (!error && responseHook) {
try {
responseHook(span, commandName, commandArgs, response);
} catch (err) {
this._diag.error('responseHook throw an exception', err);
}
}
if (error) {
span.recordException(error);
span.setStatus({ code: api.SpanStatusCode.ERROR, message: error?.message });
}
span.end();
}
} RedisInstrumentationV4_V5.__initStatic2();
// ---- RedisInstrumentation (wrapper) ----
const DEFAULT_CONFIG = {
requireParentSpan: false,
};
class RedisInstrumentation extends instrumentation.InstrumentationBase {
__init() {this.initialized = false;}
constructor(config = {}) {
const resolvedConfig = { ...DEFAULT_CONFIG, ...config };
super(PACKAGE_NAME, PACKAGE_VERSION, resolvedConfig);RedisInstrumentation.prototype.__init.call(this); this.instrumentationV2_V3 = new RedisInstrumentationV2_V3(this.getConfig());
this.instrumentationV4_V5 = new RedisInstrumentationV4_V5(this.getConfig());
this.initialized = true;
}
setConfig(config = {}) {
const newConfig = { ...DEFAULT_CONFIG, ...config };
super.setConfig(newConfig);
if (!this.initialized) {
return;
}
this.instrumentationV2_V3.setConfig(newConfig);
this.instrumentationV4_V5.setConfig(newConfig);
}
init() {}
getModuleDefinitions() {
return [...this.instrumentationV2_V3.getModuleDefinitions(), ...this.instrumentationV4_V5.getModuleDefinitions()];
}
setTracerProvider(tracerProvider) {
super.setTracerProvider(tracerProvider);
if (!this.initialized) {
return;
}
this.instrumentationV2_V3.setTracerProvider(tracerProvider);
this.instrumentationV4_V5.setTracerProvider(tracerProvider);
}
enable() {
super.enable();
if (!this.initialized) {
return;
}
this.instrumentationV2_V3.enable();
this.instrumentationV4_V5.enable();
}
disable() {
super.disable();
if (!this.initialized) {
return;
}
this.instrumentationV2_V3.disable();
this.instrumentationV4_V5.disable();
}
}
exports.RedisInstrumentation = RedisInstrumentation;
//# sourceMappingURL=redis-instrumentation.js.map
{"version":3,"file":"redis-instrumentation.js","sources":["../../../../../../src/integrations/tracing/redis/vendored/redis-instrumentation.ts"],"sourcesContent":["/*\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 * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/instrumentation-redis\n * - Upstream version: @opentelemetry/instrumentation-redis@0.62.0\n * - Minor TypeScript adjustments for this repository's compiler settings\n */\n/* eslint-disable -- vendored @opentelemetry/instrumentation-redis */\n\nimport { context, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';\nimport type { DiagLogger, Span, TracerProvider } from '@opentelemetry/api';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n isWrapped,\n safeExecuteInTheMiddle,\n SemconvStability,\n semconvStabilityFromStr,\n} from '@opentelemetry/instrumentation';\nimport {\n ATTR_DB_OPERATION_NAME,\n ATTR_DB_QUERY_TEXT,\n ATTR_DB_SYSTEM_NAME,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n} from '@opentelemetry/semantic-conventions';\n\nimport { defaultDbStatementSerializer } from './redis-common';\nimport {\n ATTR_DB_CONNECTION_STRING,\n ATTR_DB_STATEMENT,\n ATTR_DB_SYSTEM,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n DB_SYSTEM_NAME_VALUE_REDIS,\n DB_SYSTEM_VALUE_REDIS,\n} from './semconv';\nimport type { RedisInstrumentationConfig } from './types';\n\nconst PACKAGE_NAME = '@opentelemetry/instrumentation-redis';\nconst PACKAGE_VERSION = '0.62.0';\n\n// ---- Internal types ----\n\ninterface RedisPluginClientTypes {\n connection_options?: {\n port?: string | number;\n host?: string;\n };\n address?: string;\n}\n\ninterface RedisCommand {\n command: string;\n args: string[];\n buffer_args: boolean;\n callback: (err: Error | null, reply: unknown) => void;\n call_on_write: boolean;\n}\n\ninterface MultiErrorReply extends Error {\n replies: unknown[];\n errorIndexes: Array<number>;\n}\n\ninterface OpenSpanInfo {\n span: Span;\n commandName: string;\n commandArgs: Array<string | Buffer>;\n}\n\nconst OTEL_OPEN_SPANS = Symbol('opentelemetry.instrumentation.redis.open_spans');\nconst MULTI_COMMAND_OPTIONS = Symbol('opentelemetry.instrumentation.redis.multi_command_options');\n\n// ---- v4-v5 utils ----\n\nfunction removeCredentialsFromDBConnectionStringAttribute(\n diagLogger: DiagLogger,\n url: string | undefined,\n): string | undefined {\n if (typeof url !== 'string' || !url) {\n return undefined;\n }\n try {\n const u = new URL(url);\n u.searchParams.delete('user_pwd');\n u.username = '';\n u.password = '';\n return u.href;\n } catch (err) {\n diagLogger.error('failed to sanitize redis connection url', err);\n }\n return undefined;\n}\n\nfunction getClientAttributes(\n diagLogger: DiagLogger,\n options: any,\n semconvStability: SemconvStability,\n): Record<string, any> {\n const attributes: Record<string, any> = {};\n if (semconvStability & SemconvStability.OLD) {\n Object.assign(attributes, {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n [ATTR_NET_PEER_NAME]: options?.socket?.host,\n [ATTR_NET_PEER_PORT]: options?.socket?.port,\n [ATTR_DB_CONNECTION_STRING]: removeCredentialsFromDBConnectionStringAttribute(diagLogger, options?.url),\n });\n }\n if (semconvStability & SemconvStability.STABLE) {\n Object.assign(attributes, {\n [ATTR_DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_REDIS,\n [ATTR_SERVER_ADDRESS]: options?.socket?.host,\n [ATTR_SERVER_PORT]: options?.socket?.port,\n });\n }\n return attributes;\n}\n\n// ---- v2-v3 utils ----\n\nfunction endSpanV2(span: Span, err: Error | null | undefined): void {\n if (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message,\n });\n }\n span.end();\n}\n\nfunction getTracedCreateClient(original: Function): Function {\n return function createClientTrace(this: any) {\n const client = original.apply(this, arguments);\n return context.bind(context.active(), client);\n };\n}\n\nfunction getTracedCreateStreamTrace(original: Function): Function {\n return function create_stream_trace(this: any) {\n if (!Object.prototype.hasOwnProperty.call(this, 'stream')) {\n Object.defineProperty(this, 'stream', {\n get() {\n return this._patched_redis_stream;\n },\n set(val: any) {\n context.bind(context.active(), val);\n this._patched_redis_stream = val;\n },\n });\n }\n return original.apply(this, arguments);\n };\n}\n\n// ---- RedisInstrumentationV2_V3 ----\n\nclass RedisInstrumentationV2_V3 extends InstrumentationBase<RedisInstrumentationConfig> {\n static COMPONENT = 'redis';\n _semconvStability: SemconvStability;\n\n constructor(config: RedisInstrumentationConfig = {}) {\n super(PACKAGE_NAME, PACKAGE_VERSION, config);\n this._semconvStability = config.semconvStability\n ? config.semconvStability\n : semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n override setConfig(config: RedisInstrumentationConfig = {}): void {\n super.setConfig(config);\n this._semconvStability = config.semconvStability\n ? config.semconvStability\n : semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n init() {\n return [\n new InstrumentationNodeModuleDefinition(\n 'redis',\n ['>=2.6.0 <4'],\n (moduleExports: any) => {\n if (isWrapped(moduleExports.RedisClient.prototype['internal_send_command'])) {\n this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');\n }\n this._wrap(moduleExports.RedisClient.prototype, 'internal_send_command', this._getPatchInternalSendCommand());\n if (isWrapped(moduleExports.RedisClient.prototype['create_stream'])) {\n this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');\n }\n this._wrap(moduleExports.RedisClient.prototype, 'create_stream', this._getPatchCreateStream());\n if (isWrapped(moduleExports.createClient)) {\n this._unwrap(moduleExports, 'createClient');\n }\n this._wrap(moduleExports, 'createClient', this._getPatchCreateClient());\n return moduleExports;\n },\n (moduleExports: any) => {\n if (moduleExports === undefined) return;\n this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');\n this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');\n this._unwrap(moduleExports, 'createClient');\n },\n ),\n ];\n }\n\n private _getPatchInternalSendCommand() {\n const instrumentation = this;\n return function internal_send_command(original: Function) {\n return function internal_send_command_trace(this: RedisPluginClientTypes, cmd: RedisCommand) {\n if (arguments.length !== 1 || typeof cmd !== 'object') {\n return original.apply(this, arguments);\n }\n const config = instrumentation.getConfig();\n const hasNoParentSpan = trace.getSpan(context.active()) === undefined;\n if (config.requireParentSpan === true && hasNoParentSpan) {\n return original.apply(this, arguments);\n }\n const dbStatementSerializer = config?.dbStatementSerializer || defaultDbStatementSerializer;\n const attributes: Record<string, any> = {};\n if (instrumentation._semconvStability & SemconvStability.OLD) {\n Object.assign(attributes, {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n [ATTR_DB_STATEMENT]: dbStatementSerializer(cmd.command, cmd.args),\n });\n }\n if (instrumentation._semconvStability & SemconvStability.STABLE) {\n Object.assign(attributes, {\n [ATTR_DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_REDIS,\n [ATTR_DB_OPERATION_NAME]: cmd.command,\n [ATTR_DB_QUERY_TEXT]: dbStatementSerializer(cmd.command, cmd.args),\n });\n }\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = instrumentation.tracer.startSpan(`${RedisInstrumentationV2_V3.COMPONENT}-${cmd.command}`, {\n kind: SpanKind.CLIENT,\n attributes,\n });\n if (this.connection_options) {\n const connectionAttributes: Record<string, any> = {};\n if (instrumentation._semconvStability & SemconvStability.OLD) {\n Object.assign(connectionAttributes, {\n [ATTR_NET_PEER_NAME]: this.connection_options.host,\n [ATTR_NET_PEER_PORT]: this.connection_options.port,\n });\n }\n if (instrumentation._semconvStability & SemconvStability.STABLE) {\n Object.assign(connectionAttributes, {\n [ATTR_SERVER_ADDRESS]: this.connection_options.host,\n [ATTR_SERVER_PORT]: this.connection_options.port,\n });\n }\n span.setAttributes(connectionAttributes);\n }\n if (this.address && instrumentation._semconvStability & SemconvStability.OLD) {\n span.setAttribute(ATTR_DB_CONNECTION_STRING, `redis://${this.address}`);\n }\n const originalCallback = arguments[0].callback;\n if (originalCallback) {\n const originalContext = context.active();\n arguments[0].callback = function callback(this: any, err: Error | null, reply: unknown) {\n if (config?.responseHook) {\n const responseHook = config.responseHook;\n safeExecuteInTheMiddle(\n () => {\n responseHook(span, cmd.command, cmd.args, reply);\n },\n (e: Error | undefined) => {\n if (e) {\n instrumentation._diag.error('Error executing responseHook', e);\n }\n },\n true,\n );\n }\n endSpanV2(span, err);\n return context.with(originalContext, originalCallback, this, ...arguments);\n };\n }\n try {\n return original.apply(this, arguments);\n } catch (rethrow) {\n endSpanV2(span, rethrow as Error);\n throw rethrow;\n }\n };\n };\n }\n\n private _getPatchCreateClient() {\n return function createClient(original: Function) {\n return getTracedCreateClient(original);\n };\n }\n\n private _getPatchCreateStream() {\n return function createReadStream(original: Function) {\n return getTracedCreateStreamTrace(original);\n };\n }\n}\n\n// ---- RedisInstrumentationV4_V5 ----\n\nclass RedisInstrumentationV4_V5 extends InstrumentationBase<RedisInstrumentationConfig> {\n static COMPONENT = 'redis';\n _semconvStability: SemconvStability;\n\n constructor(config: RedisInstrumentationConfig = {}) {\n super(PACKAGE_NAME, PACKAGE_VERSION, config);\n this._semconvStability = config.semconvStability\n ? config.semconvStability\n : semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n override setConfig(config: RedisInstrumentationConfig = {}): void {\n super.setConfig(config);\n this._semconvStability = config.semconvStability\n ? config.semconvStability\n : semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n init() {\n return [\n this._getInstrumentationNodeModuleDefinition('@redis/client'),\n this._getInstrumentationNodeModuleDefinition('@node-redis/client'),\n ];\n }\n\n private _getInstrumentationNodeModuleDefinition(basePackageName: string) {\n const commanderModuleFile = new InstrumentationNodeModuleFile(\n `${basePackageName}/dist/lib/commander.js`,\n ['^1.0.0'],\n (moduleExports: any, moduleVersion?: string) => {\n const transformCommandArguments = moduleExports.transformCommandArguments;\n if (!transformCommandArguments) {\n this._diag.error('internal instrumentation error, missing transformCommandArguments function');\n return moduleExports;\n }\n const functionToPatch = moduleVersion?.startsWith('1.0.') ? 'extendWithCommands' : 'attachCommands';\n if (isWrapped(moduleExports?.[functionToPatch])) {\n this._unwrap(moduleExports, functionToPatch);\n }\n this._wrap(moduleExports, functionToPatch, this._getPatchExtendWithCommands(transformCommandArguments));\n return moduleExports;\n },\n (moduleExports: any) => {\n if (isWrapped(moduleExports?.extendWithCommands)) {\n this._unwrap(moduleExports, 'extendWithCommands');\n }\n if (isWrapped(moduleExports?.attachCommands)) {\n this._unwrap(moduleExports, 'attachCommands');\n }\n },\n );\n\n const multiCommanderModule = new InstrumentationNodeModuleFile(\n `${basePackageName}/dist/lib/client/multi-command.js`,\n ['^1.0.0', '>=5.0.0 <5.12.0'],\n (moduleExports: any) => {\n const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;\n if (isWrapped(redisClientMultiCommandPrototype?.exec)) {\n this._unwrap(redisClientMultiCommandPrototype, 'exec');\n }\n this._wrap(redisClientMultiCommandPrototype, 'exec', this._getPatchMultiCommandsExec(false));\n if (isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {\n this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');\n }\n this._wrap(redisClientMultiCommandPrototype, 'execAsPipeline', this._getPatchMultiCommandsExec(true));\n if (isWrapped(redisClientMultiCommandPrototype?.addCommand)) {\n this._unwrap(redisClientMultiCommandPrototype, 'addCommand');\n }\n this._wrap(redisClientMultiCommandPrototype, 'addCommand', this._getPatchMultiCommandsAddCommand());\n return moduleExports;\n },\n (moduleExports: any) => {\n const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;\n if (isWrapped(redisClientMultiCommandPrototype?.exec)) {\n this._unwrap(redisClientMultiCommandPrototype, 'exec');\n }\n if (isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {\n this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');\n }\n if (isWrapped(redisClientMultiCommandPrototype?.addCommand)) {\n this._unwrap(redisClientMultiCommandPrototype, 'addCommand');\n }\n },\n );\n\n const clientIndexModule = new InstrumentationNodeModuleFile(\n `${basePackageName}/dist/lib/client/index.js`,\n ['^1.0.0', '>=5.0.0 <5.12.0'],\n (moduleExports: any) => {\n const redisClientPrototype = moduleExports?.default?.prototype;\n if (redisClientPrototype?.multi) {\n if (isWrapped(redisClientPrototype?.multi)) {\n this._unwrap(redisClientPrototype, 'multi');\n }\n this._wrap(redisClientPrototype, 'multi', this._getPatchRedisClientMulti());\n }\n if (redisClientPrototype?.MULTI) {\n if (isWrapped(redisClientPrototype?.MULTI)) {\n this._unwrap(redisClientPrototype, 'MULTI');\n }\n this._wrap(redisClientPrototype, 'MULTI', this._getPatchRedisClientMulti());\n }\n if (isWrapped(redisClientPrototype?.sendCommand)) {\n this._unwrap(redisClientPrototype, 'sendCommand');\n }\n this._wrap(redisClientPrototype, 'sendCommand', this._getPatchRedisClientSendCommand());\n if (isWrapped(redisClientPrototype?.connect)) {\n this._unwrap(redisClientPrototype, 'connect');\n }\n this._wrap(redisClientPrototype, 'connect', this._getPatchedClientConnect());\n return moduleExports;\n },\n (moduleExports: any) => {\n const redisClientPrototype = moduleExports?.default?.prototype;\n if (isWrapped(redisClientPrototype?.multi)) {\n this._unwrap(redisClientPrototype, 'multi');\n }\n if (isWrapped(redisClientPrototype?.MULTI)) {\n this._unwrap(redisClientPrototype, 'MULTI');\n }\n if (isWrapped(redisClientPrototype?.sendCommand)) {\n this._unwrap(redisClientPrototype, 'sendCommand');\n }\n if (isWrapped(redisClientPrototype?.connect)) {\n this._unwrap(redisClientPrototype, 'connect');\n }\n },\n );\n\n return new InstrumentationNodeModuleDefinition(\n basePackageName,\n ['^1.0.0', '>=5.0.0 <5.12.0'],\n (moduleExports: any) => moduleExports,\n () => {},\n [commanderModuleFile, multiCommanderModule, clientIndexModule],\n );\n }\n\n private _getPatchExtendWithCommands(transformCommandArguments: Function) {\n const plugin = this;\n return function extendWithCommandsPatchWrapper(original: Function) {\n return function extendWithCommandsPatch(this: any, config: any) {\n if (config?.BaseClass?.name !== 'RedisClient') {\n return original.apply(this, arguments);\n }\n const origExecutor = config.executor;\n config.executor = function (this: any, command: any, args: any) {\n const redisCommandArguments = transformCommandArguments(command, args).args;\n return plugin._traceClientCommand(origExecutor, this, arguments, redisCommandArguments);\n };\n return original.apply(this, arguments);\n };\n };\n }\n\n private _getPatchMultiCommandsExec(isPipeline: boolean) {\n const plugin = this;\n return function execPatchWrapper(original: Function) {\n return function execPatch(this: any) {\n const execRes = original.apply(this, arguments);\n if (typeof execRes?.then !== 'function') {\n plugin._diag.error('non-promise result when patching exec/execAsPipeline');\n return execRes;\n }\n return execRes\n .then((redisRes: unknown[]) => {\n const openSpans: OpenSpanInfo[] = this[OTEL_OPEN_SPANS];\n plugin._endSpansWithRedisReplies(openSpans, redisRes, isPipeline);\n return redisRes;\n })\n .catch((err: any) => {\n const openSpans: OpenSpanInfo[] = this[OTEL_OPEN_SPANS];\n if (!openSpans) {\n plugin._diag.error('cannot find open spans to end for multi/pipeline');\n } else {\n const replies =\n err.constructor.name === 'MultiErrorReply'\n ? (err as MultiErrorReply).replies\n : new Array(openSpans.length).fill(err);\n plugin._endSpansWithRedisReplies(openSpans, replies, isPipeline);\n }\n return Promise.reject(err);\n });\n };\n };\n }\n\n private _getPatchMultiCommandsAddCommand() {\n const plugin = this;\n return function addCommandWrapper(original: Function) {\n return function addCommandPatch(this: any, args: any) {\n return plugin._traceClientCommand(original, this, arguments, args);\n };\n };\n }\n\n private _getPatchRedisClientMulti() {\n return function multiPatchWrapper(original: Function) {\n return function multiPatch(this: any) {\n const multiRes: any = original.apply(this, arguments);\n multiRes[MULTI_COMMAND_OPTIONS] = this.options;\n return multiRes;\n };\n };\n }\n\n private _getPatchRedisClientSendCommand() {\n const plugin = this;\n return function sendCommandWrapper(original: Function) {\n return function sendCommandPatch(this: any, args: any) {\n return plugin._traceClientCommand(original, this, arguments, args);\n };\n };\n }\n\n private _getPatchedClientConnect() {\n const plugin = this;\n return function connectWrapper(original: Function) {\n return function patchedConnect(this: any) {\n const options = this.options;\n const attributes = getClientAttributes(plugin._diag, options, plugin._semconvStability);\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = plugin.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-connect`, {\n kind: SpanKind.CLIENT,\n attributes,\n });\n const res = context.with(trace.setSpan(context.active(), span), () => {\n return original.apply(this);\n });\n return res\n .then((result: any) => {\n span.end();\n return result;\n })\n .catch((error: Error) => {\n span.recordException(error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error.message,\n });\n span.end();\n return Promise.reject(error);\n });\n };\n };\n }\n\n _traceClientCommand(\n origFunction: Function,\n origThis: any,\n origArguments: IArguments,\n redisCommandArguments: Array<string | Buffer>,\n ): any {\n const hasNoParentSpan = trace.getSpan(context.active()) === undefined;\n if (hasNoParentSpan && this.getConfig().requireParentSpan) {\n return origFunction.apply(origThis, origArguments);\n }\n const clientOptions = origThis.options || origThis[MULTI_COMMAND_OPTIONS];\n const commandName = redisCommandArguments[0] as string;\n const commandArgs = redisCommandArguments.slice(1);\n const dbStatementSerializer = this.getConfig().dbStatementSerializer || defaultDbStatementSerializer;\n const attributes = getClientAttributes(this._diag, clientOptions, this._semconvStability);\n if (this._semconvStability & SemconvStability.STABLE) {\n attributes[ATTR_DB_OPERATION_NAME] = commandName;\n }\n try {\n const dbStatement = dbStatementSerializer(commandName, commandArgs);\n if (dbStatement != null) {\n if (this._semconvStability & SemconvStability.OLD) {\n attributes[ATTR_DB_STATEMENT] = dbStatement;\n }\n if (this._semconvStability & SemconvStability.STABLE) {\n attributes[ATTR_DB_QUERY_TEXT] = dbStatement;\n }\n }\n } catch (e) {\n this._diag.error('dbStatementSerializer throw an exception', e, { commandName });\n }\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = this.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-${commandName}`, {\n kind: SpanKind.CLIENT,\n attributes,\n });\n const res = context.with(trace.setSpan(context.active(), span), () => {\n return origFunction.apply(origThis, origArguments);\n });\n if (typeof res?.then === 'function') {\n res.then(\n (redisRes: unknown) => {\n this._endSpanWithResponse(span, commandName, commandArgs, redisRes, undefined);\n },\n (err: Error) => {\n this._endSpanWithResponse(span, commandName, commandArgs, null, err);\n },\n );\n } else {\n const redisClientMultiCommand: any = res;\n redisClientMultiCommand[OTEL_OPEN_SPANS] = redisClientMultiCommand[OTEL_OPEN_SPANS] || [];\n redisClientMultiCommand[OTEL_OPEN_SPANS].push({\n span,\n commandName,\n commandArgs,\n });\n }\n return res;\n }\n\n _endSpansWithRedisReplies(openSpans: OpenSpanInfo[] | undefined, replies: unknown[], isPipeline = false): void {\n if (!openSpans) {\n return this._diag.error('cannot find open spans to end for redis multi/pipeline');\n }\n if (replies.length !== openSpans.length) {\n return this._diag.error('number of multi command spans does not match response from redis');\n }\n const allCommands = openSpans.map(s => s.commandName);\n const allSameCommand = allCommands.every(cmd => cmd === allCommands[0]);\n const operationName = allSameCommand\n ? (isPipeline ? 'PIPELINE ' : 'MULTI ') + allCommands[0]\n : isPipeline\n ? 'PIPELINE'\n : 'MULTI';\n for (let i = 0; i < openSpans.length; i++) {\n const { span, commandArgs } = openSpans[i]!;\n const currCommandRes = replies[i];\n const [res, err] = currCommandRes instanceof Error ? [null, currCommandRes] : [currCommandRes, undefined];\n if (this._semconvStability & SemconvStability.STABLE) {\n span.setAttribute(ATTR_DB_OPERATION_NAME, operationName);\n }\n this._endSpanWithResponse(span, allCommands[i]!, commandArgs, res, err);\n }\n }\n\n _endSpanWithResponse(\n span: Span,\n commandName: string,\n commandArgs: Array<string | Buffer>,\n response: unknown,\n error: Error | null | undefined,\n ): void {\n const { responseHook } = this.getConfig();\n if (!error && responseHook) {\n try {\n responseHook(span, commandName, commandArgs, response);\n } catch (err) {\n this._diag.error('responseHook throw an exception', err);\n }\n }\n if (error) {\n span.recordException(error);\n span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message });\n }\n span.end();\n }\n}\n\n// ---- RedisInstrumentation (wrapper) ----\n\nconst DEFAULT_CONFIG: RedisInstrumentationConfig = {\n requireParentSpan: false,\n};\n\nexport class RedisInstrumentation extends InstrumentationBase<RedisInstrumentationConfig> {\n private instrumentationV2_V3: RedisInstrumentationV2_V3;\n private instrumentationV4_V5: RedisInstrumentationV4_V5;\n private initialized = false;\n\n constructor(config: RedisInstrumentationConfig = {}) {\n const resolvedConfig = { ...DEFAULT_CONFIG, ...config };\n super(PACKAGE_NAME, PACKAGE_VERSION, resolvedConfig);\n this.instrumentationV2_V3 = new RedisInstrumentationV2_V3(this.getConfig());\n this.instrumentationV4_V5 = new RedisInstrumentationV4_V5(this.getConfig());\n this.initialized = true;\n }\n\n override setConfig(config: RedisInstrumentationConfig = {}): void {\n const newConfig = { ...DEFAULT_CONFIG, ...config };\n super.setConfig(newConfig);\n if (!this.initialized) {\n return;\n }\n this.instrumentationV2_V3.setConfig(newConfig);\n this.instrumentationV4_V5.setConfig(newConfig);\n }\n\n init() {}\n\n override getModuleDefinitions() {\n return [...this.instrumentationV2_V3.getModuleDefinitions(), ...this.instrumentationV4_V5.getModuleDefinitions()];\n }\n\n override setTracerProvider(tracerProvider: TracerProvider): void {\n super.setTracerProvider(tracerProvider);\n if (!this.initialized) {\n return;\n }\n this.instrumentationV2_V3.setTracerProvider(tracerProvider);\n this.instrumentationV4_V5.setTracerProvider(tracerProvider);\n }\n\n override enable(): void {\n super.enable();\n if (!this.initialized) {\n return;\n }\n this.instrumentationV2_V3.enable();\n this.instrumentationV4_V5.enable();\n }\n\n override disable(): void {\n super.disable();\n if (!this.initialized) {\n return;\n }\n this.instrumentationV2_V3.disable();\n this.instrumentationV4_V5.disable();\n }\n}\n"],"names":["SemconvStability","ATTR_DB_SYSTEM","DB_SYSTEM_VALUE_REDIS","ATTR_NET_PEER_NAME","ATTR_NET_PEER_PORT","ATTR_DB_CONNECTION_STRING","ATTR_DB_SYSTEM_NAME","DB_SYSTEM_NAME_VALUE_REDIS","ATTR_SERVER_ADDRESS","ATTR_SERVER_PORT","SpanStatusCode","context","InstrumentationBase","semconvStabilityFromStr","InstrumentationNodeModuleDefinition","isWrapped","instrumentation","trace","defaultDbStatementSerializer","ATTR_DB_STATEMENT","ATTR_DB_OPERATION_NAME","ATTR_DB_QUERY_TEXT","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SpanKind","safeExecuteInTheMiddle","InstrumentationNodeModuleFile"],"mappings":"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"}
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE from the Sentry authors:
* - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/instrumentation-redis
* - Upstream version: @opentelemetry/instrumentation-redis@0.62.0
* - Minor TypeScript adjustments for this repository's compiler settings
*/
/* eslint-disable -- vendored @opentelemetry/instrumentation-redis */
/*
* This file contains a copy of unstable semantic convention definitions
* used by the vendored redis/ioredis instrumentations.
* @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv
*/
// Deprecated constants kept for backwards compatibility with older semconv
const ATTR_DB_CONNECTION_STRING = 'db.connection_string';
const ATTR_DB_STATEMENT = 'db.statement';
const ATTR_DB_SYSTEM = 'db.system';
const ATTR_NET_PEER_NAME = 'net.peer.name';
const ATTR_NET_PEER_PORT = 'net.peer.port';
const DB_SYSTEM_NAME_VALUE_REDIS = 'redis';
const DB_SYSTEM_VALUE_REDIS = 'redis';
exports.ATTR_DB_CONNECTION_STRING = ATTR_DB_CONNECTION_STRING;
exports.ATTR_DB_STATEMENT = ATTR_DB_STATEMENT;
exports.ATTR_DB_SYSTEM = ATTR_DB_SYSTEM;
exports.ATTR_NET_PEER_NAME = ATTR_NET_PEER_NAME;
exports.ATTR_NET_PEER_PORT = ATTR_NET_PEER_PORT;
exports.DB_SYSTEM_NAME_VALUE_REDIS = DB_SYSTEM_NAME_VALUE_REDIS;
exports.DB_SYSTEM_VALUE_REDIS = DB_SYSTEM_VALUE_REDIS;
//# sourceMappingURL=semconv.js.map
{"version":3,"file":"semconv.js","sources":["../../../../../../src/integrations/tracing/redis/vendored/semconv.ts"],"sourcesContent":["/*\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 * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/instrumentation-redis\n * - Upstream version: @opentelemetry/instrumentation-redis@0.62.0\n * - Minor TypeScript adjustments for this repository's compiler settings\n */\n/* eslint-disable -- vendored @opentelemetry/instrumentation-redis */\n\n/*\n * This file contains a copy of unstable semantic convention definitions\n * used by the vendored redis/ioredis instrumentations.\n * @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv\n */\n\n// Deprecated constants kept for backwards compatibility with older semconv\nexport const ATTR_DB_CONNECTION_STRING = 'db.connection_string';\nexport const ATTR_DB_STATEMENT = 'db.statement';\nexport const ATTR_DB_SYSTEM = 'db.system';\nexport const ATTR_NET_PEER_NAME = 'net.peer.name';\nexport const ATTR_NET_PEER_PORT = 'net.peer.port';\nexport const DB_SYSTEM_NAME_VALUE_REDIS = 'redis';\nexport const DB_SYSTEM_VALUE_REDIS = 'redis';\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACO,MAAM,yBAAA,GAA4B;AAClC,MAAM,iBAAA,GAAoB;AAC1B,MAAM,cAAA,GAAiB;AACvB,MAAM,kBAAA,GAAqB;AAC3B,MAAM,kBAAA,GAAqB;AAC3B,MAAM,0BAAA,GAA6B;AACnC,MAAM,qBAAA,GAAwB;;;;;;;;;;"}
import { defineIntegration, spanToJSON, SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, SEMANTIC_ATTRIBUTE_CACHE_HIT, SEMANTIC_ATTRIBUTE_CACHE_KEY, SEMANTIC_ATTRIBUTE_SENTRY_OP, truncate } from '@sentry/core';
import { generateInstrumentOnce } from '@sentry/node-core';
import { getCacheKeySafely, getCacheOperation, shouldConsiderForCache, calculateCacheItemSize, isInCommands, GET_COMMANDS } from '../../../utils/redisCache.js';
import { IORedisInstrumentation } from './vendored/ioredis-instrumentation.js';
import { RedisInstrumentation } from './vendored/redis-instrumentation.js';
import { subscribeRedisDiagnosticChannels } from './redis-dc-subscriber.js';
const INTEGRATION_NAME = 'Redis';
/* Only exported for testing purposes */
let _redisOptions = {};
/* Only exported for testing purposes */
const cacheResponseHook = (
span,
redisCommand,
cmdArgs,
response,
) => {
const safeKey = getCacheKeySafely(redisCommand, cmdArgs);
const cacheOperation = getCacheOperation(redisCommand);
if (
!safeKey ||
!cacheOperation ||
!_redisOptions.cachePrefixes ||
!shouldConsiderForCache(redisCommand, safeKey, _redisOptions.cachePrefixes)
) {
// not relevant for cache
return;
}
// otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199
// We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/
// Fall back to stable semconv attributes (server.address/server.port) when
// old-semconv ones are absent, eg OTEL_SEMCONV_STABILITY_OPT_IN=database
// set for node-redis v4/v5.
const spanData = spanToJSON(span).data;
const networkPeerAddress = spanData['net.peer.name'] ?? spanData['server.address'];
const networkPeerPort = spanData['net.peer.port'] ?? spanData['server.port'];
if (networkPeerPort && networkPeerAddress) {
span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });
}
const cacheItemSize = calculateCacheItemSize(response);
if (cacheItemSize) {
span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);
}
if (isInCommands(GET_COMMANDS, redisCommand) && cacheItemSize !== undefined) {
span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);
}
span.setAttributes({
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,
[SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey,
});
// todo: change to string[] once EAP supports it
const spanDescription = safeKey.join(', ');
span.updateName(
_redisOptions.maxCacheKeyLength ? truncate(spanDescription, _redisOptions.maxCacheKeyLength) : spanDescription,
);
};
const instrumentIORedis = generateInstrumentOnce(`${INTEGRATION_NAME}.IORedis`, () => {
return new IORedisInstrumentation({
responseHook: cacheResponseHook,
});
});
const instrumentRedisModule = generateInstrumentOnce(`${INTEGRATION_NAME}.Redis`, () => {
return new RedisInstrumentation({
responseHook: cacheResponseHook,
});
});
/** To be able to preload all Redis OTel instrumentations with just one ID ("Redis"), all the instrumentations are generated in this one function */
const instrumentRedis = Object.assign(
() => {
instrumentIORedis();
instrumentRedisModule();
// node-redis >= 5.12.0 publishes via diagnostics_channel. The subscriber uses
// `@sentry/opentelemetry/tracing-channel`, which needs the Sentry OTel context manager
// to be registered before it can `bindStore`. `initOpenTelemetry()` runs after integration
// `setupOnce`, so defer to the next tick.
void Promise.resolve().then(() => subscribeRedisDiagnosticChannels(cacheResponseHook));
// todo: implement them gradually
// new LegacyRedisInstrumentation({}),
},
{ id: INTEGRATION_NAME },
);
const _redisIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
_redisOptions = options;
instrumentRedis();
},
};
}) ;
/**
* Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and
* [ioredis](https://www.npmjs.com/package/ioredis) libraries.
*
* For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).
*
* @example
* ```javascript
* const Sentry = require('@sentry/node');
*
* Sentry.init({
* integrations: [Sentry.redisIntegration()],
* });
* ```
*/
const redisIntegration = defineIntegration(_redisIntegration);
export { _redisOptions, cacheResponseHook, instrumentRedis, redisIntegration };
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/redis/index.ts"],"sourcesContent":["import type { Span } from '@opentelemetry/api';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n defineIntegration,\n SEMANTIC_ATTRIBUTE_CACHE_HIT,\n SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE,\n SEMANTIC_ATTRIBUTE_CACHE_KEY,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n truncate,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport type { IORedisCommandArgs } from '../../../utils/redisCache';\nimport {\n calculateCacheItemSize,\n GET_COMMANDS,\n getCacheKeySafely,\n getCacheOperation,\n isInCommands,\n shouldConsiderForCache,\n} from '../../../utils/redisCache';\nimport type { IORedisResponseCustomAttributeFunction } from './vendored/types';\nimport { IORedisInstrumentation } from './vendored/ioredis-instrumentation';\nimport { RedisInstrumentation } from './vendored/redis-instrumentation';\nimport { subscribeRedisDiagnosticChannels } from './redis-dc-subscriber';\n\ninterface RedisOptions {\n /**\n * Define cache prefixes for cache keys that should be captured as a cache span.\n *\n * Setting this to, for example, `['user:']` will capture cache keys that start with `user:`.\n */\n cachePrefixes?: string[];\n /**\n * Maximum length of the cache key added to the span description. If the key exceeds this length, it will be truncated.\n *\n * Passing `0` will use the full cache key without truncation.\n *\n * By default, the full cache key is used.\n */\n maxCacheKeyLength?: number;\n}\n\nconst INTEGRATION_NAME = 'Redis';\n\n/* Only exported for testing purposes */\nexport let _redisOptions: RedisOptions = {};\n\n/* Only exported for testing purposes */\nexport const cacheResponseHook: IORedisResponseCustomAttributeFunction = (\n span: Span,\n redisCommand: string,\n cmdArgs: IORedisCommandArgs,\n response: unknown,\n) => {\n const safeKey = getCacheKeySafely(redisCommand, cmdArgs);\n const cacheOperation = getCacheOperation(redisCommand);\n\n if (\n !safeKey ||\n !cacheOperation ||\n !_redisOptions.cachePrefixes ||\n !shouldConsiderForCache(redisCommand, safeKey, _redisOptions.cachePrefixes)\n ) {\n // not relevant for cache\n return;\n }\n\n // otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199\n // We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/\n // Fall back to stable semconv attributes (server.address/server.port) when\n // old-semconv ones are absent, eg OTEL_SEMCONV_STABILITY_OPT_IN=database\n // set for node-redis v4/v5.\n const spanData = spanToJSON(span).data;\n const networkPeerAddress = spanData['net.peer.name'] ?? spanData['server.address'];\n const networkPeerPort = spanData['net.peer.port'] ?? spanData['server.port'];\n if (networkPeerPort && networkPeerAddress) {\n span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });\n }\n\n const cacheItemSize = calculateCacheItemSize(response);\n\n if (cacheItemSize) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);\n }\n\n if (isInCommands(GET_COMMANDS, redisCommand) && cacheItemSize !== undefined) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);\n }\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,\n [SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey,\n });\n\n // todo: change to string[] once EAP supports it\n const spanDescription = safeKey.join(', ');\n\n span.updateName(\n _redisOptions.maxCacheKeyLength ? truncate(spanDescription, _redisOptions.maxCacheKeyLength) : spanDescription,\n );\n};\n\nconst instrumentIORedis = generateInstrumentOnce(`${INTEGRATION_NAME}.IORedis`, () => {\n return new IORedisInstrumentation({\n responseHook: cacheResponseHook,\n });\n});\n\nconst instrumentRedisModule = generateInstrumentOnce(`${INTEGRATION_NAME}.Redis`, () => {\n return new RedisInstrumentation({\n responseHook: cacheResponseHook,\n });\n});\n\n/** To be able to preload all Redis OTel instrumentations with just one ID (\"Redis\"), all the instrumentations are generated in this one function */\nexport const instrumentRedis = Object.assign(\n (): void => {\n instrumentIORedis();\n instrumentRedisModule();\n // node-redis >= 5.12.0 publishes via diagnostics_channel. The subscriber uses\n // `@sentry/opentelemetry/tracing-channel`, which needs the Sentry OTel context manager\n // to be registered before it can `bindStore`. `initOpenTelemetry()` runs after integration\n // `setupOnce`, so defer to the next tick.\n void Promise.resolve().then(() => subscribeRedisDiagnosticChannels(cacheResponseHook));\n\n // todo: implement them gradually\n // new LegacyRedisInstrumentation({}),\n },\n { id: INTEGRATION_NAME },\n);\n\nconst _redisIntegration = ((options: RedisOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n _redisOptions = options;\n instrumentRedis();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and\n * [ioredis](https://www.npmjs.com/package/ioredis) libraries.\n *\n * For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.redisIntegration()],\n * });\n * ```\n */\nexport const redisIntegration = defineIntegration(_redisIntegration);\n"],"names":[],"mappings":"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"}
import { startSpanManual, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_STATUS_ERROR } from '@sentry/core';
import { tracingChannel } from '@sentry/opentelemetry/tracing-channel';
import { defaultDbStatementSerializer } from './vendored/redis-common.js';
import { DB_SYSTEM_VALUE_REDIS, ATTR_NET_PEER_PORT, ATTR_NET_PEER_NAME, ATTR_DB_STATEMENT, ATTR_DB_SYSTEM } from './vendored/semconv.js';
// Channel names as published by node-redis >= 5.12.0.
// Hardcoded so we don't import `redis` at module-load time.
const CHANNEL_COMMAND = 'node-redis:command';
const CHANNEL_BATCH = 'node-redis:batch';
const CHANNEL_CONNECT = 'node-redis:connect';
const ORIGIN = 'auto.db.redis.diagnostic_channel';
const NOOP = () => {};
let subscribed = false;
let currentResponseHook;
/**
* Subscribe Sentry handlers to node-redis diagnostics_channel events (>= 5.12.0).
*
* Uses `@sentry/opentelemetry/tracing-channel` so OTel AsyncLocalStorage context propagates
* automatically via `bindStore` — without it, spans created in `start` would not become
* the active context for subsequent operations.
*
* Safe on every runtime that exposes `node:diagnostics_channel` (Node, Bun, Deno, Workers).
* In node-redis < 5.12.0 the channels are never published to, so subscribers are inert and
* there is no double-instrumentation against the IITM-based patcher (gated to < 5.12.0).
*/
function subscribeRedisDiagnosticChannels(responseHook) {
currentResponseHook = responseHook;
if (subscribed) return;
try {
setupCommandChannel();
setupBatchChannel();
setupConnectChannel();
subscribed = true;
} catch {
// tracingChannel from @sentry/opentelemetry requires `node:diagnostics_channel`.
// On runtimes where it isn't available, fail closed.
}
}
function setupCommandChannel() {
const channel = tracingChannel(CHANNEL_COMMAND, data => {
// node-redis >= 5.12.0 includes the command name as args[0] in the DC payload.
// Strip it so serialization and cache key extraction see only the actual arguments.
const actualArgs = data.args.slice(1);
const statement = safeSerialize(data.command, actualArgs);
return startSpanManual(
{
name: `redis-${data.command}`,
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis',
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,
...(statement != null ? { [ATTR_DB_STATEMENT]: statement } : {}),
...(data.serverAddress != null ? { [ATTR_NET_PEER_NAME]: data.serverAddress } : {}),
...(data.serverPort != null ? { [ATTR_NET_PEER_PORT]: data.serverPort } : {}),
},
},
span => span,
) ;
});
channel.subscribe({
start: NOOP,
asyncStart: NOOP,
end: NOOP,
asyncEnd: data => {
const span = data._sentrySpan;
// only end if error handler isn't going to
if (!span || data.error) return;
// Same slice: strip command name from args before passing to the response hook.
runResponseHook(span, data.command, data.args.slice(1), data.result);
span.end();
},
error: data => {
const span = data._sentrySpan;
if (!span) return;
if (data.error) {
span.setStatus({ code: SPAN_STATUS_ERROR, message: data.error.message });
}
span.end();
},
});
}
function setupBatchChannel() {
const channel = tracingChannel(CHANNEL_BATCH, data => {
const operationName = data.batchMode === 'PIPELINE' ? 'PIPELINE' : 'MULTI';
return startSpanManual(
{
name: operationName,
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis',
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,
...(data.batchSize != null ? { 'db.redis.batch_size': data.batchSize } : {}),
...(data.serverAddress != null ? { [ATTR_NET_PEER_NAME]: data.serverAddress } : {}),
...(data.serverPort != null ? { [ATTR_NET_PEER_PORT]: data.serverPort } : {}),
},
},
span => span,
) ;
});
channel.subscribe({
start: NOOP,
asyncStart: NOOP,
end: NOOP,
asyncEnd: data => {
// only end if the error handler isn't going to
if (!data.error) data._sentrySpan?.end();
},
error: data => {
const span = data._sentrySpan;
if (!span) return;
if (data.error) {
span.setStatus({ code: SPAN_STATUS_ERROR, message: data.error.message });
}
span.end();
},
});
}
function setupConnectChannel() {
const channel = tracingChannel(CHANNEL_CONNECT, data => {
return startSpanManual(
{
name: 'redis-connect',
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis.connect',
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,
...(data.serverAddress != null ? { [ATTR_NET_PEER_NAME]: data.serverAddress } : {}),
...(data.serverPort != null ? { [ATTR_NET_PEER_PORT]: data.serverPort } : {}),
},
},
span => span,
) ;
});
channel.subscribe({
start: NOOP,
asyncStart: NOOP,
end: NOOP,
asyncEnd: data => {
// only end if the error handler isn't going to
if (!data.error) data._sentrySpan?.end();
},
error: data => {
const span = data._sentrySpan;
if (!span) return;
if (data.error) {
span.setStatus({ code: SPAN_STATUS_ERROR, message: data.error.message });
}
span.end();
},
});
}
function runResponseHook(span, command, args, result) {
const hook = currentResponseHook;
if (!hook) return;
try {
hook(span, command, args , result);
} catch {
// never let user hooks break instrumentation
}
}
function safeSerialize(command, args) {
try {
return defaultDbStatementSerializer(command, args);
} catch {
return undefined;
}
}
export { subscribeRedisDiagnosticChannels };
//# sourceMappingURL=redis-dc-subscriber.js.map
{"version":3,"file":"redis-dc-subscriber.js","sources":["../../../../../src/integrations/tracing/redis/redis-dc-subscriber.ts"],"sourcesContent":["import type { Span } from '@opentelemetry/api';\nimport {\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n startSpanManual,\n} from '@sentry/core';\nimport { tracingChannel, type TracingChannelContextWithSpan } from '@sentry/opentelemetry/tracing-channel';\nimport { defaultDbStatementSerializer } from './vendored/redis-common';\nimport {\n ATTR_DB_STATEMENT,\n ATTR_DB_SYSTEM,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n DB_SYSTEM_VALUE_REDIS,\n} from './vendored/semconv';\nimport type { IORedisInstrumentationConfig } from './vendored/types';\n\n// Channel names as published by node-redis >= 5.12.0.\n// Hardcoded so we don't import `redis` at module-load time.\nconst CHANNEL_COMMAND = 'node-redis:command';\nconst CHANNEL_BATCH = 'node-redis:batch';\nconst CHANNEL_CONNECT = 'node-redis:connect';\n\nconst ORIGIN = 'auto.db.redis.diagnostic_channel';\n\ninterface CommandData {\n command: string;\n args: Array<string | Buffer>;\n database?: number;\n serverAddress?: string;\n serverPort?: number;\n result?: unknown;\n error?: Error;\n}\n\ninterface BatchData {\n batchMode?: 'MULTI' | 'PIPELINE';\n batchSize?: number;\n database?: number;\n clientId?: string | number;\n serverAddress?: string;\n serverPort?: number;\n result?: unknown[];\n error?: Error;\n}\n\ninterface ConnectData {\n serverAddress?: string;\n serverPort?: number;\n url?: string;\n error?: Error;\n}\n\nconst NOOP = (): void => {};\n\nlet subscribed = false;\nlet currentResponseHook: IORedisInstrumentationConfig['responseHook'] | undefined;\n\n/**\n * Subscribe Sentry handlers to node-redis diagnostics_channel events (>= 5.12.0).\n *\n * Uses `@sentry/opentelemetry/tracing-channel` so OTel AsyncLocalStorage context propagates\n * automatically via `bindStore` — without it, spans created in `start` would not become\n * the active context for subsequent operations.\n *\n * Safe on every runtime that exposes `node:diagnostics_channel` (Node, Bun, Deno, Workers).\n * In node-redis < 5.12.0 the channels are never published to, so subscribers are inert and\n * there is no double-instrumentation against the IITM-based patcher (gated to < 5.12.0).\n */\nexport function subscribeRedisDiagnosticChannels(responseHook?: IORedisInstrumentationConfig['responseHook']): void {\n currentResponseHook = responseHook;\n if (subscribed) return;\n\n try {\n setupCommandChannel();\n setupBatchChannel();\n setupConnectChannel();\n subscribed = true;\n } catch {\n // tracingChannel from @sentry/opentelemetry requires `node:diagnostics_channel`.\n // On runtimes where it isn't available, fail closed.\n }\n}\n\nfunction setupCommandChannel(): void {\n const channel = tracingChannel<CommandData>(CHANNEL_COMMAND, data => {\n // node-redis >= 5.12.0 includes the command name as args[0] in the DC payload.\n // Strip it so serialization and cache key extraction see only the actual arguments.\n const actualArgs = data.args.slice(1);\n const statement = safeSerialize(data.command, actualArgs);\n return startSpanManual(\n {\n name: `redis-${data.command}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis',\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n ...(statement != null ? { [ATTR_DB_STATEMENT]: statement } : {}),\n ...(data.serverAddress != null ? { [ATTR_NET_PEER_NAME]: data.serverAddress } : {}),\n ...(data.serverPort != null ? { [ATTR_NET_PEER_PORT]: data.serverPort } : {}),\n },\n },\n span => span,\n ) as Span;\n });\n\n channel.subscribe({\n start: NOOP,\n asyncStart: NOOP,\n end: NOOP,\n asyncEnd: data => {\n const span = data._sentrySpan;\n // only end if error handler isn't going to\n if (!span || data.error) return;\n // Same slice: strip command name from args before passing to the response hook.\n runResponseHook(span, data.command, data.args.slice(1), data.result);\n span.end();\n },\n error: data => {\n const span = data._sentrySpan;\n if (!span) return;\n if (data.error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: data.error.message });\n }\n span.end();\n },\n });\n}\n\nfunction setupBatchChannel(): void {\n const channel = tracingChannel<BatchData>(CHANNEL_BATCH, data => {\n const operationName = data.batchMode === 'PIPELINE' ? 'PIPELINE' : 'MULTI';\n\n return startSpanManual(\n {\n name: operationName,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis',\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n ...(data.batchSize != null ? { 'db.redis.batch_size': data.batchSize } : {}),\n ...(data.serverAddress != null ? { [ATTR_NET_PEER_NAME]: data.serverAddress } : {}),\n ...(data.serverPort != null ? { [ATTR_NET_PEER_PORT]: data.serverPort } : {}),\n },\n },\n span => span,\n ) as Span;\n });\n\n channel.subscribe({\n start: NOOP,\n asyncStart: NOOP,\n end: NOOP,\n asyncEnd: data => {\n // only end if the error handler isn't going to\n if (!data.error) data._sentrySpan?.end();\n },\n error: data => {\n const span = data._sentrySpan;\n if (!span) return;\n if (data.error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: data.error.message });\n }\n span.end();\n },\n });\n}\n\nfunction setupConnectChannel(): void {\n const channel = tracingChannel<ConnectData>(CHANNEL_CONNECT, data => {\n return startSpanManual(\n {\n name: 'redis-connect',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.redis.connect',\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n ...(data.serverAddress != null ? { [ATTR_NET_PEER_NAME]: data.serverAddress } : {}),\n ...(data.serverPort != null ? { [ATTR_NET_PEER_PORT]: data.serverPort } : {}),\n },\n },\n span => span,\n ) as Span;\n });\n\n channel.subscribe({\n start: NOOP,\n asyncStart: NOOP,\n end: NOOP,\n asyncEnd: data => {\n // only end if the error handler isn't going to\n if (!data.error) data._sentrySpan?.end();\n },\n error: data => {\n const span = data._sentrySpan;\n if (!span) return;\n if (data.error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: data.error.message });\n }\n span.end();\n },\n });\n}\n\nfunction runResponseHook(span: Span, command: string, args: Array<string | Buffer>, result: unknown): void {\n const hook = currentResponseHook;\n if (!hook) return;\n try {\n hook(span, command, args as unknown as Parameters<typeof hook>[2], result);\n } catch {\n // never let user hooks break instrumentation\n }\n}\n\nfunction safeSerialize(command: string, args: Array<string | Buffer>): string | undefined {\n try {\n return defaultDbStatementSerializer(command, args);\n } catch {\n return undefined;\n }\n}\n\n// Test-only helper.\nexport function _resetRedisDiagnosticChannelsForTesting(): void {\n subscribed = false;\n currentResponseHook = undefined;\n}\n\n// Suppress unused-import lint when only used in types.\nexport type { TracingChannelContextWithSpan };\n"],"names":[],"mappings":"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"}
import { trace, context, SpanKind, diag, SpanStatusCode } from '@opentelemetry/api';
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
import { InstrumentationBase, semconvStabilityFromStr, InstrumentationNodeModuleDefinition, isWrapped, SemconvStability, safeExecuteInTheMiddle } from '@opentelemetry/instrumentation';
import { ATTR_DB_SYSTEM_NAME, ATTR_DB_QUERY_TEXT, ATTR_SERVER_ADDRESS, ATTR_SERVER_PORT } from '@opentelemetry/semantic-conventions';
import { defaultDbStatementSerializer } from './redis-common.js';
import { DB_SYSTEM_VALUE_REDIS, ATTR_DB_SYSTEM, ATTR_DB_STATEMENT, ATTR_DB_CONNECTION_STRING, DB_SYSTEM_NAME_VALUE_REDIS, ATTR_NET_PEER_NAME, ATTR_NET_PEER_PORT } from './semconv.js';
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE from the Sentry authors:
* - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-ioredis-v0.62.0/packages/instrumentation-ioredis
* - Upstream version: @opentelemetry/instrumentation-ioredis@0.62.0
* - Minor TypeScript adjustments for this repository's compiler settings
*/
/* eslint-disable -- vendored @opentelemetry/instrumentation-ioredis */
const PACKAGE_NAME = '@opentelemetry/instrumentation-ioredis';
const PACKAGE_VERSION = '0.62.0';
// ---- utils ----
function endSpan(span, err) {
if (err) {
span.recordException(err);
span.setStatus({
code: SpanStatusCode.ERROR,
message: err.message,
});
}
span.end();
}
// ---- IORedisInstrumentation ----
const DEFAULT_CONFIG = {
requireParentSpan: true,
};
class IORedisInstrumentation extends InstrumentationBase {
constructor(config = {}) {
super(PACKAGE_NAME, PACKAGE_VERSION, { ...DEFAULT_CONFIG, ...config });
this._setSemconvStabilityFromEnv();
}
_setSemconvStabilityFromEnv() {
this._netSemconvStability = semconvStabilityFromStr('http', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
this._dbSemconvStability = semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
setConfig(config = {}) {
super.setConfig({ ...DEFAULT_CONFIG, ...config });
}
init() {
return [
new InstrumentationNodeModuleDefinition(
'ioredis',
['>=2.0.0 <6'],
(module, moduleVersion) => {
const moduleExports =
module[Symbol.toStringTag] === 'Module'
? module.default // ESM
: module; // CommonJS
if (isWrapped(moduleExports.prototype.sendCommand)) {
this._unwrap(moduleExports.prototype, 'sendCommand');
}
this._wrap(moduleExports.prototype, 'sendCommand', this._patchSendCommand(moduleVersion));
if (isWrapped(moduleExports.prototype.connect)) {
this._unwrap(moduleExports.prototype, 'connect');
}
this._wrap(moduleExports.prototype, 'connect', this._patchConnection());
return module;
},
(module) => {
if (module === undefined) return;
const moduleExports =
module[Symbol.toStringTag] === 'Module'
? module.default // ESM
: module; // CommonJS
this._unwrap(moduleExports.prototype, 'sendCommand');
this._unwrap(moduleExports.prototype, 'connect');
},
),
];
}
_patchSendCommand(moduleVersion) {
return (original) => {
return this._traceSendCommand(original, moduleVersion);
};
}
_patchConnection() {
return (original) => {
return this._traceConnection(original);
};
}
_traceSendCommand(original, moduleVersion) {
const instrumentation = this;
return function ( cmd) {
if (arguments.length < 1 || typeof cmd !== 'object') {
return original.apply(this, arguments);
}
const config = instrumentation.getConfig();
const dbStatementSerializer = config.dbStatementSerializer || defaultDbStatementSerializer;
const hasNoParentSpan = trace.getSpan(context.active()) === undefined;
if (config.requireParentSpan === true && hasNoParentSpan) {
return original.apply(this, arguments);
}
const attributes = {};
const { host, port } = this.options;
const dbQueryText = dbStatementSerializer(cmd.name, cmd.args);
if (instrumentation._dbSemconvStability & SemconvStability.OLD) {
attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_REDIS;
attributes[ATTR_DB_STATEMENT] = dbQueryText;
attributes[ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;
}
if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {
attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_REDIS;
attributes[ATTR_DB_QUERY_TEXT] = dbQueryText;
}
if (instrumentation._netSemconvStability & SemconvStability.OLD) {
attributes[ATTR_NET_PEER_NAME] = host;
attributes[ATTR_NET_PEER_PORT] = port;
}
if (instrumentation._netSemconvStability & SemconvStability.STABLE) {
attributes[ATTR_SERVER_ADDRESS] = host;
attributes[ATTR_SERVER_PORT] = port;
}
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = instrumentation.tracer.startSpan(cmd.name, {
kind: SpanKind.CLIENT,
attributes,
});
const { requestHook } = config;
if (requestHook) {
safeExecuteInTheMiddle(
() =>
requestHook(span, {
moduleVersion,
cmdName: cmd.name,
cmdArgs: cmd.args,
}),
(e) => {
if (e) {
diag.error('ioredis instrumentation: request hook failed', e);
}
},
true,
);
}
try {
const result = original.apply(this, arguments);
const origResolve = cmd.resolve;
cmd.resolve = function (result) {
safeExecuteInTheMiddle(
() => config.responseHook?.(span, cmd.name, cmd.args, result),
(e) => {
if (e) {
diag.error('ioredis instrumentation: response hook failed', e);
}
},
true,
);
endSpan(span, null);
origResolve(result);
};
const origReject = cmd.reject;
cmd.reject = function (err) {
endSpan(span, err);
origReject(err);
};
return result;
} catch (error) {
endSpan(span, error );
throw error;
}
};
}
_traceConnection(original) {
const instrumentation = this;
return function () {
const hasNoParentSpan = trace.getSpan(context.active()) === undefined;
if (instrumentation.getConfig().requireParentSpan === true && hasNoParentSpan) {
return original.apply(this, arguments);
}
const attributes = {};
const { host, port } = this.options;
if (instrumentation._dbSemconvStability & SemconvStability.OLD) {
attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_REDIS;
attributes[ATTR_DB_STATEMENT] = 'connect';
attributes[ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;
}
if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {
attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_REDIS;
attributes[ATTR_DB_QUERY_TEXT] = 'connect';
}
if (instrumentation._netSemconvStability & SemconvStability.OLD) {
attributes[ATTR_NET_PEER_NAME] = host;
attributes[ATTR_NET_PEER_PORT] = port;
}
if (instrumentation._netSemconvStability & SemconvStability.STABLE) {
attributes[ATTR_SERVER_ADDRESS] = host;
attributes[ATTR_SERVER_PORT] = port;
}
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = instrumentation.tracer.startSpan('connect', {
kind: SpanKind.CLIENT,
attributes,
});
try {
const result = original.apply(this, arguments);
if (typeof result?.then === 'function') {
return result.then(
(value) => {
endSpan(span, null);
return value;
},
(error) => {
endSpan(span, error);
return Promise.reject(error);
},
);
}
endSpan(span, null);
return result;
} catch (error) {
endSpan(span, error );
throw error;
}
};
}
}
export { IORedisInstrumentation };
//# sourceMappingURL=ioredis-instrumentation.js.map
{"version":3,"file":"ioredis-instrumentation.js","sources":["../../../../../../src/integrations/tracing/redis/vendored/ioredis-instrumentation.ts"],"sourcesContent":["/*\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 * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-ioredis-v0.62.0/packages/instrumentation-ioredis\n * - Upstream version: @opentelemetry/instrumentation-ioredis@0.62.0\n * - Minor TypeScript adjustments for this repository's compiler settings\n */\n/* eslint-disable -- vendored @opentelemetry/instrumentation-ioredis */\n\nimport { context, diag, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';\nimport type { Span } from '@opentelemetry/api';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n isWrapped,\n safeExecuteInTheMiddle,\n SemconvStability,\n semconvStabilityFromStr,\n} from '@opentelemetry/instrumentation';\nimport {\n ATTR_DB_QUERY_TEXT,\n ATTR_DB_SYSTEM_NAME,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n} from '@opentelemetry/semantic-conventions';\n\nimport { defaultDbStatementSerializer } from './redis-common';\nimport {\n ATTR_DB_CONNECTION_STRING,\n ATTR_DB_STATEMENT,\n ATTR_DB_SYSTEM,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n DB_SYSTEM_NAME_VALUE_REDIS,\n DB_SYSTEM_VALUE_REDIS,\n} from './semconv';\nimport type { IORedisInstrumentationConfig } from './types';\n\nconst PACKAGE_NAME = '@opentelemetry/instrumentation-ioredis';\nconst PACKAGE_VERSION = '0.62.0';\n\n// ---- utils ----\n\nfunction endSpan(span: Span, err: Error | null | undefined): void {\n if (err) {\n span.recordException(err);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message,\n });\n }\n span.end();\n}\n\n// ---- IORedisInstrumentation ----\n\nconst DEFAULT_CONFIG: IORedisInstrumentationConfig = {\n requireParentSpan: true,\n};\n\nexport class IORedisInstrumentation extends InstrumentationBase<IORedisInstrumentationConfig> {\n _netSemconvStability!: SemconvStability;\n _dbSemconvStability!: SemconvStability;\n\n constructor(config: IORedisInstrumentationConfig = {}) {\n super(PACKAGE_NAME, PACKAGE_VERSION, { ...DEFAULT_CONFIG, ...config });\n this._setSemconvStabilityFromEnv();\n }\n\n _setSemconvStabilityFromEnv(): void {\n this._netSemconvStability = semconvStabilityFromStr('http', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n this._dbSemconvStability = semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n override setConfig(config: IORedisInstrumentationConfig = {}): void {\n super.setConfig({ ...DEFAULT_CONFIG, ...config });\n }\n\n init() {\n return [\n new InstrumentationNodeModuleDefinition(\n 'ioredis',\n ['>=2.0.0 <6'],\n (module: any, moduleVersion?: string) => {\n const moduleExports =\n module[Symbol.toStringTag] === 'Module'\n ? module.default // ESM\n : module; // CommonJS\n if (isWrapped(moduleExports.prototype.sendCommand)) {\n this._unwrap(moduleExports.prototype, 'sendCommand');\n }\n this._wrap(moduleExports.prototype, 'sendCommand', this._patchSendCommand(moduleVersion));\n if (isWrapped(moduleExports.prototype.connect)) {\n this._unwrap(moduleExports.prototype, 'connect');\n }\n this._wrap(moduleExports.prototype, 'connect', this._patchConnection());\n return module;\n },\n (module: any) => {\n if (module === undefined) return;\n const moduleExports =\n module[Symbol.toStringTag] === 'Module'\n ? module.default // ESM\n : module; // CommonJS\n this._unwrap(moduleExports.prototype, 'sendCommand');\n this._unwrap(moduleExports.prototype, 'connect');\n },\n ),\n ];\n }\n\n private _patchSendCommand(moduleVersion?: string) {\n return (original: Function) => {\n return this._traceSendCommand(original, moduleVersion);\n };\n }\n\n private _patchConnection() {\n return (original: Function) => {\n return this._traceConnection(original);\n };\n }\n\n private _traceSendCommand(original: Function, moduleVersion?: string) {\n const instrumentation = this;\n return function (this: any, cmd: any) {\n if (arguments.length < 1 || typeof cmd !== 'object') {\n return original.apply(this, arguments);\n }\n const config = instrumentation.getConfig();\n const dbStatementSerializer = config.dbStatementSerializer || defaultDbStatementSerializer;\n const hasNoParentSpan = trace.getSpan(context.active()) === undefined;\n if (config.requireParentSpan === true && hasNoParentSpan) {\n return original.apply(this, arguments);\n }\n const attributes: Record<string, any> = {};\n const { host, port } = this.options;\n const dbQueryText = dbStatementSerializer(cmd.name, cmd.args);\n if (instrumentation._dbSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_REDIS;\n attributes[ATTR_DB_STATEMENT] = dbQueryText;\n attributes[ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;\n }\n if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {\n attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_REDIS;\n attributes[ATTR_DB_QUERY_TEXT] = dbQueryText;\n }\n if (instrumentation._netSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_NET_PEER_NAME] = host;\n attributes[ATTR_NET_PEER_PORT] = port;\n }\n if (instrumentation._netSemconvStability & SemconvStability.STABLE) {\n attributes[ATTR_SERVER_ADDRESS] = host;\n attributes[ATTR_SERVER_PORT] = port;\n }\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = instrumentation.tracer.startSpan(cmd.name, {\n kind: SpanKind.CLIENT,\n attributes,\n });\n const { requestHook } = config;\n if (requestHook) {\n safeExecuteInTheMiddle(\n () =>\n requestHook(span, {\n moduleVersion,\n cmdName: cmd.name,\n cmdArgs: cmd.args,\n }),\n (e: Error | undefined) => {\n if (e) {\n diag.error('ioredis instrumentation: request hook failed', e);\n }\n },\n true,\n );\n }\n try {\n const result = original.apply(this, arguments);\n const origResolve = cmd.resolve;\n cmd.resolve = function (result: unknown) {\n safeExecuteInTheMiddle(\n () => config.responseHook?.(span, cmd.name, cmd.args, result),\n (e: Error | undefined) => {\n if (e) {\n diag.error('ioredis instrumentation: response hook failed', e);\n }\n },\n true,\n );\n endSpan(span, null);\n origResolve(result);\n };\n const origReject = cmd.reject;\n cmd.reject = function (err: Error) {\n endSpan(span, err);\n origReject(err);\n };\n return result;\n } catch (error) {\n endSpan(span, error as Error);\n throw error;\n }\n };\n }\n\n private _traceConnection(original: Function) {\n const instrumentation = this;\n return function (this: any) {\n const hasNoParentSpan = trace.getSpan(context.active()) === undefined;\n if (instrumentation.getConfig().requireParentSpan === true && hasNoParentSpan) {\n return original.apply(this, arguments);\n }\n const attributes: Record<string, any> = {};\n const { host, port } = this.options;\n if (instrumentation._dbSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_DB_SYSTEM] = DB_SYSTEM_VALUE_REDIS;\n attributes[ATTR_DB_STATEMENT] = 'connect';\n attributes[ATTR_DB_CONNECTION_STRING] = `redis://${host}:${port}`;\n }\n if (instrumentation._dbSemconvStability & SemconvStability.STABLE) {\n attributes[ATTR_DB_SYSTEM_NAME] = DB_SYSTEM_NAME_VALUE_REDIS;\n attributes[ATTR_DB_QUERY_TEXT] = 'connect';\n }\n if (instrumentation._netSemconvStability & SemconvStability.OLD) {\n attributes[ATTR_NET_PEER_NAME] = host;\n attributes[ATTR_NET_PEER_PORT] = port;\n }\n if (instrumentation._netSemconvStability & SemconvStability.STABLE) {\n attributes[ATTR_SERVER_ADDRESS] = host;\n attributes[ATTR_SERVER_PORT] = port;\n }\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = instrumentation.tracer.startSpan('connect', {\n kind: SpanKind.CLIENT,\n attributes,\n });\n try {\n const result = original.apply(this, arguments);\n if (typeof result?.then === 'function') {\n return result.then(\n (value: unknown) => {\n endSpan(span, null);\n return value;\n },\n (error: Error) => {\n endSpan(span, error);\n return Promise.reject(error);\n },\n );\n }\n endSpan(span, null);\n return result;\n } catch (error) {\n endSpan(span, error as Error);\n throw error;\n }\n };\n }\n}\n"],"names":[],"mappings":"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"}
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE from the Sentry authors:
* - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/redis-common
* - Upstream version: @opentelemetry/redis-common@0.38.2
* - Minor TypeScript adjustments for this repository's compiler settings
*/
/* eslint-disable -- vendored @opentelemetry/redis-common */
/**
* List of regexes and the number of arguments that should be serialized for matching commands.
* For example, HSET should serialize which key and field it's operating on, but not its value.
* Setting the subset to -1 will serialize all arguments.
* Commands without a match will have their first argument serialized.
*
* Refer to https://redis.io/commands/ for the full list.
*/
const serializationSubsets = [
{
regex: /^ECHO/i,
args: 0,
},
{
regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i,
args: 1,
},
{
regex: /^(HSET|HMSET|LSET|LINSERT)/i,
args: 2,
},
{
regex:
/^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i,
args: -1,
},
];
/**
* Given the redis command name and arguments, return a combination of the
* command name + the allowed arguments according to `serializationSubsets`.
*/
const defaultDbStatementSerializer = (
cmdName,
cmdArgs,
) => {
if (Array.isArray(cmdArgs) && cmdArgs.length) {
const nArgsToSerialize = serializationSubsets.find(({ regex }) => regex.test(cmdName))?.args ?? 0;
const argsToSerialize =
nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs.slice();
if (cmdArgs.length > argsToSerialize.length) {
argsToSerialize.push(`[${cmdArgs.length - nArgsToSerialize} other arguments]`);
}
return `${cmdName} ${argsToSerialize.join(' ')}`;
}
return cmdName;
};
export { defaultDbStatementSerializer };
//# sourceMappingURL=redis-common.js.map
{"version":3,"file":"redis-common.js","sources":["../../../../../../src/integrations/tracing/redis/vendored/redis-common.ts"],"sourcesContent":["/*\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 * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/redis-common\n * - Upstream version: @opentelemetry/redis-common@0.38.2\n * - Minor TypeScript adjustments for this repository's compiler settings\n */\n/* eslint-disable -- vendored @opentelemetry/redis-common */\n\n/**\n * List of regexes and the number of arguments that should be serialized for matching commands.\n * For example, HSET should serialize which key and field it's operating on, but not its value.\n * Setting the subset to -1 will serialize all arguments.\n * Commands without a match will have their first argument serialized.\n *\n * Refer to https://redis.io/commands/ for the full list.\n */\nconst serializationSubsets = [\n {\n regex: /^ECHO/i,\n args: 0,\n },\n {\n regex: /^(LPUSH|MSET|PFA|PUBLISH|RPUSH|SADD|SET|SPUBLISH|XADD|ZADD)/i,\n args: 1,\n },\n {\n regex: /^(HSET|HMSET|LSET|LINSERT)/i,\n args: 2,\n },\n {\n regex:\n /^(ACL|BIT|B[LRZ]|CLIENT|CLUSTER|CONFIG|COMMAND|DECR|DEL|EVAL|EX|FUNCTION|GEO|GET|HINCR|HMGET|HSCAN|INCR|L[TRLM]|MEMORY|P[EFISTU]|RPOP|S[CDIMORSU]|XACK|X[CDGILPRT]|Z[CDILMPRS])/i,\n args: -1,\n },\n];\n\n/**\n * Given the redis command name and arguments, return a combination of the\n * command name + the allowed arguments according to `serializationSubsets`.\n */\nexport const defaultDbStatementSerializer = (\n cmdName: string,\n cmdArgs: Array<string | Buffer | number | any[]>,\n): string => {\n if (Array.isArray(cmdArgs) && cmdArgs.length) {\n const nArgsToSerialize = serializationSubsets.find(({ regex }) => regex.test(cmdName))?.args ?? 0;\n const argsToSerialize: Array<string | Buffer | number | any[]> =\n nArgsToSerialize >= 0 ? cmdArgs.slice(0, nArgsToSerialize) : cmdArgs.slice();\n if (cmdArgs.length > argsToSerialize.length) {\n argsToSerialize.push(`[${cmdArgs.length - nArgsToSerialize} other arguments]`);\n }\n return `${cmdName} ${argsToSerialize.join(' ')}`;\n }\n return cmdName;\n};\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,uBAAuB;AAC7B,EAAE;AACF,IAAI,KAAK,EAAE,QAAQ;AACnB,IAAI,IAAI,EAAE,CAAC;AACX,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,8DAA8D;AACzE,IAAI,IAAI,EAAE,CAAC;AACX,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,6BAA6B;AACxC,IAAI,IAAI,EAAE,CAAC;AACX,GAAG;AACH,EAAE;AACF,IAAI,KAAK;AACT,MAAM,kLAAkL;AACxL,IAAI,IAAI,EAAE,EAAE;AACZ,GAAG;AACH,CAAC;;AAED;AACA;AACA;AACA;AACO,MAAM,+BAA+B;AAC5C,EAAE,OAAO;AACT,EAAE,OAAO;AACT,KAAa;AACb,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAA,IAAK,OAAO,CAAC,MAAM,EAAE;AAChD,IAAI,MAAM,mBAAmB,oBAAoB,CAAC,IAAI,CAAC,CAAC,EAAE,KAAA,EAAO,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,IAAA,IAAQ,CAAC;AACrG,IAAI,MAAM,eAAe;AACzB,MAAM,oBAAoB,CAAA,GAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAA,GAAI,OAAO,CAAC,KAAK,EAAE;AAClF,IAAI,IAAI,OAAO,CAAC,SAAS,eAAe,CAAC,MAAM,EAAE;AACjD,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;AACpF,IAAI;AACJ,IAAI,OAAO,CAAC,EAAA,OAAA,CAAA,CAAA,EAAA,eAAA,CAAA,IAAA,CAAA,GAAA,CAAA,CAAA,CAAA;AACA,EAAA;AACA,EAAA,OAAA,OAAA;AACA;;;;"}
import { trace, context, SpanKind, SpanStatusCode } from '@opentelemetry/api';
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
import { InstrumentationBase, semconvStabilityFromStr, InstrumentationNodeModuleDefinition, isWrapped, SemconvStability, safeExecuteInTheMiddle, InstrumentationNodeModuleFile } from '@opentelemetry/instrumentation';
import { ATTR_DB_QUERY_TEXT, ATTR_DB_OPERATION_NAME, ATTR_DB_SYSTEM_NAME, ATTR_SERVER_PORT, ATTR_SERVER_ADDRESS } from '@opentelemetry/semantic-conventions';
import { defaultDbStatementSerializer } from './redis-common.js';
import { DB_SYSTEM_VALUE_REDIS, ATTR_DB_STATEMENT, ATTR_DB_SYSTEM, DB_SYSTEM_NAME_VALUE_REDIS, ATTR_NET_PEER_PORT, ATTR_NET_PEER_NAME, ATTR_DB_CONNECTION_STRING } from './semconv.js';
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE from the Sentry authors:
* - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/instrumentation-redis
* - Upstream version: @opentelemetry/instrumentation-redis@0.62.0
* - Minor TypeScript adjustments for this repository's compiler settings
*/
/* eslint-disable -- vendored @opentelemetry/instrumentation-redis */
const PACKAGE_NAME = '@opentelemetry/instrumentation-redis';
const PACKAGE_VERSION = '0.62.0';
// ---- Internal types ----
const OTEL_OPEN_SPANS = Symbol('opentelemetry.instrumentation.redis.open_spans');
const MULTI_COMMAND_OPTIONS = Symbol('opentelemetry.instrumentation.redis.multi_command_options');
// ---- v4-v5 utils ----
function removeCredentialsFromDBConnectionStringAttribute(
diagLogger,
url,
) {
if (typeof url !== 'string' || !url) {
return undefined;
}
try {
const u = new URL(url);
u.searchParams.delete('user_pwd');
u.username = '';
u.password = '';
return u.href;
} catch (err) {
diagLogger.error('failed to sanitize redis connection url', err);
}
return undefined;
}
function getClientAttributes(
diagLogger,
options,
semconvStability,
) {
const attributes = {};
if (semconvStability & SemconvStability.OLD) {
Object.assign(attributes, {
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,
[ATTR_NET_PEER_NAME]: options?.socket?.host,
[ATTR_NET_PEER_PORT]: options?.socket?.port,
[ATTR_DB_CONNECTION_STRING]: removeCredentialsFromDBConnectionStringAttribute(diagLogger, options?.url),
});
}
if (semconvStability & SemconvStability.STABLE) {
Object.assign(attributes, {
[ATTR_DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_REDIS,
[ATTR_SERVER_ADDRESS]: options?.socket?.host,
[ATTR_SERVER_PORT]: options?.socket?.port,
});
}
return attributes;
}
// ---- v2-v3 utils ----
function endSpanV2(span, err) {
if (err) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: err.message,
});
}
span.end();
}
function getTracedCreateClient(original) {
return function createClientTrace() {
const client = original.apply(this, arguments);
return context.bind(context.active(), client);
};
}
function getTracedCreateStreamTrace(original) {
return function create_stream_trace() {
if (!Object.prototype.hasOwnProperty.call(this, 'stream')) {
Object.defineProperty(this, 'stream', {
get() {
return this._patched_redis_stream;
},
set(val) {
context.bind(context.active(), val);
this._patched_redis_stream = val;
},
});
}
return original.apply(this, arguments);
};
}
// ---- RedisInstrumentationV2_V3 ----
class RedisInstrumentationV2_V3 extends InstrumentationBase {
static __initStatic() {this.COMPONENT = 'redis';}
constructor(config = {}) {
super(PACKAGE_NAME, PACKAGE_VERSION, config);
this._semconvStability = config.semconvStability
? config.semconvStability
: semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
setConfig(config = {}) {
super.setConfig(config);
this._semconvStability = config.semconvStability
? config.semconvStability
: semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
init() {
return [
new InstrumentationNodeModuleDefinition(
'redis',
['>=2.6.0 <4'],
(moduleExports) => {
if (isWrapped(moduleExports.RedisClient.prototype['internal_send_command'])) {
this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');
}
this._wrap(moduleExports.RedisClient.prototype, 'internal_send_command', this._getPatchInternalSendCommand());
if (isWrapped(moduleExports.RedisClient.prototype['create_stream'])) {
this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');
}
this._wrap(moduleExports.RedisClient.prototype, 'create_stream', this._getPatchCreateStream());
if (isWrapped(moduleExports.createClient)) {
this._unwrap(moduleExports, 'createClient');
}
this._wrap(moduleExports, 'createClient', this._getPatchCreateClient());
return moduleExports;
},
(moduleExports) => {
if (moduleExports === undefined) return;
this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');
this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');
this._unwrap(moduleExports, 'createClient');
},
),
];
}
_getPatchInternalSendCommand() {
const instrumentation = this;
return function internal_send_command(original) {
return function internal_send_command_trace( cmd) {
if (arguments.length !== 1 || typeof cmd !== 'object') {
return original.apply(this, arguments);
}
const config = instrumentation.getConfig();
const hasNoParentSpan = trace.getSpan(context.active()) === undefined;
if (config.requireParentSpan === true && hasNoParentSpan) {
return original.apply(this, arguments);
}
const dbStatementSerializer = config?.dbStatementSerializer || defaultDbStatementSerializer;
const attributes = {};
if (instrumentation._semconvStability & SemconvStability.OLD) {
Object.assign(attributes, {
[ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,
[ATTR_DB_STATEMENT]: dbStatementSerializer(cmd.command, cmd.args),
});
}
if (instrumentation._semconvStability & SemconvStability.STABLE) {
Object.assign(attributes, {
[ATTR_DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_REDIS,
[ATTR_DB_OPERATION_NAME]: cmd.command,
[ATTR_DB_QUERY_TEXT]: dbStatementSerializer(cmd.command, cmd.args),
});
}
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = instrumentation.tracer.startSpan(`${RedisInstrumentationV2_V3.COMPONENT}-${cmd.command}`, {
kind: SpanKind.CLIENT,
attributes,
});
if (this.connection_options) {
const connectionAttributes = {};
if (instrumentation._semconvStability & SemconvStability.OLD) {
Object.assign(connectionAttributes, {
[ATTR_NET_PEER_NAME]: this.connection_options.host,
[ATTR_NET_PEER_PORT]: this.connection_options.port,
});
}
if (instrumentation._semconvStability & SemconvStability.STABLE) {
Object.assign(connectionAttributes, {
[ATTR_SERVER_ADDRESS]: this.connection_options.host,
[ATTR_SERVER_PORT]: this.connection_options.port,
});
}
span.setAttributes(connectionAttributes);
}
if (this.address && instrumentation._semconvStability & SemconvStability.OLD) {
span.setAttribute(ATTR_DB_CONNECTION_STRING, `redis://${this.address}`);
}
const originalCallback = arguments[0].callback;
if (originalCallback) {
const originalContext = context.active();
arguments[0].callback = function callback( err, reply) {
if (config?.responseHook) {
const responseHook = config.responseHook;
safeExecuteInTheMiddle(
() => {
responseHook(span, cmd.command, cmd.args, reply);
},
(e) => {
if (e) {
instrumentation._diag.error('Error executing responseHook', e);
}
},
true,
);
}
endSpanV2(span, err);
return context.with(originalContext, originalCallback, this, ...arguments);
};
}
try {
return original.apply(this, arguments);
} catch (rethrow) {
endSpanV2(span, rethrow );
throw rethrow;
}
};
};
}
_getPatchCreateClient() {
return function createClient(original) {
return getTracedCreateClient(original);
};
}
_getPatchCreateStream() {
return function createReadStream(original) {
return getTracedCreateStreamTrace(original);
};
}
} RedisInstrumentationV2_V3.__initStatic();
// ---- RedisInstrumentationV4_V5 ----
class RedisInstrumentationV4_V5 extends InstrumentationBase {
static __initStatic2() {this.COMPONENT = 'redis';}
constructor(config = {}) {
super(PACKAGE_NAME, PACKAGE_VERSION, config);
this._semconvStability = config.semconvStability
? config.semconvStability
: semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
setConfig(config = {}) {
super.setConfig(config);
this._semconvStability = config.semconvStability
? config.semconvStability
: semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
}
init() {
return [
this._getInstrumentationNodeModuleDefinition('@redis/client'),
this._getInstrumentationNodeModuleDefinition('@node-redis/client'),
];
}
_getInstrumentationNodeModuleDefinition(basePackageName) {
const commanderModuleFile = new InstrumentationNodeModuleFile(
`${basePackageName}/dist/lib/commander.js`,
['^1.0.0'],
(moduleExports, moduleVersion) => {
const transformCommandArguments = moduleExports.transformCommandArguments;
if (!transformCommandArguments) {
this._diag.error('internal instrumentation error, missing transformCommandArguments function');
return moduleExports;
}
const functionToPatch = moduleVersion?.startsWith('1.0.') ? 'extendWithCommands' : 'attachCommands';
if (isWrapped(moduleExports?.[functionToPatch])) {
this._unwrap(moduleExports, functionToPatch);
}
this._wrap(moduleExports, functionToPatch, this._getPatchExtendWithCommands(transformCommandArguments));
return moduleExports;
},
(moduleExports) => {
if (isWrapped(moduleExports?.extendWithCommands)) {
this._unwrap(moduleExports, 'extendWithCommands');
}
if (isWrapped(moduleExports?.attachCommands)) {
this._unwrap(moduleExports, 'attachCommands');
}
},
);
const multiCommanderModule = new InstrumentationNodeModuleFile(
`${basePackageName}/dist/lib/client/multi-command.js`,
['^1.0.0', '>=5.0.0 <5.12.0'],
(moduleExports) => {
const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;
if (isWrapped(redisClientMultiCommandPrototype?.exec)) {
this._unwrap(redisClientMultiCommandPrototype, 'exec');
}
this._wrap(redisClientMultiCommandPrototype, 'exec', this._getPatchMultiCommandsExec(false));
if (isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {
this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');
}
this._wrap(redisClientMultiCommandPrototype, 'execAsPipeline', this._getPatchMultiCommandsExec(true));
if (isWrapped(redisClientMultiCommandPrototype?.addCommand)) {
this._unwrap(redisClientMultiCommandPrototype, 'addCommand');
}
this._wrap(redisClientMultiCommandPrototype, 'addCommand', this._getPatchMultiCommandsAddCommand());
return moduleExports;
},
(moduleExports) => {
const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;
if (isWrapped(redisClientMultiCommandPrototype?.exec)) {
this._unwrap(redisClientMultiCommandPrototype, 'exec');
}
if (isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {
this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');
}
if (isWrapped(redisClientMultiCommandPrototype?.addCommand)) {
this._unwrap(redisClientMultiCommandPrototype, 'addCommand');
}
},
);
const clientIndexModule = new InstrumentationNodeModuleFile(
`${basePackageName}/dist/lib/client/index.js`,
['^1.0.0', '>=5.0.0 <5.12.0'],
(moduleExports) => {
const redisClientPrototype = moduleExports?.default?.prototype;
if (redisClientPrototype?.multi) {
if (isWrapped(redisClientPrototype?.multi)) {
this._unwrap(redisClientPrototype, 'multi');
}
this._wrap(redisClientPrototype, 'multi', this._getPatchRedisClientMulti());
}
if (redisClientPrototype?.MULTI) {
if (isWrapped(redisClientPrototype?.MULTI)) {
this._unwrap(redisClientPrototype, 'MULTI');
}
this._wrap(redisClientPrototype, 'MULTI', this._getPatchRedisClientMulti());
}
if (isWrapped(redisClientPrototype?.sendCommand)) {
this._unwrap(redisClientPrototype, 'sendCommand');
}
this._wrap(redisClientPrototype, 'sendCommand', this._getPatchRedisClientSendCommand());
if (isWrapped(redisClientPrototype?.connect)) {
this._unwrap(redisClientPrototype, 'connect');
}
this._wrap(redisClientPrototype, 'connect', this._getPatchedClientConnect());
return moduleExports;
},
(moduleExports) => {
const redisClientPrototype = moduleExports?.default?.prototype;
if (isWrapped(redisClientPrototype?.multi)) {
this._unwrap(redisClientPrototype, 'multi');
}
if (isWrapped(redisClientPrototype?.MULTI)) {
this._unwrap(redisClientPrototype, 'MULTI');
}
if (isWrapped(redisClientPrototype?.sendCommand)) {
this._unwrap(redisClientPrototype, 'sendCommand');
}
if (isWrapped(redisClientPrototype?.connect)) {
this._unwrap(redisClientPrototype, 'connect');
}
},
);
return new InstrumentationNodeModuleDefinition(
basePackageName,
['^1.0.0', '>=5.0.0 <5.12.0'],
(moduleExports) => moduleExports,
() => {},
[commanderModuleFile, multiCommanderModule, clientIndexModule],
);
}
_getPatchExtendWithCommands(transformCommandArguments) {
const plugin = this;
return function extendWithCommandsPatchWrapper(original) {
return function extendWithCommandsPatch( config) {
if (config?.BaseClass?.name !== 'RedisClient') {
return original.apply(this, arguments);
}
const origExecutor = config.executor;
config.executor = function ( command, args) {
const redisCommandArguments = transformCommandArguments(command, args).args;
return plugin._traceClientCommand(origExecutor, this, arguments, redisCommandArguments);
};
return original.apply(this, arguments);
};
};
}
_getPatchMultiCommandsExec(isPipeline) {
const plugin = this;
return function execPatchWrapper(original) {
return function execPatch() {
const execRes = original.apply(this, arguments);
if (typeof execRes?.then !== 'function') {
plugin._diag.error('non-promise result when patching exec/execAsPipeline');
return execRes;
}
return execRes
.then((redisRes) => {
const openSpans = this[OTEL_OPEN_SPANS];
plugin._endSpansWithRedisReplies(openSpans, redisRes, isPipeline);
return redisRes;
})
.catch((err) => {
const openSpans = this[OTEL_OPEN_SPANS];
if (!openSpans) {
plugin._diag.error('cannot find open spans to end for multi/pipeline');
} else {
const replies =
err.constructor.name === 'MultiErrorReply'
? (err ).replies
: new Array(openSpans.length).fill(err);
plugin._endSpansWithRedisReplies(openSpans, replies, isPipeline);
}
return Promise.reject(err);
});
};
};
}
_getPatchMultiCommandsAddCommand() {
const plugin = this;
return function addCommandWrapper(original) {
return function addCommandPatch( args) {
return plugin._traceClientCommand(original, this, arguments, args);
};
};
}
_getPatchRedisClientMulti() {
return function multiPatchWrapper(original) {
return function multiPatch() {
const multiRes = original.apply(this, arguments);
multiRes[MULTI_COMMAND_OPTIONS] = this.options;
return multiRes;
};
};
}
_getPatchRedisClientSendCommand() {
const plugin = this;
return function sendCommandWrapper(original) {
return function sendCommandPatch( args) {
return plugin._traceClientCommand(original, this, arguments, args);
};
};
}
_getPatchedClientConnect() {
const plugin = this;
return function connectWrapper(original) {
return function patchedConnect() {
const options = this.options;
const attributes = getClientAttributes(plugin._diag, options, plugin._semconvStability);
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = plugin.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-connect`, {
kind: SpanKind.CLIENT,
attributes,
});
const res = context.with(trace.setSpan(context.active(), span), () => {
return original.apply(this);
});
return res
.then((result) => {
span.end();
return result;
})
.catch((error) => {
span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message,
});
span.end();
return Promise.reject(error);
});
};
};
}
_traceClientCommand(
origFunction,
origThis,
origArguments,
redisCommandArguments,
) {
const hasNoParentSpan = trace.getSpan(context.active()) === undefined;
if (hasNoParentSpan && this.getConfig().requireParentSpan) {
return origFunction.apply(origThis, origArguments);
}
const clientOptions = origThis.options || origThis[MULTI_COMMAND_OPTIONS];
const commandName = redisCommandArguments[0] ;
const commandArgs = redisCommandArguments.slice(1);
const dbStatementSerializer = this.getConfig().dbStatementSerializer || defaultDbStatementSerializer;
const attributes = getClientAttributes(this._diag, clientOptions, this._semconvStability);
if (this._semconvStability & SemconvStability.STABLE) {
attributes[ATTR_DB_OPERATION_NAME] = commandName;
}
try {
const dbStatement = dbStatementSerializer(commandName, commandArgs);
if (dbStatement != null) {
if (this._semconvStability & SemconvStability.OLD) {
attributes[ATTR_DB_STATEMENT] = dbStatement;
}
if (this._semconvStability & SemconvStability.STABLE) {
attributes[ATTR_DB_QUERY_TEXT] = dbStatement;
}
}
} catch (e) {
this._diag.error('dbStatementSerializer throw an exception', e, { commandName });
}
attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
const span = this.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-${commandName}`, {
kind: SpanKind.CLIENT,
attributes,
});
const res = context.with(trace.setSpan(context.active(), span), () => {
return origFunction.apply(origThis, origArguments);
});
if (typeof res?.then === 'function') {
res.then(
(redisRes) => {
this._endSpanWithResponse(span, commandName, commandArgs, redisRes, undefined);
},
(err) => {
this._endSpanWithResponse(span, commandName, commandArgs, null, err);
},
);
} else {
const redisClientMultiCommand = res;
redisClientMultiCommand[OTEL_OPEN_SPANS] = redisClientMultiCommand[OTEL_OPEN_SPANS] || [];
redisClientMultiCommand[OTEL_OPEN_SPANS].push({
span,
commandName,
commandArgs,
});
}
return res;
}
_endSpansWithRedisReplies(openSpans, replies, isPipeline = false) {
if (!openSpans) {
return this._diag.error('cannot find open spans to end for redis multi/pipeline');
}
if (replies.length !== openSpans.length) {
return this._diag.error('number of multi command spans does not match response from redis');
}
const allCommands = openSpans.map(s => s.commandName);
const allSameCommand = allCommands.every(cmd => cmd === allCommands[0]);
const operationName = allSameCommand
? (isPipeline ? 'PIPELINE ' : 'MULTI ') + allCommands[0]
: isPipeline
? 'PIPELINE'
: 'MULTI';
for (let i = 0; i < openSpans.length; i++) {
const { span, commandArgs } = openSpans[i];
const currCommandRes = replies[i];
const [res, err] = currCommandRes instanceof Error ? [null, currCommandRes] : [currCommandRes, undefined];
if (this._semconvStability & SemconvStability.STABLE) {
span.setAttribute(ATTR_DB_OPERATION_NAME, operationName);
}
this._endSpanWithResponse(span, allCommands[i], commandArgs, res, err);
}
}
_endSpanWithResponse(
span,
commandName,
commandArgs,
response,
error,
) {
const { responseHook } = this.getConfig();
if (!error && responseHook) {
try {
responseHook(span, commandName, commandArgs, response);
} catch (err) {
this._diag.error('responseHook throw an exception', err);
}
}
if (error) {
span.recordException(error);
span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message });
}
span.end();
}
} RedisInstrumentationV4_V5.__initStatic2();
// ---- RedisInstrumentation (wrapper) ----
const DEFAULT_CONFIG = {
requireParentSpan: false,
};
class RedisInstrumentation extends InstrumentationBase {
__init() {this.initialized = false;}
constructor(config = {}) {
const resolvedConfig = { ...DEFAULT_CONFIG, ...config };
super(PACKAGE_NAME, PACKAGE_VERSION, resolvedConfig);RedisInstrumentation.prototype.__init.call(this); this.instrumentationV2_V3 = new RedisInstrumentationV2_V3(this.getConfig());
this.instrumentationV4_V5 = new RedisInstrumentationV4_V5(this.getConfig());
this.initialized = true;
}
setConfig(config = {}) {
const newConfig = { ...DEFAULT_CONFIG, ...config };
super.setConfig(newConfig);
if (!this.initialized) {
return;
}
this.instrumentationV2_V3.setConfig(newConfig);
this.instrumentationV4_V5.setConfig(newConfig);
}
init() {}
getModuleDefinitions() {
return [...this.instrumentationV2_V3.getModuleDefinitions(), ...this.instrumentationV4_V5.getModuleDefinitions()];
}
setTracerProvider(tracerProvider) {
super.setTracerProvider(tracerProvider);
if (!this.initialized) {
return;
}
this.instrumentationV2_V3.setTracerProvider(tracerProvider);
this.instrumentationV4_V5.setTracerProvider(tracerProvider);
}
enable() {
super.enable();
if (!this.initialized) {
return;
}
this.instrumentationV2_V3.enable();
this.instrumentationV4_V5.enable();
}
disable() {
super.disable();
if (!this.initialized) {
return;
}
this.instrumentationV2_V3.disable();
this.instrumentationV4_V5.disable();
}
}
export { RedisInstrumentation };
//# sourceMappingURL=redis-instrumentation.js.map
{"version":3,"file":"redis-instrumentation.js","sources":["../../../../../../src/integrations/tracing/redis/vendored/redis-instrumentation.ts"],"sourcesContent":["/*\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 * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/instrumentation-redis\n * - Upstream version: @opentelemetry/instrumentation-redis@0.62.0\n * - Minor TypeScript adjustments for this repository's compiler settings\n */\n/* eslint-disable -- vendored @opentelemetry/instrumentation-redis */\n\nimport { context, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';\nimport type { DiagLogger, Span, TracerProvider } from '@opentelemetry/api';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n InstrumentationNodeModuleFile,\n isWrapped,\n safeExecuteInTheMiddle,\n SemconvStability,\n semconvStabilityFromStr,\n} from '@opentelemetry/instrumentation';\nimport {\n ATTR_DB_OPERATION_NAME,\n ATTR_DB_QUERY_TEXT,\n ATTR_DB_SYSTEM_NAME,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n} from '@opentelemetry/semantic-conventions';\n\nimport { defaultDbStatementSerializer } from './redis-common';\nimport {\n ATTR_DB_CONNECTION_STRING,\n ATTR_DB_STATEMENT,\n ATTR_DB_SYSTEM,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n DB_SYSTEM_NAME_VALUE_REDIS,\n DB_SYSTEM_VALUE_REDIS,\n} from './semconv';\nimport type { RedisInstrumentationConfig } from './types';\n\nconst PACKAGE_NAME = '@opentelemetry/instrumentation-redis';\nconst PACKAGE_VERSION = '0.62.0';\n\n// ---- Internal types ----\n\ninterface RedisPluginClientTypes {\n connection_options?: {\n port?: string | number;\n host?: string;\n };\n address?: string;\n}\n\ninterface RedisCommand {\n command: string;\n args: string[];\n buffer_args: boolean;\n callback: (err: Error | null, reply: unknown) => void;\n call_on_write: boolean;\n}\n\ninterface MultiErrorReply extends Error {\n replies: unknown[];\n errorIndexes: Array<number>;\n}\n\ninterface OpenSpanInfo {\n span: Span;\n commandName: string;\n commandArgs: Array<string | Buffer>;\n}\n\nconst OTEL_OPEN_SPANS = Symbol('opentelemetry.instrumentation.redis.open_spans');\nconst MULTI_COMMAND_OPTIONS = Symbol('opentelemetry.instrumentation.redis.multi_command_options');\n\n// ---- v4-v5 utils ----\n\nfunction removeCredentialsFromDBConnectionStringAttribute(\n diagLogger: DiagLogger,\n url: string | undefined,\n): string | undefined {\n if (typeof url !== 'string' || !url) {\n return undefined;\n }\n try {\n const u = new URL(url);\n u.searchParams.delete('user_pwd');\n u.username = '';\n u.password = '';\n return u.href;\n } catch (err) {\n diagLogger.error('failed to sanitize redis connection url', err);\n }\n return undefined;\n}\n\nfunction getClientAttributes(\n diagLogger: DiagLogger,\n options: any,\n semconvStability: SemconvStability,\n): Record<string, any> {\n const attributes: Record<string, any> = {};\n if (semconvStability & SemconvStability.OLD) {\n Object.assign(attributes, {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n [ATTR_NET_PEER_NAME]: options?.socket?.host,\n [ATTR_NET_PEER_PORT]: options?.socket?.port,\n [ATTR_DB_CONNECTION_STRING]: removeCredentialsFromDBConnectionStringAttribute(diagLogger, options?.url),\n });\n }\n if (semconvStability & SemconvStability.STABLE) {\n Object.assign(attributes, {\n [ATTR_DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_REDIS,\n [ATTR_SERVER_ADDRESS]: options?.socket?.host,\n [ATTR_SERVER_PORT]: options?.socket?.port,\n });\n }\n return attributes;\n}\n\n// ---- v2-v3 utils ----\n\nfunction endSpanV2(span: Span, err: Error | null | undefined): void {\n if (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message,\n });\n }\n span.end();\n}\n\nfunction getTracedCreateClient(original: Function): Function {\n return function createClientTrace(this: any) {\n const client = original.apply(this, arguments);\n return context.bind(context.active(), client);\n };\n}\n\nfunction getTracedCreateStreamTrace(original: Function): Function {\n return function create_stream_trace(this: any) {\n if (!Object.prototype.hasOwnProperty.call(this, 'stream')) {\n Object.defineProperty(this, 'stream', {\n get() {\n return this._patched_redis_stream;\n },\n set(val: any) {\n context.bind(context.active(), val);\n this._patched_redis_stream = val;\n },\n });\n }\n return original.apply(this, arguments);\n };\n}\n\n// ---- RedisInstrumentationV2_V3 ----\n\nclass RedisInstrumentationV2_V3 extends InstrumentationBase<RedisInstrumentationConfig> {\n static COMPONENT = 'redis';\n _semconvStability: SemconvStability;\n\n constructor(config: RedisInstrumentationConfig = {}) {\n super(PACKAGE_NAME, PACKAGE_VERSION, config);\n this._semconvStability = config.semconvStability\n ? config.semconvStability\n : semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n override setConfig(config: RedisInstrumentationConfig = {}): void {\n super.setConfig(config);\n this._semconvStability = config.semconvStability\n ? config.semconvStability\n : semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n init() {\n return [\n new InstrumentationNodeModuleDefinition(\n 'redis',\n ['>=2.6.0 <4'],\n (moduleExports: any) => {\n if (isWrapped(moduleExports.RedisClient.prototype['internal_send_command'])) {\n this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');\n }\n this._wrap(moduleExports.RedisClient.prototype, 'internal_send_command', this._getPatchInternalSendCommand());\n if (isWrapped(moduleExports.RedisClient.prototype['create_stream'])) {\n this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');\n }\n this._wrap(moduleExports.RedisClient.prototype, 'create_stream', this._getPatchCreateStream());\n if (isWrapped(moduleExports.createClient)) {\n this._unwrap(moduleExports, 'createClient');\n }\n this._wrap(moduleExports, 'createClient', this._getPatchCreateClient());\n return moduleExports;\n },\n (moduleExports: any) => {\n if (moduleExports === undefined) return;\n this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');\n this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');\n this._unwrap(moduleExports, 'createClient');\n },\n ),\n ];\n }\n\n private _getPatchInternalSendCommand() {\n const instrumentation = this;\n return function internal_send_command(original: Function) {\n return function internal_send_command_trace(this: RedisPluginClientTypes, cmd: RedisCommand) {\n if (arguments.length !== 1 || typeof cmd !== 'object') {\n return original.apply(this, arguments);\n }\n const config = instrumentation.getConfig();\n const hasNoParentSpan = trace.getSpan(context.active()) === undefined;\n if (config.requireParentSpan === true && hasNoParentSpan) {\n return original.apply(this, arguments);\n }\n const dbStatementSerializer = config?.dbStatementSerializer || defaultDbStatementSerializer;\n const attributes: Record<string, any> = {};\n if (instrumentation._semconvStability & SemconvStability.OLD) {\n Object.assign(attributes, {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS,\n [ATTR_DB_STATEMENT]: dbStatementSerializer(cmd.command, cmd.args),\n });\n }\n if (instrumentation._semconvStability & SemconvStability.STABLE) {\n Object.assign(attributes, {\n [ATTR_DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_REDIS,\n [ATTR_DB_OPERATION_NAME]: cmd.command,\n [ATTR_DB_QUERY_TEXT]: dbStatementSerializer(cmd.command, cmd.args),\n });\n }\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = instrumentation.tracer.startSpan(`${RedisInstrumentationV2_V3.COMPONENT}-${cmd.command}`, {\n kind: SpanKind.CLIENT,\n attributes,\n });\n if (this.connection_options) {\n const connectionAttributes: Record<string, any> = {};\n if (instrumentation._semconvStability & SemconvStability.OLD) {\n Object.assign(connectionAttributes, {\n [ATTR_NET_PEER_NAME]: this.connection_options.host,\n [ATTR_NET_PEER_PORT]: this.connection_options.port,\n });\n }\n if (instrumentation._semconvStability & SemconvStability.STABLE) {\n Object.assign(connectionAttributes, {\n [ATTR_SERVER_ADDRESS]: this.connection_options.host,\n [ATTR_SERVER_PORT]: this.connection_options.port,\n });\n }\n span.setAttributes(connectionAttributes);\n }\n if (this.address && instrumentation._semconvStability & SemconvStability.OLD) {\n span.setAttribute(ATTR_DB_CONNECTION_STRING, `redis://${this.address}`);\n }\n const originalCallback = arguments[0].callback;\n if (originalCallback) {\n const originalContext = context.active();\n arguments[0].callback = function callback(this: any, err: Error | null, reply: unknown) {\n if (config?.responseHook) {\n const responseHook = config.responseHook;\n safeExecuteInTheMiddle(\n () => {\n responseHook(span, cmd.command, cmd.args, reply);\n },\n (e: Error | undefined) => {\n if (e) {\n instrumentation._diag.error('Error executing responseHook', e);\n }\n },\n true,\n );\n }\n endSpanV2(span, err);\n return context.with(originalContext, originalCallback, this, ...arguments);\n };\n }\n try {\n return original.apply(this, arguments);\n } catch (rethrow) {\n endSpanV2(span, rethrow as Error);\n throw rethrow;\n }\n };\n };\n }\n\n private _getPatchCreateClient() {\n return function createClient(original: Function) {\n return getTracedCreateClient(original);\n };\n }\n\n private _getPatchCreateStream() {\n return function createReadStream(original: Function) {\n return getTracedCreateStreamTrace(original);\n };\n }\n}\n\n// ---- RedisInstrumentationV4_V5 ----\n\nclass RedisInstrumentationV4_V5 extends InstrumentationBase<RedisInstrumentationConfig> {\n static COMPONENT = 'redis';\n _semconvStability: SemconvStability;\n\n constructor(config: RedisInstrumentationConfig = {}) {\n super(PACKAGE_NAME, PACKAGE_VERSION, config);\n this._semconvStability = config.semconvStability\n ? config.semconvStability\n : semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n override setConfig(config: RedisInstrumentationConfig = {}): void {\n super.setConfig(config);\n this._semconvStability = config.semconvStability\n ? config.semconvStability\n : semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);\n }\n\n init() {\n return [\n this._getInstrumentationNodeModuleDefinition('@redis/client'),\n this._getInstrumentationNodeModuleDefinition('@node-redis/client'),\n ];\n }\n\n private _getInstrumentationNodeModuleDefinition(basePackageName: string) {\n const commanderModuleFile = new InstrumentationNodeModuleFile(\n `${basePackageName}/dist/lib/commander.js`,\n ['^1.0.0'],\n (moduleExports: any, moduleVersion?: string) => {\n const transformCommandArguments = moduleExports.transformCommandArguments;\n if (!transformCommandArguments) {\n this._diag.error('internal instrumentation error, missing transformCommandArguments function');\n return moduleExports;\n }\n const functionToPatch = moduleVersion?.startsWith('1.0.') ? 'extendWithCommands' : 'attachCommands';\n if (isWrapped(moduleExports?.[functionToPatch])) {\n this._unwrap(moduleExports, functionToPatch);\n }\n this._wrap(moduleExports, functionToPatch, this._getPatchExtendWithCommands(transformCommandArguments));\n return moduleExports;\n },\n (moduleExports: any) => {\n if (isWrapped(moduleExports?.extendWithCommands)) {\n this._unwrap(moduleExports, 'extendWithCommands');\n }\n if (isWrapped(moduleExports?.attachCommands)) {\n this._unwrap(moduleExports, 'attachCommands');\n }\n },\n );\n\n const multiCommanderModule = new InstrumentationNodeModuleFile(\n `${basePackageName}/dist/lib/client/multi-command.js`,\n ['^1.0.0', '>=5.0.0 <5.12.0'],\n (moduleExports: any) => {\n const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;\n if (isWrapped(redisClientMultiCommandPrototype?.exec)) {\n this._unwrap(redisClientMultiCommandPrototype, 'exec');\n }\n this._wrap(redisClientMultiCommandPrototype, 'exec', this._getPatchMultiCommandsExec(false));\n if (isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {\n this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');\n }\n this._wrap(redisClientMultiCommandPrototype, 'execAsPipeline', this._getPatchMultiCommandsExec(true));\n if (isWrapped(redisClientMultiCommandPrototype?.addCommand)) {\n this._unwrap(redisClientMultiCommandPrototype, 'addCommand');\n }\n this._wrap(redisClientMultiCommandPrototype, 'addCommand', this._getPatchMultiCommandsAddCommand());\n return moduleExports;\n },\n (moduleExports: any) => {\n const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;\n if (isWrapped(redisClientMultiCommandPrototype?.exec)) {\n this._unwrap(redisClientMultiCommandPrototype, 'exec');\n }\n if (isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {\n this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');\n }\n if (isWrapped(redisClientMultiCommandPrototype?.addCommand)) {\n this._unwrap(redisClientMultiCommandPrototype, 'addCommand');\n }\n },\n );\n\n const clientIndexModule = new InstrumentationNodeModuleFile(\n `${basePackageName}/dist/lib/client/index.js`,\n ['^1.0.0', '>=5.0.0 <5.12.0'],\n (moduleExports: any) => {\n const redisClientPrototype = moduleExports?.default?.prototype;\n if (redisClientPrototype?.multi) {\n if (isWrapped(redisClientPrototype?.multi)) {\n this._unwrap(redisClientPrototype, 'multi');\n }\n this._wrap(redisClientPrototype, 'multi', this._getPatchRedisClientMulti());\n }\n if (redisClientPrototype?.MULTI) {\n if (isWrapped(redisClientPrototype?.MULTI)) {\n this._unwrap(redisClientPrototype, 'MULTI');\n }\n this._wrap(redisClientPrototype, 'MULTI', this._getPatchRedisClientMulti());\n }\n if (isWrapped(redisClientPrototype?.sendCommand)) {\n this._unwrap(redisClientPrototype, 'sendCommand');\n }\n this._wrap(redisClientPrototype, 'sendCommand', this._getPatchRedisClientSendCommand());\n if (isWrapped(redisClientPrototype?.connect)) {\n this._unwrap(redisClientPrototype, 'connect');\n }\n this._wrap(redisClientPrototype, 'connect', this._getPatchedClientConnect());\n return moduleExports;\n },\n (moduleExports: any) => {\n const redisClientPrototype = moduleExports?.default?.prototype;\n if (isWrapped(redisClientPrototype?.multi)) {\n this._unwrap(redisClientPrototype, 'multi');\n }\n if (isWrapped(redisClientPrototype?.MULTI)) {\n this._unwrap(redisClientPrototype, 'MULTI');\n }\n if (isWrapped(redisClientPrototype?.sendCommand)) {\n this._unwrap(redisClientPrototype, 'sendCommand');\n }\n if (isWrapped(redisClientPrototype?.connect)) {\n this._unwrap(redisClientPrototype, 'connect');\n }\n },\n );\n\n return new InstrumentationNodeModuleDefinition(\n basePackageName,\n ['^1.0.0', '>=5.0.0 <5.12.0'],\n (moduleExports: any) => moduleExports,\n () => {},\n [commanderModuleFile, multiCommanderModule, clientIndexModule],\n );\n }\n\n private _getPatchExtendWithCommands(transformCommandArguments: Function) {\n const plugin = this;\n return function extendWithCommandsPatchWrapper(original: Function) {\n return function extendWithCommandsPatch(this: any, config: any) {\n if (config?.BaseClass?.name !== 'RedisClient') {\n return original.apply(this, arguments);\n }\n const origExecutor = config.executor;\n config.executor = function (this: any, command: any, args: any) {\n const redisCommandArguments = transformCommandArguments(command, args).args;\n return plugin._traceClientCommand(origExecutor, this, arguments, redisCommandArguments);\n };\n return original.apply(this, arguments);\n };\n };\n }\n\n private _getPatchMultiCommandsExec(isPipeline: boolean) {\n const plugin = this;\n return function execPatchWrapper(original: Function) {\n return function execPatch(this: any) {\n const execRes = original.apply(this, arguments);\n if (typeof execRes?.then !== 'function') {\n plugin._diag.error('non-promise result when patching exec/execAsPipeline');\n return execRes;\n }\n return execRes\n .then((redisRes: unknown[]) => {\n const openSpans: OpenSpanInfo[] = this[OTEL_OPEN_SPANS];\n plugin._endSpansWithRedisReplies(openSpans, redisRes, isPipeline);\n return redisRes;\n })\n .catch((err: any) => {\n const openSpans: OpenSpanInfo[] = this[OTEL_OPEN_SPANS];\n if (!openSpans) {\n plugin._diag.error('cannot find open spans to end for multi/pipeline');\n } else {\n const replies =\n err.constructor.name === 'MultiErrorReply'\n ? (err as MultiErrorReply).replies\n : new Array(openSpans.length).fill(err);\n plugin._endSpansWithRedisReplies(openSpans, replies, isPipeline);\n }\n return Promise.reject(err);\n });\n };\n };\n }\n\n private _getPatchMultiCommandsAddCommand() {\n const plugin = this;\n return function addCommandWrapper(original: Function) {\n return function addCommandPatch(this: any, args: any) {\n return plugin._traceClientCommand(original, this, arguments, args);\n };\n };\n }\n\n private _getPatchRedisClientMulti() {\n return function multiPatchWrapper(original: Function) {\n return function multiPatch(this: any) {\n const multiRes: any = original.apply(this, arguments);\n multiRes[MULTI_COMMAND_OPTIONS] = this.options;\n return multiRes;\n };\n };\n }\n\n private _getPatchRedisClientSendCommand() {\n const plugin = this;\n return function sendCommandWrapper(original: Function) {\n return function sendCommandPatch(this: any, args: any) {\n return plugin._traceClientCommand(original, this, arguments, args);\n };\n };\n }\n\n private _getPatchedClientConnect() {\n const plugin = this;\n return function connectWrapper(original: Function) {\n return function patchedConnect(this: any) {\n const options = this.options;\n const attributes = getClientAttributes(plugin._diag, options, plugin._semconvStability);\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = plugin.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-connect`, {\n kind: SpanKind.CLIENT,\n attributes,\n });\n const res = context.with(trace.setSpan(context.active(), span), () => {\n return original.apply(this);\n });\n return res\n .then((result: any) => {\n span.end();\n return result;\n })\n .catch((error: Error) => {\n span.recordException(error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error.message,\n });\n span.end();\n return Promise.reject(error);\n });\n };\n };\n }\n\n _traceClientCommand(\n origFunction: Function,\n origThis: any,\n origArguments: IArguments,\n redisCommandArguments: Array<string | Buffer>,\n ): any {\n const hasNoParentSpan = trace.getSpan(context.active()) === undefined;\n if (hasNoParentSpan && this.getConfig().requireParentSpan) {\n return origFunction.apply(origThis, origArguments);\n }\n const clientOptions = origThis.options || origThis[MULTI_COMMAND_OPTIONS];\n const commandName = redisCommandArguments[0] as string;\n const commandArgs = redisCommandArguments.slice(1);\n const dbStatementSerializer = this.getConfig().dbStatementSerializer || defaultDbStatementSerializer;\n const attributes = getClientAttributes(this._diag, clientOptions, this._semconvStability);\n if (this._semconvStability & SemconvStability.STABLE) {\n attributes[ATTR_DB_OPERATION_NAME] = commandName;\n }\n try {\n const dbStatement = dbStatementSerializer(commandName, commandArgs);\n if (dbStatement != null) {\n if (this._semconvStability & SemconvStability.OLD) {\n attributes[ATTR_DB_STATEMENT] = dbStatement;\n }\n if (this._semconvStability & SemconvStability.STABLE) {\n attributes[ATTR_DB_QUERY_TEXT] = dbStatement;\n }\n }\n } catch (e) {\n this._diag.error('dbStatementSerializer throw an exception', e, { commandName });\n }\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';\n const span = this.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-${commandName}`, {\n kind: SpanKind.CLIENT,\n attributes,\n });\n const res = context.with(trace.setSpan(context.active(), span), () => {\n return origFunction.apply(origThis, origArguments);\n });\n if (typeof res?.then === 'function') {\n res.then(\n (redisRes: unknown) => {\n this._endSpanWithResponse(span, commandName, commandArgs, redisRes, undefined);\n },\n (err: Error) => {\n this._endSpanWithResponse(span, commandName, commandArgs, null, err);\n },\n );\n } else {\n const redisClientMultiCommand: any = res;\n redisClientMultiCommand[OTEL_OPEN_SPANS] = redisClientMultiCommand[OTEL_OPEN_SPANS] || [];\n redisClientMultiCommand[OTEL_OPEN_SPANS].push({\n span,\n commandName,\n commandArgs,\n });\n }\n return res;\n }\n\n _endSpansWithRedisReplies(openSpans: OpenSpanInfo[] | undefined, replies: unknown[], isPipeline = false): void {\n if (!openSpans) {\n return this._diag.error('cannot find open spans to end for redis multi/pipeline');\n }\n if (replies.length !== openSpans.length) {\n return this._diag.error('number of multi command spans does not match response from redis');\n }\n const allCommands = openSpans.map(s => s.commandName);\n const allSameCommand = allCommands.every(cmd => cmd === allCommands[0]);\n const operationName = allSameCommand\n ? (isPipeline ? 'PIPELINE ' : 'MULTI ') + allCommands[0]\n : isPipeline\n ? 'PIPELINE'\n : 'MULTI';\n for (let i = 0; i < openSpans.length; i++) {\n const { span, commandArgs } = openSpans[i]!;\n const currCommandRes = replies[i];\n const [res, err] = currCommandRes instanceof Error ? [null, currCommandRes] : [currCommandRes, undefined];\n if (this._semconvStability & SemconvStability.STABLE) {\n span.setAttribute(ATTR_DB_OPERATION_NAME, operationName);\n }\n this._endSpanWithResponse(span, allCommands[i]!, commandArgs, res, err);\n }\n }\n\n _endSpanWithResponse(\n span: Span,\n commandName: string,\n commandArgs: Array<string | Buffer>,\n response: unknown,\n error: Error | null | undefined,\n ): void {\n const { responseHook } = this.getConfig();\n if (!error && responseHook) {\n try {\n responseHook(span, commandName, commandArgs, response);\n } catch (err) {\n this._diag.error('responseHook throw an exception', err);\n }\n }\n if (error) {\n span.recordException(error);\n span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message });\n }\n span.end();\n }\n}\n\n// ---- RedisInstrumentation (wrapper) ----\n\nconst DEFAULT_CONFIG: RedisInstrumentationConfig = {\n requireParentSpan: false,\n};\n\nexport class RedisInstrumentation extends InstrumentationBase<RedisInstrumentationConfig> {\n private instrumentationV2_V3: RedisInstrumentationV2_V3;\n private instrumentationV4_V5: RedisInstrumentationV4_V5;\n private initialized = false;\n\n constructor(config: RedisInstrumentationConfig = {}) {\n const resolvedConfig = { ...DEFAULT_CONFIG, ...config };\n super(PACKAGE_NAME, PACKAGE_VERSION, resolvedConfig);\n this.instrumentationV2_V3 = new RedisInstrumentationV2_V3(this.getConfig());\n this.instrumentationV4_V5 = new RedisInstrumentationV4_V5(this.getConfig());\n this.initialized = true;\n }\n\n override setConfig(config: RedisInstrumentationConfig = {}): void {\n const newConfig = { ...DEFAULT_CONFIG, ...config };\n super.setConfig(newConfig);\n if (!this.initialized) {\n return;\n }\n this.instrumentationV2_V3.setConfig(newConfig);\n this.instrumentationV4_V5.setConfig(newConfig);\n }\n\n init() {}\n\n override getModuleDefinitions() {\n return [...this.instrumentationV2_V3.getModuleDefinitions(), ...this.instrumentationV4_V5.getModuleDefinitions()];\n }\n\n override setTracerProvider(tracerProvider: TracerProvider): void {\n super.setTracerProvider(tracerProvider);\n if (!this.initialized) {\n return;\n }\n this.instrumentationV2_V3.setTracerProvider(tracerProvider);\n this.instrumentationV4_V5.setTracerProvider(tracerProvider);\n }\n\n override enable(): void {\n super.enable();\n if (!this.initialized) {\n return;\n }\n this.instrumentationV2_V3.enable();\n this.instrumentationV4_V5.enable();\n }\n\n override disable(): void {\n super.disable();\n if (!this.initialized) {\n return;\n }\n this.instrumentationV2_V3.disable();\n this.instrumentationV4_V5.disable();\n }\n}\n"],"names":[],"mappings":"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"}
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE from the Sentry authors:
* - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/instrumentation-redis
* - Upstream version: @opentelemetry/instrumentation-redis@0.62.0
* - Minor TypeScript adjustments for this repository's compiler settings
*/
/* eslint-disable -- vendored @opentelemetry/instrumentation-redis */
/*
* This file contains a copy of unstable semantic convention definitions
* used by the vendored redis/ioredis instrumentations.
* @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv
*/
// Deprecated constants kept for backwards compatibility with older semconv
const ATTR_DB_CONNECTION_STRING = 'db.connection_string';
const ATTR_DB_STATEMENT = 'db.statement';
const ATTR_DB_SYSTEM = 'db.system';
const ATTR_NET_PEER_NAME = 'net.peer.name';
const ATTR_NET_PEER_PORT = 'net.peer.port';
const DB_SYSTEM_NAME_VALUE_REDIS = 'redis';
const DB_SYSTEM_VALUE_REDIS = 'redis';
export { ATTR_DB_CONNECTION_STRING, ATTR_DB_STATEMENT, ATTR_DB_SYSTEM, ATTR_NET_PEER_NAME, ATTR_NET_PEER_PORT, DB_SYSTEM_NAME_VALUE_REDIS, DB_SYSTEM_VALUE_REDIS };
//# sourceMappingURL=semconv.js.map
{"version":3,"file":"semconv.js","sources":["../../../../../../src/integrations/tracing/redis/vendored/semconv.ts"],"sourcesContent":["/*\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 * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/instrumentation-redis\n * - Upstream version: @opentelemetry/instrumentation-redis@0.62.0\n * - Minor TypeScript adjustments for this repository's compiler settings\n */\n/* eslint-disable -- vendored @opentelemetry/instrumentation-redis */\n\n/*\n * This file contains a copy of unstable semantic convention definitions\n * used by the vendored redis/ioredis instrumentations.\n * @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv\n */\n\n// Deprecated constants kept for backwards compatibility with older semconv\nexport const ATTR_DB_CONNECTION_STRING = 'db.connection_string';\nexport const ATTR_DB_STATEMENT = 'db.statement';\nexport const ATTR_DB_SYSTEM = 'db.system';\nexport const ATTR_NET_PEER_NAME = 'net.peer.name';\nexport const ATTR_NET_PEER_PORT = 'net.peer.port';\nexport const DB_SYSTEM_NAME_VALUE_REDIS = 'redis';\nexport const DB_SYSTEM_VALUE_REDIS = 'redis';\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACO,MAAM,yBAAA,GAA4B;AAClC,MAAM,iBAAA,GAAoB;AAC1B,MAAM,cAAA,GAAiB;AACvB,MAAM,kBAAA,GAAqB;AAC3B,MAAM,kBAAA,GAAqB;AAC3B,MAAM,0BAAA,GAA6B;AACnC,MAAM,qBAAA,GAAwB;;;;"}
import { IORedisResponseCustomAttributeFunction } from './vendored/types';
interface RedisOptions {
/**
* Define cache prefixes for cache keys that should be captured as a cache span.
*
* Setting this to, for example, `['user:']` will capture cache keys that start with `user:`.
*/
cachePrefixes?: string[];
/**
* Maximum length of the cache key added to the span description. If the key exceeds this length, it will be truncated.
*
* Passing `0` will use the full cache key without truncation.
*
* By default, the full cache key is used.
*/
maxCacheKeyLength?: number;
}
export declare let _redisOptions: RedisOptions;
export declare const cacheResponseHook: IORedisResponseCustomAttributeFunction;
/** To be able to preload all Redis OTel instrumentations with just one ID ("Redis"), all the instrumentations are generated in this one function */
export declare const instrumentRedis: (() => void) & {
id: string;
};
/**
* Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and
* [ioredis](https://www.npmjs.com/package/ioredis) libraries.
*
* For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).
*
* @example
* ```javascript
* const Sentry = require('@sentry/node');
*
* Sentry.init({
* integrations: [Sentry.redisIntegration()],
* });
* ```
*/
export declare const redisIntegration: (options?: RedisOptions | undefined) => import("@sentry/core").Integration;
export {};
//# sourceMappingURL=index.d.ts.map
import { TracingChannelContextWithSpan } from '@sentry/opentelemetry/tracing-channel';
import { IORedisInstrumentationConfig } from './vendored/types';
/**
* Subscribe Sentry handlers to node-redis diagnostics_channel events (>= 5.12.0).
*
* Uses `@sentry/opentelemetry/tracing-channel` so OTel AsyncLocalStorage context propagates
* automatically via `bindStore` — without it, spans created in `start` would not become
* the active context for subsequent operations.
*
* Safe on every runtime that exposes `node:diagnostics_channel` (Node, Bun, Deno, Workers).
* In node-redis < 5.12.0 the channels are never published to, so subscribers are inert and
* there is no double-instrumentation against the IITM-based patcher (gated to < 5.12.0).
*/
export declare function subscribeRedisDiagnosticChannels(responseHook?: IORedisInstrumentationConfig['responseHook']): void;
export declare function _resetRedisDiagnosticChannelsForTesting(): void;
export { TracingChannelContextWithSpan };
//# sourceMappingURL=redis-dc-subscriber.d.ts.map
import { InstrumentationBase, InstrumentationNodeModuleDefinition, SemconvStability } from '@opentelemetry/instrumentation';
import { IORedisInstrumentationConfig } from './types';
export declare class IORedisInstrumentation extends InstrumentationBase<IORedisInstrumentationConfig> {
_netSemconvStability: SemconvStability;
_dbSemconvStability: SemconvStability;
constructor(config?: IORedisInstrumentationConfig);
_setSemconvStabilityFromEnv(): void;
setConfig(config?: IORedisInstrumentationConfig): void;
init(): InstrumentationNodeModuleDefinition[];
private _patchSendCommand;
private _patchConnection;
private _traceSendCommand;
private _traceConnection;
}
//# sourceMappingURL=ioredis-instrumentation.d.ts.map
/**
* Given the redis command name and arguments, return a combination of the
* command name + the allowed arguments according to `serializationSubsets`.
*/
export declare const defaultDbStatementSerializer: (cmdName: string, cmdArgs: Array<string | Buffer | number | any[]>) => string;
//# sourceMappingURL=redis-common.d.ts.map
import { TracerProvider } from '@opentelemetry/api';
import { InstrumentationBase } from '@opentelemetry/instrumentation';
import { RedisInstrumentationConfig } from './types';
export declare class RedisInstrumentation extends InstrumentationBase<RedisInstrumentationConfig> {
private instrumentationV2_V3;
private instrumentationV4_V5;
private initialized;
constructor(config?: RedisInstrumentationConfig);
setConfig(config?: RedisInstrumentationConfig): void;
init(): void;
getModuleDefinitions(): import("@opentelemetry/instrumentation").InstrumentationModuleDefinition[];
setTracerProvider(tracerProvider: TracerProvider): void;
enable(): void;
disable(): void;
}
//# sourceMappingURL=redis-instrumentation.d.ts.map
export declare const ATTR_DB_CONNECTION_STRING = "db.connection_string";
export declare const ATTR_DB_STATEMENT = "db.statement";
export declare const ATTR_DB_SYSTEM = "db.system";
export declare const ATTR_NET_PEER_NAME = "net.peer.name";
export declare const ATTR_NET_PEER_PORT = "net.peer.port";
export declare const DB_SYSTEM_NAME_VALUE_REDIS = "redis";
export declare const DB_SYSTEM_VALUE_REDIS = "redis";
//# sourceMappingURL=semconv.d.ts.map
import { Span } from '@opentelemetry/api';
import { InstrumentationConfig, SemconvStability } from '@opentelemetry/instrumentation';
/**
* Function that can be used to serialize db.statement tag
* @param cmdName - The name of the command (eg. set, get, mset)
* @param cmdArgs - Array of arguments passed to the command
* @returns serialized string that will be used as the db.statement attribute.
*/
export type DbStatementSerializer = (cmdName: string, cmdArgs: Array<string | Buffer>) => string;
/**
* Function that can be used to add custom attributes to span on response from redis server
*/
export interface RedisResponseCustomAttributeFunction {
(span: Span, cmdName: string, cmdArgs: Array<string | Buffer>, response: unknown): void;
}
export interface RedisInstrumentationConfig extends InstrumentationConfig {
/** Custom serializer function for the db.statement tag */
dbStatementSerializer?: DbStatementSerializer;
/** Function for adding custom attributes on db response */
responseHook?: RedisResponseCustomAttributeFunction;
/** Require parent to create redis span, default when unset is false */
requireParentSpan?: boolean;
/**
* Controls which semantic-convention attributes are emitted on spans.
* Default: 'OLD'.
*/
semconvStability?: SemconvStability;
}
export type CommandArgs = Array<string | Buffer | number | any[]>;
/**
* Function that can be used to serialize db.statement tag for ioredis
*/
export type IORedisDbStatementSerializer = (cmdName: string, cmdArgs: CommandArgs) => string;
export interface IORedisRequestHookInformation {
moduleVersion?: string;
cmdName: string;
cmdArgs: CommandArgs;
}
export interface RedisRequestCustomAttributeFunction {
(span: Span, requestInfo: IORedisRequestHookInformation): void;
}
/**
* Function that can be used to add custom attributes to span on response from redis server (ioredis)
*/
export interface IORedisResponseCustomAttributeFunction {
(span: Span, cmdName: string, cmdArgs: CommandArgs, response: unknown): void;
}
export interface IORedisInstrumentationConfig extends InstrumentationConfig {
/** Custom serializer function for the db.statement tag */
dbStatementSerializer?: IORedisDbStatementSerializer;
/** Function for adding custom attributes on db request */
requestHook?: RedisRequestCustomAttributeFunction;
/** Function for adding custom attributes on db response */
responseHook?: IORedisResponseCustomAttributeFunction;
/** Require parent to create ioredis span, default when unset is true */
requireParentSpan?: boolean;
}
//# sourceMappingURL=types.d.ts.map
import type { IORedisResponseCustomAttributeFunction } from './vendored/types';
interface RedisOptions {
/**
* Define cache prefixes for cache keys that should be captured as a cache span.
*
* Setting this to, for example, `['user:']` will capture cache keys that start with `user:`.
*/
cachePrefixes?: string[];
/**
* Maximum length of the cache key added to the span description. If the key exceeds this length, it will be truncated.
*
* Passing `0` will use the full cache key without truncation.
*
* By default, the full cache key is used.
*/
maxCacheKeyLength?: number;
}
export declare let _redisOptions: RedisOptions;
export declare const cacheResponseHook: IORedisResponseCustomAttributeFunction;
/** To be able to preload all Redis OTel instrumentations with just one ID ("Redis"), all the instrumentations are generated in this one function */
export declare const instrumentRedis: (() => void) & {
id: string;
};
/**
* Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and
* [ioredis](https://www.npmjs.com/package/ioredis) libraries.
*
* For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).
*
* @example
* ```javascript
* const Sentry = require('@sentry/node');
*
* Sentry.init({
* integrations: [Sentry.redisIntegration()],
* });
* ```
*/
export declare const redisIntegration: (options?: RedisOptions | undefined) => import("@sentry/core").Integration;
export {};
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/tracing/redis/index.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,sCAAsC,EAAE,MAAM,kBAAkB,CAAC;AAK/E,UAAU,YAAY;IACpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAKD,eAAO,IAAI,aAAa,EAAE,YAAiB,CAAC;AAG5C,eAAO,MAAM,iBAAiB,EAAE,sCAoD/B,CAAC;AAcF,qJAAqJ;AACrJ,eAAO,MAAM,eAAe,SACtB,IAAI;;CAaT,CAAC;AAYF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,4EAAuC,CAAC"}
import { type TracingChannelContextWithSpan } from '@sentry/opentelemetry/tracing-channel';
import type { IORedisInstrumentationConfig } from './vendored/types';
/**
* Subscribe Sentry handlers to node-redis diagnostics_channel events (>= 5.12.0).
*
* Uses `@sentry/opentelemetry/tracing-channel` so OTel AsyncLocalStorage context propagates
* automatically via `bindStore` — without it, spans created in `start` would not become
* the active context for subsequent operations.
*
* Safe on every runtime that exposes `node:diagnostics_channel` (Node, Bun, Deno, Workers).
* In node-redis < 5.12.0 the channels are never published to, so subscribers are inert and
* there is no double-instrumentation against the IITM-based patcher (gated to < 5.12.0).
*/
export declare function subscribeRedisDiagnosticChannels(responseHook?: IORedisInstrumentationConfig['responseHook']): void;
export declare function _resetRedisDiagnosticChannelsForTesting(): void;
export type { TracingChannelContextWithSpan };
//# sourceMappingURL=redis-dc-subscriber.d.ts.map
{"version":3,"file":"redis-dc-subscriber.d.ts","sourceRoot":"","sources":["../../../../../src/integrations/tracing/redis/redis-dc-subscriber.ts"],"names":[],"mappings":"AAOA,OAAO,EAAkB,KAAK,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAS3G,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AA2CrE;;;;;;;;;;GAUG;AACH,wBAAgB,gCAAgC,CAAC,YAAY,CAAC,EAAE,4BAA4B,CAAC,cAAc,CAAC,GAAG,IAAI,CAalH;AA6ID,wBAAgB,uCAAuC,IAAI,IAAI,CAG9D;AAGD,YAAY,EAAE,6BAA6B,EAAE,CAAC"}
import { InstrumentationBase, InstrumentationNodeModuleDefinition, SemconvStability } from '@opentelemetry/instrumentation';
import type { IORedisInstrumentationConfig } from './types';
export declare class IORedisInstrumentation extends InstrumentationBase<IORedisInstrumentationConfig> {
_netSemconvStability: SemconvStability;
_dbSemconvStability: SemconvStability;
constructor(config?: IORedisInstrumentationConfig);
_setSemconvStabilityFromEnv(): void;
setConfig(config?: IORedisInstrumentationConfig): void;
init(): InstrumentationNodeModuleDefinition[];
private _patchSendCommand;
private _patchConnection;
private _traceSendCommand;
private _traceConnection;
}
//# sourceMappingURL=ioredis-instrumentation.d.ts.map
{"version":3,"file":"ioredis-instrumentation.d.ts","sourceRoot":"","sources":["../../../../../../src/integrations/tracing/redis/vendored/ioredis-instrumentation.ts"],"names":[],"mappings":"AAyBA,OAAO,EACL,mBAAmB,EACnB,mCAAmC,EAGnC,gBAAgB,EAEjB,MAAM,gCAAgC,CAAC;AAkBxC,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAwB5D,qBAAa,sBAAuB,SAAQ,mBAAmB,CAAC,4BAA4B,CAAC;IAC3F,oBAAoB,EAAG,gBAAgB,CAAC;IACxC,mBAAmB,EAAG,gBAAgB,CAAC;gBAE3B,MAAM,GAAE,4BAAiC;IAKrD,2BAA2B,IAAI,IAAI;IAK1B,SAAS,CAAC,MAAM,GAAE,4BAAiC,GAAG,IAAI;IAInE,IAAI;IAiCJ,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,iBAAiB;IAmFzB,OAAO,CAAC,gBAAgB;CAqDzB"}
/**
* Given the redis command name and arguments, return a combination of the
* command name + the allowed arguments according to `serializationSubsets`.
*/
export declare const defaultDbStatementSerializer: (cmdName: string, cmdArgs: Array<string | Buffer | number | any[]>) => string;
//# sourceMappingURL=redis-common.d.ts.map
{"version":3,"file":"redis-common.d.ts","sourceRoot":"","sources":["../../../../../../src/integrations/tracing/redis/vendored/redis-common.ts"],"names":[],"mappings":"AAkDA;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GACvC,SAAS,MAAM,EACf,SAAS,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,GAAG,EAAE,CAAC,KAC/C,MAWF,CAAC"}
import type { TracerProvider } from '@opentelemetry/api';
import { InstrumentationBase } from '@opentelemetry/instrumentation';
import type { RedisInstrumentationConfig } from './types';
export declare class RedisInstrumentation extends InstrumentationBase<RedisInstrumentationConfig> {
private instrumentationV2_V3;
private instrumentationV4_V5;
private initialized;
constructor(config?: RedisInstrumentationConfig);
setConfig(config?: RedisInstrumentationConfig): void;
init(): void;
getModuleDefinitions(): import("@opentelemetry/instrumentation").InstrumentationModuleDefinition[];
setTracerProvider(tracerProvider: TracerProvider): void;
enable(): void;
disable(): void;
}
//# sourceMappingURL=redis-instrumentation.d.ts.map
{"version":3,"file":"redis-instrumentation.d.ts","sourceRoot":"","sources":["../../../../../../src/integrations/tracing/redis/vendored/redis-instrumentation.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EACL,mBAAmB,EAOpB,MAAM,gCAAgC,CAAC;AAmBxC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAmnB1D,qBAAa,oBAAqB,SAAQ,mBAAmB,CAAC,0BAA0B,CAAC;IACvF,OAAO,CAAC,oBAAoB,CAA4B;IACxD,OAAO,CAAC,oBAAoB,CAA4B;IACxD,OAAO,CAAC,WAAW,CAAS;gBAEhB,MAAM,GAAE,0BAA+B;IAQ1C,SAAS,CAAC,MAAM,GAAE,0BAA+B,GAAG,IAAI;IAUjE,IAAI;IAEK,oBAAoB;IAIpB,iBAAiB,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI;IASvD,MAAM,IAAI,IAAI;IASd,OAAO,IAAI,IAAI;CAQzB"}
export declare const ATTR_DB_CONNECTION_STRING = "db.connection_string";
export declare const ATTR_DB_STATEMENT = "db.statement";
export declare const ATTR_DB_SYSTEM = "db.system";
export declare const ATTR_NET_PEER_NAME = "net.peer.name";
export declare const ATTR_NET_PEER_PORT = "net.peer.port";
export declare const DB_SYSTEM_NAME_VALUE_REDIS = "redis";
export declare const DB_SYSTEM_VALUE_REDIS = "redis";
//# sourceMappingURL=semconv.d.ts.map
{"version":3,"file":"semconv.d.ts","sourceRoot":"","sources":["../../../../../../src/integrations/tracing/redis/vendored/semconv.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAChE,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAChD,eAAO,MAAM,cAAc,cAAc,CAAC;AAC1C,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,0BAA0B,UAAU,CAAC;AAClD,eAAO,MAAM,qBAAqB,UAAU,CAAC"}
import type { Span } from '@opentelemetry/api';
import type { InstrumentationConfig, SemconvStability } from '@opentelemetry/instrumentation';
/**
* Function that can be used to serialize db.statement tag
* @param cmdName - The name of the command (eg. set, get, mset)
* @param cmdArgs - Array of arguments passed to the command
* @returns serialized string that will be used as the db.statement attribute.
*/
export type DbStatementSerializer = (cmdName: string, cmdArgs: Array<string | Buffer>) => string;
/**
* Function that can be used to add custom attributes to span on response from redis server
*/
export interface RedisResponseCustomAttributeFunction {
(span: Span, cmdName: string, cmdArgs: Array<string | Buffer>, response: unknown): void;
}
export interface RedisInstrumentationConfig extends InstrumentationConfig {
/** Custom serializer function for the db.statement tag */
dbStatementSerializer?: DbStatementSerializer;
/** Function for adding custom attributes on db response */
responseHook?: RedisResponseCustomAttributeFunction;
/** Require parent to create redis span, default when unset is false */
requireParentSpan?: boolean;
/**
* Controls which semantic-convention attributes are emitted on spans.
* Default: 'OLD'.
*/
semconvStability?: SemconvStability;
}
export type CommandArgs = Array<string | Buffer | number | any[]>;
/**
* Function that can be used to serialize db.statement tag for ioredis
*/
export type IORedisDbStatementSerializer = (cmdName: string, cmdArgs: CommandArgs) => string;
export interface IORedisRequestHookInformation {
moduleVersion?: string;
cmdName: string;
cmdArgs: CommandArgs;
}
export interface RedisRequestCustomAttributeFunction {
(span: Span, requestInfo: IORedisRequestHookInformation): void;
}
/**
* Function that can be used to add custom attributes to span on response from redis server (ioredis)
*/
export interface IORedisResponseCustomAttributeFunction {
(span: Span, cmdName: string, cmdArgs: CommandArgs, response: unknown): void;
}
export interface IORedisInstrumentationConfig extends InstrumentationConfig {
/** Custom serializer function for the db.statement tag */
dbStatementSerializer?: IORedisDbStatementSerializer;
/** Function for adding custom attributes on db request */
requestHook?: RedisRequestCustomAttributeFunction;
/** Function for adding custom attributes on db response */
responseHook?: IORedisResponseCustomAttributeFunction;
/** Require parent to create ioredis span, default when unset is true */
requireParentSpan?: boolean;
}
//# sourceMappingURL=types.d.ts.map
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/integrations/tracing/redis/vendored/types.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAI9F;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,MAAM,CAAC;AAEjG;;GAEG;AACH,MAAM,WAAW,oCAAoC;IACnD,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CACzF;AAED,MAAM,WAAW,0BAA2B,SAAQ,qBAAqB;IACvE,0DAA0D;IAC1D,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,2DAA2D;IAC3D,YAAY,CAAC,EAAE,oCAAoC,CAAC;IACpD,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAID,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,KAAK,MAAM,CAAC;AAE7F,MAAM,WAAW,6BAA6B;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,mCAAmC;IAClD,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,6BAA6B,GAAG,IAAI,CAAC;CAChE;AAED;;GAEG;AACH,MAAM,WAAW,sCAAsC;IACrD,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9E;AAED,MAAM,WAAW,4BAA6B,SAAQ,qBAAqB;IACzE,0DAA0D;IAC1D,qBAAqB,CAAC,EAAE,4BAA4B,CAAC;IACrD,0DAA0D;IAC1D,WAAW,CAAC,EAAE,mCAAmC,CAAC;IAClD,2DAA2D;IAC3D,YAAY,CAAC,EAAE,sCAAsC,CAAC;IACtD,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B"}
+4
-4

@@ -15,3 +15,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

const mysql2 = require('./integrations/tracing/mysql2.js');
const redis = require('./integrations/tracing/redis.js');
const index$b = require('./integrations/tracing/redis/index.js');
const postgres = require('./integrations/tracing/postgres.js');

@@ -29,3 +29,3 @@ const postgresjs = require('./integrations/tracing/postgresjs.js');

const amqplib = require('./integrations/tracing/amqplib.js');
const index$b = require('./integrations/tracing/vercelai/index.js');
const index$c = require('./integrations/tracing/vercelai/index.js');
const index$a = require('./integrations/tracing/openai/index.js');

@@ -65,3 +65,3 @@ const index = require('./integrations/tracing/anthropic-ai/index.js');

exports.mysql2Integration = mysql2.mysql2Integration;
exports.redisIntegration = redis.redisIntegration;
exports.redisIntegration = index$b.redisIntegration;
exports.postgresIntegration = postgres.postgresIntegration;

@@ -83,3 +83,3 @@ exports.postgresJsIntegration = postgresjs.postgresJsIntegration;

exports.amqplibIntegration = amqplib.amqplibIntegration;
exports.vercelAIIntegration = index$b.vercelAIIntegration;
exports.vercelAIIntegration = index$c.vercelAIIntegration;
exports.openAIIntegration = index$a.openAIIntegration;

@@ -86,0 +86,0 @@ exports.anthropicAIIntegration = index.anthropicAIIntegration;

Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const api = require('@opentelemetry/api');
const instrumentationHttp = require('@opentelemetry/instrumentation-http');
const core = require('@sentry/core');

@@ -10,11 +8,5 @@ const nodeCore = require('@sentry/node-core');

const INSTRUMENTATION_NAME = '@opentelemetry_sentry-patched/instrumentation-http';
// TODO(v11): Consolidate all the various HTTP integration options into one,
// and deprecate the duplicated and aliased options.
// The `http.client.request.created` diagnostics channel, needed for trace propagation,
// was added in Node 22.12.0 (backported from 23.2.0). Earlier 22.x versions don't have it.
const FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL =
(nodeCore.NODE_VERSION.major === 22 && nodeCore.NODE_VERSION.minor >= 12) ||
(nodeCore.NODE_VERSION.major === 23 && nodeCore.NODE_VERSION.minor >= 2) ||
nodeCore.NODE_VERSION.major >= 24;
const instrumentSentryHttp = nodeCore.generateInstrumentOnce(

@@ -27,61 +19,2 @@ `${INTEGRATION_NAME}.sentry`,

const instrumentOtelHttp = nodeCore.generateInstrumentOnce(INTEGRATION_NAME, config => {
const instrumentation = new instrumentationHttp.HttpInstrumentation({
...config,
// This is hard-coded and can never be overridden by the user
disableIncomingRequestInstrumentation: true,
});
// We want to update the logger namespace so we can better identify what is happening here
try {
instrumentation['_diag'] = api.diag.createComponentLogger({
namespace: INSTRUMENTATION_NAME,
});
// @ts-expect-error We are writing a read-only property here...
instrumentation.instrumentationName = INSTRUMENTATION_NAME;
} catch {
// ignore errors here...
}
// The OTel HttpInstrumentation (>=0.213.0) has a guard (`_httpPatched`/`_httpsPatched`)
// that prevents patching `http`/`https` when loaded by both CJS `require()` and ESM `import`.
// In environments like AWS Lambda, the runtime loads `http` via CJS first (for the Runtime API),
// and then the user's ESM handler imports `node:http`. The guard blocks ESM patching after CJS,
// which breaks HTTP spans for ESM handlers. We disable this guard to allow both to be patched.
// TODO(andrei): Remove once https://github.com/open-telemetry/opentelemetry-js/issues/6489 is fixed.
try {
const noopDescriptor = { get: () => false, set: () => {} };
Object.defineProperty(instrumentation, '_httpPatched', noopDescriptor);
Object.defineProperty(instrumentation, '_httpsPatched', noopDescriptor);
} catch {
// ignore errors here...
}
return instrumentation;
});
/** Exported only for tests. */
function _shouldUseOtelHttpInstrumentation(
options,
clientOptions = {},
) {
// If `spans` is passed in, it takes precedence
// Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled
if (typeof options.spans === 'boolean') {
return options.spans;
}
if (clientOptions.skipOpenTelemetrySetup) {
return false;
}
// IMPORTANT: We only disable span instrumentation when spans are not enabled _and_ we are on a Node version
// that fully supports the necessary diagnostics channels for trace propagation
if (!core.hasSpansEnabled(clientOptions) && FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL) {
return false;
}
return true;
}
/**

@@ -94,2 +27,3 @@ * The http integration instruments Node's internal http and https modules.

const disableIncomingRequestSpans = options.disableIncomingRequestSpans;
const enableServerSpans = spans && !disableIncomingRequestSpans;

@@ -109,3 +43,3 @@ const serverOptions = {

onSpanCreated: options.incomingRequestSpanHook,
} ;
};

@@ -115,4 +49,2 @@ const server = nodeCore.httpServerIntegration(serverOptions);

const enableServerSpans = spans && !disableIncomingRequestSpans;
return {

@@ -128,5 +60,2 @@ name: INTEGRATION_NAME,

setupOnce() {
const clientOptions = (core.getClient()?.getOptions() || {}) ;
const useOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation(options, clientOptions);
server.setupOnce();

@@ -136,14 +65,13 @@

breadcrumbs: options.breadcrumbs,
propagateTraceInOutgoingRequests:
typeof options.tracePropagation === 'boolean'
? options.tracePropagation
: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL || !useOtelHttpInstrumentation,
createSpansForOutgoingRequests: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL,
spans: options.spans,
spans,
propagateTraceInOutgoingRequests: options.tracePropagation ?? true,
createSpansForOutgoingRequests: spans,
ignoreOutgoingRequests: options.ignoreOutgoingRequests,
outgoingRequestHook: (span, request) => {
// Sanitize data URLs to prevent long base64 strings in span attributes
const url = nodeCore.getRequestUrl(request);
const url = core.getRequestUrlFromClientRequest(request);
if (url.startsWith('data:')) {
const sanitizedUrl = core.stripDataUrlContent(url);
// TODO(v11): Update these to the Sentry semantic attributes.
// https://getsentry.github.io/sentry-conventions/attributes/
span.setAttribute('http.url', sanitizedUrl);

@@ -153,3 +81,2 @@ span.setAttribute(core.SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);

}
options.instrumentation?.requestHook?.(span, request);

@@ -159,16 +86,14 @@ },

outgoingRequestApplyCustomAttributes: options.instrumentation?.applyCustomAttributesOnSpan,
} ;
};
// This is Sentry-specific instrumentation for outgoing request breadcrumbs & trace propagation
// This is Sentry-specific instrumentation for outgoing request
// breadcrumbs & trace propagation. It uses the diagnostic channels on
// node versions that support it, falling back to monkey-patching when
// needed.
instrumentSentryHttp(sentryHttpInstrumentationOptions);
// This is the "regular" OTEL instrumentation that emits outgoing request spans
if (useOtelHttpInstrumentation) {
const instrumentationConfig = getConfigWithDefaults(options);
instrumentOtelHttp(instrumentationConfig);
}
},
processEvent(event) {
// Note: We always run this, even if spans are disabled
// The reason being that e.g. the remix integration disables span creation here but still wants to use the ignore status codes option
// Always run this, even if spans are disabled
// The reason being that e.g. the remix integration disables span
// creation here but still wants to use the ignore status codes option
return serverSpans.processEvent(event);

@@ -179,56 +104,4 @@ },

function getConfigWithDefaults(options = {}) {
const instrumentationConfig = {
// This is handled by the SentryHttpInstrumentation on Node 22+
disableOutgoingRequestInstrumentation: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL,
ignoreOutgoingRequestHook: request => {
const url = nodeCore.getRequestUrl(request);
if (!url) {
return false;
}
const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;
if (_ignoreOutgoingRequests?.(url, request)) {
return true;
}
return false;
},
requireParentforOutgoingSpans: false,
requestHook: (span, req) => {
nodeCore.addOriginToSpan(span, 'auto.http.otel.http');
// Sanitize data URLs to prevent long base64 strings in span attributes
const url = nodeCore.getRequestUrl(req );
if (url.startsWith('data:')) {
const sanitizedUrl = core.stripDataUrlContent(url);
span.setAttribute('http.url', sanitizedUrl);
span.setAttribute(core.SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);
span.updateName(`${(req ).method || 'GET'} ${sanitizedUrl}`);
}
options.instrumentation?.requestHook?.(span, req);
},
responseHook: (span, res) => {
options.instrumentation?.responseHook?.(span, res);
},
applyCustomAttributesOnSpan: (
span,
request,
response,
) => {
options.instrumentation?.applyCustomAttributesOnSpan?.(span, request, response);
},
} ;
return instrumentationConfig;
}
exports._shouldUseOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation;
exports.httpIntegration = httpIntegration;
exports.instrumentOtelHttp = instrumentOtelHttp;
exports.instrumentSentryHttp = instrumentSentryHttp;
//# sourceMappingURL=http.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"http.js","sources":["../../../src/integrations/http.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 {\n defineIntegration,\n getClient,\n hasSpansEnabled,\n SEMANTIC_ATTRIBUTE_URL_FULL,\n stripDataUrlContent,\n} from '@sentry/core';\nimport type { HTTPModuleRequestIncomingMessage, NodeClient, SentryHttpInstrumentationOptions } from '@sentry/node-core';\nimport {\n addOriginToSpan,\n generateInstrumentOnce,\n getRequestUrl,\n httpServerIntegration,\n httpServerSpansIntegration,\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\n// The `http.client.request.created` diagnostics channel, needed for trace propagation,\n// was added in Node 22.12.0 (backported from 23.2.0). Earlier 22.x versions don't have it.\nconst FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL =\n (NODE_VERSION.major === 22 && NODE_VERSION.minor >= 12) ||\n (NODE_VERSION.major === 23 && NODE_VERSION.minor >= 2) ||\n NODE_VERSION.major >= 24;\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 * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing HTTP requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when `skipOpenTelemetrySetup: true` is configured and you want\n * to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry's HttpInstrumentation.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\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 * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n incomingRequestSpanHook?: (span: Span, request: IncomingMessage, response: ServerResponse) => void;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\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], [301, 303], [305, 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\nexport const 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({\n ...config,\n // This is hard-coded and can never be overridden by the user\n disableIncomingRequestInstrumentation: true,\n });\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 // The OTel HttpInstrumentation (>=0.213.0) has a guard (`_httpPatched`/`_httpsPatched`)\n // that prevents patching `http`/`https` when loaded by both CJS `require()` and ESM `import`.\n // In environments like AWS Lambda, the runtime loads `http` via CJS first (for the Runtime API),\n // and then the user's ESM handler imports `node:http`. The guard blocks ESM patching after CJS,\n // which breaks HTTP spans for ESM handlers. We disable this guard to allow both to be patched.\n // TODO(andrei): Remove once https://github.com/open-telemetry/opentelemetry-js/issues/6489 is fixed.\n try {\n const noopDescriptor = { get: () => false, set: () => {} };\n Object.defineProperty(instrumentation, '_httpPatched', noopDescriptor);\n Object.defineProperty(instrumentation, '_httpsPatched', noopDescriptor);\n } catch {\n // ignore errors here...\n }\n\n return instrumentation;\n});\n\n/** Exported only for tests. */\nexport function _shouldUseOtelHttpInstrumentation(\n options: HttpOptions,\n clientOptions: Partial<NodeClientOptions> = {},\n): 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 a Node version\n // that fully supports the necessary diagnostics channels for trace propagation\n if (!hasSpansEnabled(clientOptions) && FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL) {\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 spans = options.spans ?? true;\n const disableIncomingRequestSpans = options.disableIncomingRequestSpans;\n\n const serverOptions = {\n sessions: options.trackIncomingRequestsAsSessions,\n sessionFlushingDelayMS: options.sessionFlushingDelayMS,\n ignoreRequestBody: options.ignoreIncomingRequestBody,\n maxRequestBodySize: options.maxIncomingRequestBodySize,\n } satisfies Parameters<typeof httpServerIntegration>[0];\n\n const serverSpansOptions = {\n ignoreIncomingRequests: options.ignoreIncomingRequests,\n ignoreStaticAssets: options.ignoreStaticAssets,\n ignoreStatusCodes: options.dropSpansForIncomingRequestStatusCodes,\n instrumentation: options.instrumentation,\n onSpanCreated: options.incomingRequestSpanHook,\n } satisfies Parameters<typeof httpServerSpansIntegration>[0];\n\n const server = httpServerIntegration(serverOptions);\n const serverSpans = httpServerSpansIntegration(serverSpansOptions);\n\n const enableServerSpans = spans && !disableIncomingRequestSpans;\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n const clientOptions = client.getOptions();\n\n if (enableServerSpans && hasSpansEnabled(clientOptions)) {\n serverSpans.setup(client);\n }\n },\n setupOnce() {\n const clientOptions = (getClient<NodeClient>()?.getOptions() || {}) satisfies Partial<NodeClientOptions>;\n const useOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation(options, clientOptions);\n\n server.setupOnce();\n\n const sentryHttpInstrumentationOptions = {\n breadcrumbs: options.breadcrumbs,\n propagateTraceInOutgoingRequests:\n typeof options.tracePropagation === 'boolean'\n ? options.tracePropagation\n : FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL || !useOtelHttpInstrumentation,\n createSpansForOutgoingRequests: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL,\n spans: options.spans,\n ignoreOutgoingRequests: options.ignoreOutgoingRequests,\n outgoingRequestHook: (span: Span, request: ClientRequest) => {\n // Sanitize data URLs to prevent long base64 strings in span attributes\n const url = getRequestUrl(request);\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n span.setAttribute('http.url', sanitizedUrl);\n span.setAttribute(SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);\n span.updateName(`${request.method || 'GET'} ${sanitizedUrl}`);\n }\n\n options.instrumentation?.requestHook?.(span, request);\n },\n outgoingResponseHook: options.instrumentation?.responseHook,\n outgoingRequestApplyCustomAttributes: options.instrumentation?.applyCustomAttributesOnSpan,\n } satisfies SentryHttpInstrumentationOptions;\n\n // This is Sentry-specific instrumentation for outgoing request breadcrumbs & trace propagation\n instrumentSentryHttp(sentryHttpInstrumentationOptions);\n\n // This is the \"regular\" OTEL instrumentation that emits outgoing request spans\n if (useOtelHttpInstrumentation) {\n const instrumentationConfig = getConfigWithDefaults(options);\n instrumentOtelHttp(instrumentationConfig);\n }\n },\n processEvent(event) {\n // Note: We always run this, even if spans are disabled\n // The reason being that e.g. the remix integration disables span creation here but still wants to use the ignore status codes option\n return serverSpans.processEvent(event);\n },\n };\n});\n\nfunction getConfigWithDefaults(options: Partial<HttpOptions> = {}): HttpInstrumentationConfig {\n const instrumentationConfig = {\n // This is handled by the SentryHttpInstrumentation on Node 22+\n disableOutgoingRequestInstrumentation: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL,\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 requireParentforOutgoingSpans: false,\n requestHook: (span, req) => {\n addOriginToSpan(span, 'auto.http.otel.http');\n\n // Sanitize data URLs to prevent long base64 strings in span attributes\n const url = getRequestUrl(req as ClientRequest);\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n span.setAttribute('http.url', sanitizedUrl);\n span.setAttribute(SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);\n span.updateName(`${(req as ClientRequest).method || 'GET'} ${sanitizedUrl}`);\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":["NODE_VERSION","generateInstrumentOnce","SentryHttpInstrumentation","HttpInstrumentation","diag","hasSpansEnabled","defineIntegration","httpServerIntegration","httpServerSpansIntegration","getClient","getRequestUrl","stripDataUrlContent","SEMANTIC_ATTRIBUTE_URL_FULL","addOriginToSpan"],"mappings":"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"}
{"version":3,"file":"http.js","sources":["../../../src/integrations/http.ts"],"sourcesContent":["import type { RequestOptions } from 'node:http';\nimport type { HttpClientRequest, HttpIncomingMessage, HttpServerResponse, Span } from '@sentry/core';\nimport {\n defineIntegration,\n hasSpansEnabled,\n SEMANTIC_ATTRIBUTE_URL_FULL,\n stripDataUrlContent,\n getRequestUrlFromClientRequest,\n} from '@sentry/core';\nimport type {\n NodeClient,\n SentryHttpInstrumentationOptions,\n HttpServerIntegrationOptions,\n HttpServerSpansIntegrationOptions,\n} from '@sentry/node-core';\nimport {\n generateInstrumentOnce,\n httpServerIntegration,\n httpServerSpansIntegration,\n SentryHttpInstrumentation,\n} from '@sentry/node-core';\n\nconst INTEGRATION_NAME = 'Http';\n\n// TODO(v11): Consolidate all the various HTTP integration options into one,\n// and deprecate the duplicated and aliased options.\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 * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing HTTP requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when `skipOpenTelemetrySetup: true` is configured and you want\n * to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry's HttpInstrumentation.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\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: HttpIncomingMessage) => boolean;\n\n /**\n * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n incomingRequestSpanHook?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\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], [301, 303], [305, 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: HttpIncomingMessage | HttpClientRequest) => void;\n responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: HttpIncomingMessage | HttpClientRequest,\n response: HttpIncomingMessage | HttpServerResponse,\n ) => void;\n };\n}\n\nexport const instrumentSentryHttp = generateInstrumentOnce<SentryHttpInstrumentationOptions>(\n `${INTEGRATION_NAME}.sentry`,\n options => {\n return new SentryHttpInstrumentation(options);\n },\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 spans = options.spans ?? true;\n const disableIncomingRequestSpans = options.disableIncomingRequestSpans;\n const enableServerSpans = spans && !disableIncomingRequestSpans;\n\n const serverOptions = {\n sessions: options.trackIncomingRequestsAsSessions,\n sessionFlushingDelayMS: options.sessionFlushingDelayMS,\n ignoreRequestBody: options.ignoreIncomingRequestBody,\n maxRequestBodySize: options.maxIncomingRequestBodySize,\n } satisfies HttpServerIntegrationOptions;\n\n const serverSpansOptions: HttpServerSpansIntegrationOptions = {\n ignoreIncomingRequests: options.ignoreIncomingRequests,\n ignoreStaticAssets: options.ignoreStaticAssets,\n ignoreStatusCodes: options.dropSpansForIncomingRequestStatusCodes,\n instrumentation: options.instrumentation,\n onSpanCreated: options.incomingRequestSpanHook,\n };\n\n const server = httpServerIntegration(serverOptions);\n const serverSpans = httpServerSpansIntegration(serverSpansOptions);\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n const clientOptions = client.getOptions();\n\n if (enableServerSpans && hasSpansEnabled(clientOptions)) {\n serverSpans.setup(client);\n }\n },\n setupOnce() {\n server.setupOnce();\n\n const sentryHttpInstrumentationOptions: SentryHttpInstrumentationOptions = {\n breadcrumbs: options.breadcrumbs,\n spans,\n propagateTraceInOutgoingRequests: options.tracePropagation ?? true,\n createSpansForOutgoingRequests: spans,\n ignoreOutgoingRequests: options.ignoreOutgoingRequests,\n outgoingRequestHook: (span: Span, request: HttpClientRequest) => {\n // Sanitize data URLs to prevent long base64 strings in span attributes\n const url = getRequestUrlFromClientRequest(request);\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n // TODO(v11): Update these to the Sentry semantic attributes.\n // https://getsentry.github.io/sentry-conventions/attributes/\n span.setAttribute('http.url', sanitizedUrl);\n span.setAttribute(SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);\n span.updateName(`${request.method || 'GET'} ${sanitizedUrl}`);\n }\n options.instrumentation?.requestHook?.(span, request);\n },\n outgoingResponseHook: options.instrumentation?.responseHook,\n outgoingRequestApplyCustomAttributes: options.instrumentation?.applyCustomAttributesOnSpan,\n };\n\n // This is Sentry-specific instrumentation for outgoing request\n // breadcrumbs & trace propagation. It uses the diagnostic channels on\n // node versions that support it, falling back to monkey-patching when\n // needed.\n instrumentSentryHttp(sentryHttpInstrumentationOptions);\n },\n processEvent(event) {\n // Always run this, even if spans are disabled\n // The reason being that e.g. the remix integration disables span\n // creation here but still wants to use the ignore status codes option\n return serverSpans.processEvent(event);\n },\n };\n});\n"],"names":["generateInstrumentOnce","SentryHttpInstrumentation","defineIntegration","httpServerIntegration","httpServerSpansIntegration","hasSpansEnabled","getRequestUrlFromClientRequest","stripDataUrlContent","SEMANTIC_ATTRIBUTE_URL_FULL"],"mappings":"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"}

@@ -5,3 +5,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

const amqplib = require('./amqplib.js');
const index$6 = require('./anthropic-ai/index.js');
const index$7 = require('./anthropic-ai/index.js');
const connect = require('./connect.js');

@@ -12,3 +12,3 @@ const express = require('./express.js');

const genericPool = require('./genericPool.js');
const index$7 = require('./google-genai/index.js');
const index$8 = require('./google-genai/index.js');
const graphql = require('./graphql.js');

@@ -19,4 +19,4 @@ const index$1 = require('./hapi/index.js');

const koa = require('./koa.js');
const index$3 = require('./langchain/index.js');
const index$8 = require('./langgraph/index.js');
const index$4 = require('./langchain/index.js');
const index$9 = require('./langgraph/index.js');
const lrumemoizer = require('./lrumemoizer.js');

@@ -27,9 +27,9 @@ const mongo = require('./mongo.js');

const mysql2 = require('./mysql2.js');
const index$5 = require('./openai/index.js');
const index$6 = require('./openai/index.js');
const postgres = require('./postgres.js');
const postgresjs = require('./postgresjs.js');
const prisma = require('./prisma.js');
const redis = require('./redis.js');
const index$3 = require('./redis/index.js');
const tedious = require('./tedious.js');
const index$4 = require('./vercelai/index.js');
const index$5 = require('./vercelai/index.js');

@@ -49,3 +49,3 @@ /**

mysql2.mysql2Integration(),
redis.redisIntegration(),
index$3.redisIntegration(),
postgres.postgresIntegration(),

@@ -63,8 +63,8 @@ prisma.prismaIntegration(),

// LangChain must come first to disable AI provider integrations before they instrument
index$3.langChainIntegration(),
index$8.langGraphIntegration(),
index$4.vercelAIIntegration(),
index$5.openAIIntegration(),
index$6.anthropicAIIntegration(),
index$7.googleGenAIIntegration(),
index$4.langChainIntegration(),
index$9.langGraphIntegration(),
index$5.vercelAIIntegration(),
index$6.openAIIntegration(),
index$7.anthropicAIIntegration(),
index$8.googleGenAIIntegration(),
postgresjs.postgresJsIntegration(),

@@ -82,3 +82,2 @@ firebase.firebaseIntegration(),

http.instrumentSentryHttp,
http.instrumentOtelHttp,
express.instrumentExpress,

@@ -100,14 +99,14 @@ connect.instrumentConnect,

graphql.instrumentGraphql,
redis.instrumentRedis,
index$3.instrumentRedis,
tedious.instrumentTedious,
genericPool.instrumentGenericPool,
amqplib.instrumentAmqplib,
index$3.instrumentLangChain,
index$4.instrumentVercelAi,
index$5.instrumentOpenAi,
index$4.instrumentLangChain,
index$5.instrumentVercelAi,
index$6.instrumentOpenAi,
postgresjs.instrumentPostgresJs,
firebase.instrumentFirebase,
index$6.instrumentAnthropicAi,
index$7.instrumentGoogleGenAI,
index$8.instrumentLangGraph,
index$7.instrumentAnthropicAi,
index$8.instrumentGoogleGenAI,
index$9.instrumentLangGraph,
];

@@ -114,0 +113,0 @@ }

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentOtelHttp, instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { googleGenAIIntegration, instrumentGoogleGenAI } from './google-genai';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { honoIntegration, instrumentHono } from './hono';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLangChain, langChainIntegration } from './langchain';\nimport { instrumentLangGraph, langGraphIntegration } from './langgraph';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n honoIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n // AI providers\n // LangChain must come first to disable AI provider integrations before they instrument\n langChainIntegration(),\n langGraphIntegration(),\n vercelAIIntegration(),\n openAIIntegration(),\n anthropicAIIntegration(),\n googleGenAIIntegration(),\n postgresJsIntegration(),\n firebaseIntegration(),\n ];\n}\n\n/**\n * Get a list of methods to instrument OTEL, when preload instrumentation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => void) & { id: string })[] {\n return [\n instrumentSentryHttp,\n instrumentOtelHttp,\n instrumentExpress,\n instrumentConnect,\n instrumentFastify,\n instrumentFastifyV3,\n instrumentHapi,\n instrumentHono,\n instrumentKafka,\n instrumentKoa,\n instrumentLruMemoizer,\n instrumentMongo,\n instrumentMongoose,\n instrumentMysql,\n instrumentMysql2,\n instrumentPostgres,\n instrumentHapi,\n instrumentGraphql,\n instrumentRedis,\n instrumentTedious,\n instrumentGenericPool,\n instrumentAmqplib,\n instrumentLangChain,\n instrumentVercelAi,\n instrumentOpenAi,\n instrumentPostgresJs,\n instrumentFirebase,\n instrumentAnthropicAi,\n instrumentGoogleGenAI,\n instrumentLangGraph,\n ];\n}\n"],"names":["expressIntegration","fastifyIntegration","graphqlIntegration","honoIntegration","mongoIntegration","mongooseIntegration","mysqlIntegration","mysql2Integration","redisIntegration","postgresIntegration","prismaIntegration","hapiIntegration","koaIntegration","connectIntegration","tediousIntegration","genericPoolIntegration","kafkaIntegration","amqplibIntegration","lruMemoizerIntegration","langChainIntegration","langGraphIntegration","vercelAIIntegration","openAIIntegration","anthropicAIIntegration","googleGenAIIntegration","postgresJsIntegration","firebaseIntegration","instrumentSentryHttp","instrumentOtelHttp","instrumentExpress","instrumentConnect","instrumentFastify","instrumentFastifyV3","instrumentHapi","instrumentHono","instrumentKafka","instrumentKoa","instrumentLruMemoizer","instrumentMongo","instrumentMongoose","instrumentMysql","instrumentMysql2","instrumentPostgres","instrumentGraphql","instrumentRedis","instrumentTedious","instrumentGenericPool","instrumentAmqplib","instrumentLangChain","instrumentVercelAi","instrumentOpenAi","instrumentPostgresJs","instrumentFirebase","instrumentAnthropicAi","instrumentGoogleGenAI","instrumentLangGraph"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA;AACA;AACA;AACO,SAAS,8BAA8B,GAAkB;AAChE,EAAE,OAAO;AACT,IAAIA,0BAAkB,EAAE;AACxB,IAAIC,wBAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,uBAAe,EAAE;AACrB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,uBAAe,EAAE;AACrB,IAAIC,kBAAc,EAAE;AACpB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B;AACA;AACA,IAAIC,4BAAoB,EAAE;AAC1B,IAAIC,4BAAoB,EAAE;AAC1B,IAAIC,2BAAmB,EAAE;AACzB,IAAIC,yBAAiB,EAAE;AACvB,IAAIC,8BAAsB,EAAE;AAC5B,IAAIC,8BAAsB,EAAE;AAC5B,IAAIC,gCAAqB,EAAE;AAC3B,IAAIC,4BAAmB,EAAE;AACzB,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACO,SAAS,wCAAwC,GAAmD;AAC3G,EAAE,OAAO;AACT,IAAIC,yBAAoB;AACxB,IAAIC,uBAAkB;AACtB,IAAIC,yBAAiB;AACrB,IAAIC,yBAAiB;AACrB,IAAIC,uBAAiB;AACrB,IAAIC,yBAAmB;AACvB,IAAIC,sBAAc;AAClB,IAAIC,sBAAc;AAClB,IAAIC,qBAAe;AACnB,IAAIC,iBAAa;AACjB,IAAIC,iCAAqB;AACzB,IAAIC,qBAAe;AACnB,IAAIC,2BAAkB;AACtB,IAAIC,qBAAe;AACnB,IAAIC,uBAAgB;AACpB,IAAIC,2BAAkB;AACtB,IAAIT,sBAAc;AAClB,IAAIU,yBAAiB;AACrB,IAAIC,qBAAe;AACnB,IAAIC,yBAAiB;AACrB,IAAIC,iCAAqB;AACzB,IAAIC,yBAAiB;AACrB,IAAIC,2BAAmB;AACvB,IAAIC,0BAAkB;AACtB,IAAIC,wBAAgB;AACpB,IAAIC,+BAAoB;AACxB,IAAIC,2BAAkB;AACtB,IAAIC,6BAAqB;AACzB,IAAIC,6BAAqB;AACzB,IAAIC,2BAAmB;AACvB,GAAG;AACH;;;;;"}
{"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { googleGenAIIntegration, instrumentGoogleGenAI } from './google-genai';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { honoIntegration, instrumentHono } from './hono';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLangChain, langChainIntegration } from './langchain';\nimport { instrumentLangGraph, langGraphIntegration } from './langgraph';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n honoIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n // AI providers\n // LangChain must come first to disable AI provider integrations before they instrument\n langChainIntegration(),\n langGraphIntegration(),\n vercelAIIntegration(),\n openAIIntegration(),\n anthropicAIIntegration(),\n googleGenAIIntegration(),\n postgresJsIntegration(),\n firebaseIntegration(),\n ];\n}\n\n/**\n * Get a list of methods to instrument OTEL, when preload instrumentation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => void) & { id: string })[] {\n return [\n instrumentSentryHttp,\n instrumentExpress,\n instrumentConnect,\n instrumentFastify,\n instrumentFastifyV3,\n instrumentHapi,\n instrumentHono,\n instrumentKafka,\n instrumentKoa,\n instrumentLruMemoizer,\n instrumentMongo,\n instrumentMongoose,\n instrumentMysql,\n instrumentMysql2,\n instrumentPostgres,\n instrumentHapi,\n instrumentGraphql,\n instrumentRedis,\n instrumentTedious,\n instrumentGenericPool,\n instrumentAmqplib,\n instrumentLangChain,\n instrumentVercelAi,\n instrumentOpenAi,\n instrumentPostgresJs,\n instrumentFirebase,\n instrumentAnthropicAi,\n instrumentGoogleGenAI,\n instrumentLangGraph,\n ];\n}\n"],"names":["expressIntegration","fastifyIntegration","graphqlIntegration","honoIntegration","mongoIntegration","mongooseIntegration","mysqlIntegration","mysql2Integration","redisIntegration","postgresIntegration","prismaIntegration","hapiIntegration","koaIntegration","connectIntegration","tediousIntegration","genericPoolIntegration","kafkaIntegration","amqplibIntegration","lruMemoizerIntegration","langChainIntegration","langGraphIntegration","vercelAIIntegration","openAIIntegration","anthropicAIIntegration","googleGenAIIntegration","postgresJsIntegration","firebaseIntegration","instrumentSentryHttp","instrumentExpress","instrumentConnect","instrumentFastify","instrumentFastifyV3","instrumentHapi","instrumentHono","instrumentKafka","instrumentKoa","instrumentLruMemoizer","instrumentMongo","instrumentMongoose","instrumentMysql","instrumentMysql2","instrumentPostgres","instrumentGraphql","instrumentRedis","instrumentTedious","instrumentGenericPool","instrumentAmqplib","instrumentLangChain","instrumentVercelAi","instrumentOpenAi","instrumentPostgresJs","instrumentFirebase","instrumentAnthropicAi","instrumentGoogleGenAI","instrumentLangGraph"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA;AACA;AACA;AACO,SAAS,8BAA8B,GAAkB;AAChE,EAAE,OAAO;AACT,IAAIA,0BAAkB,EAAE;AACxB,IAAIC,wBAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,uBAAe,EAAE;AACrB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,wBAAgB,EAAE;AACtB,IAAIC,4BAAmB,EAAE;AACzB,IAAIC,wBAAiB,EAAE;AACvB,IAAIC,uBAAe,EAAE;AACrB,IAAIC,kBAAc,EAAE;AACpB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B,IAAIC,sBAAgB,EAAE;AACtB,IAAIC,0BAAkB,EAAE;AACxB,IAAIC,kCAAsB,EAAE;AAC5B;AACA;AACA,IAAIC,4BAAoB,EAAE;AAC1B,IAAIC,4BAAoB,EAAE;AAC1B,IAAIC,2BAAmB,EAAE;AACzB,IAAIC,yBAAiB,EAAE;AACvB,IAAIC,8BAAsB,EAAE;AAC5B,IAAIC,8BAAsB,EAAE;AAC5B,IAAIC,gCAAqB,EAAE;AAC3B,IAAIC,4BAAmB,EAAE;AACzB,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACO,SAAS,wCAAwC,GAAmD;AAC3G,EAAE,OAAO;AACT,IAAIC,yBAAoB;AACxB,IAAIC,yBAAiB;AACrB,IAAIC,yBAAiB;AACrB,IAAIC,uBAAiB;AACrB,IAAIC,yBAAmB;AACvB,IAAIC,sBAAc;AAClB,IAAIC,sBAAc;AAClB,IAAIC,qBAAe;AACnB,IAAIC,iBAAa;AACjB,IAAIC,iCAAqB;AACzB,IAAIC,qBAAe;AACnB,IAAIC,2BAAkB;AACtB,IAAIC,qBAAe;AACnB,IAAIC,uBAAgB;AACpB,IAAIC,2BAAkB;AACtB,IAAIT,sBAAc;AAClB,IAAIU,yBAAiB;AACrB,IAAIC,uBAAe;AACnB,IAAIC,yBAAiB;AACrB,IAAIC,iCAAqB;AACzB,IAAIC,yBAAiB;AACrB,IAAIC,2BAAmB;AACvB,IAAIC,0BAAkB;AACtB,IAAIC,wBAAgB;AACpB,IAAIC,+BAAoB;AACxB,IAAIC,2BAAkB;AACtB,IAAIC,6BAAqB;AACzB,IAAIC,6BAAqB;AACzB,IAAIC,2BAAmB;AACvB,GAAG;AACH;;;;;"}

@@ -1,1 +0,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);\n } else {\n result.push(el);\n }\n });\n };\n\n flattenHelper(input);\n return result;\n}\n"],"names":[],"mappings":"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"}
{"version":3,"file":"redisCache.js","sources":["../../../src/utils/redisCache.ts"],"sourcesContent":["export type IORedisCommandArgs = Array<string | Buffer | number | unknown[]>;\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);\n } else {\n result.push(el);\n }\n });\n };\n\n flattenHelper(input);\n return result;\n}\n"],"names":[],"mappings":"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"}

@@ -13,3 +13,3 @@ export { httpIntegration } from './integrations/http.js';

export { mysql2Integration } from './integrations/tracing/mysql2.js';
export { redisIntegration } from './integrations/tracing/redis.js';
export { redisIntegration } from './integrations/tracing/redis/index.js';
export { postgresIntegration } from './integrations/tracing/postgres.js';

@@ -16,0 +16,0 @@ export { postgresJsIntegration } from './integrations/tracing/postgresjs.js';

@@ -1,17 +0,9 @@

import { diag } from '@opentelemetry/api';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { defineIntegration, getClient, hasSpansEnabled, stripDataUrlContent, SEMANTIC_ATTRIBUTE_URL_FULL } from '@sentry/core';
import { NODE_VERSION, generateInstrumentOnce, SentryHttpInstrumentation, httpServerIntegration, httpServerSpansIntegration, getRequestUrl, addOriginToSpan } from '@sentry/node-core';
import { defineIntegration, hasSpansEnabled, getRequestUrlFromClientRequest, stripDataUrlContent, SEMANTIC_ATTRIBUTE_URL_FULL } from '@sentry/core';
import { generateInstrumentOnce, SentryHttpInstrumentation, httpServerIntegration, httpServerSpansIntegration } from '@sentry/node-core';
const INTEGRATION_NAME = 'Http';
const INSTRUMENTATION_NAME = '@opentelemetry_sentry-patched/instrumentation-http';
// TODO(v11): Consolidate all the various HTTP integration options into one,
// and deprecate the duplicated and aliased options.
// The `http.client.request.created` diagnostics channel, needed for trace propagation,
// was added in Node 22.12.0 (backported from 23.2.0). Earlier 22.x versions don't have it.
const FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL =
(NODE_VERSION.major === 22 && NODE_VERSION.minor >= 12) ||
(NODE_VERSION.major === 23 && NODE_VERSION.minor >= 2) ||
NODE_VERSION.major >= 24;
const instrumentSentryHttp = generateInstrumentOnce(

@@ -24,61 +16,2 @@ `${INTEGRATION_NAME}.sentry`,

const instrumentOtelHttp = generateInstrumentOnce(INTEGRATION_NAME, config => {
const instrumentation = new HttpInstrumentation({
...config,
// This is hard-coded and can never be overridden by the user
disableIncomingRequestInstrumentation: true,
});
// We want to update the logger namespace so we can better identify what is happening here
try {
instrumentation['_diag'] = diag.createComponentLogger({
namespace: INSTRUMENTATION_NAME,
});
// @ts-expect-error We are writing a read-only property here...
instrumentation.instrumentationName = INSTRUMENTATION_NAME;
} catch {
// ignore errors here...
}
// The OTel HttpInstrumentation (>=0.213.0) has a guard (`_httpPatched`/`_httpsPatched`)
// that prevents patching `http`/`https` when loaded by both CJS `require()` and ESM `import`.
// In environments like AWS Lambda, the runtime loads `http` via CJS first (for the Runtime API),
// and then the user's ESM handler imports `node:http`. The guard blocks ESM patching after CJS,
// which breaks HTTP spans for ESM handlers. We disable this guard to allow both to be patched.
// TODO(andrei): Remove once https://github.com/open-telemetry/opentelemetry-js/issues/6489 is fixed.
try {
const noopDescriptor = { get: () => false, set: () => {} };
Object.defineProperty(instrumentation, '_httpPatched', noopDescriptor);
Object.defineProperty(instrumentation, '_httpsPatched', noopDescriptor);
} catch {
// ignore errors here...
}
return instrumentation;
});
/** Exported only for tests. */
function _shouldUseOtelHttpInstrumentation(
options,
clientOptions = {},
) {
// If `spans` is passed in, it takes precedence
// Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled
if (typeof options.spans === 'boolean') {
return options.spans;
}
if (clientOptions.skipOpenTelemetrySetup) {
return false;
}
// IMPORTANT: We only disable span instrumentation when spans are not enabled _and_ we are on a Node version
// that fully supports the necessary diagnostics channels for trace propagation
if (!hasSpansEnabled(clientOptions) && FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL) {
return false;
}
return true;
}
/**

@@ -91,2 +24,3 @@ * The http integration instruments Node's internal http and https modules.

const disableIncomingRequestSpans = options.disableIncomingRequestSpans;
const enableServerSpans = spans && !disableIncomingRequestSpans;

@@ -106,3 +40,3 @@ const serverOptions = {

onSpanCreated: options.incomingRequestSpanHook,
} ;
};

@@ -112,4 +46,2 @@ const server = httpServerIntegration(serverOptions);

const enableServerSpans = spans && !disableIncomingRequestSpans;
return {

@@ -125,5 +57,2 @@ name: INTEGRATION_NAME,

setupOnce() {
const clientOptions = (getClient()?.getOptions() || {}) ;
const useOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation(options, clientOptions);
server.setupOnce();

@@ -133,14 +62,13 @@

breadcrumbs: options.breadcrumbs,
propagateTraceInOutgoingRequests:
typeof options.tracePropagation === 'boolean'
? options.tracePropagation
: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL || !useOtelHttpInstrumentation,
createSpansForOutgoingRequests: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL,
spans: options.spans,
spans,
propagateTraceInOutgoingRequests: options.tracePropagation ?? true,
createSpansForOutgoingRequests: spans,
ignoreOutgoingRequests: options.ignoreOutgoingRequests,
outgoingRequestHook: (span, request) => {
// Sanitize data URLs to prevent long base64 strings in span attributes
const url = getRequestUrl(request);
const url = getRequestUrlFromClientRequest(request);
if (url.startsWith('data:')) {
const sanitizedUrl = stripDataUrlContent(url);
// TODO(v11): Update these to the Sentry semantic attributes.
// https://getsentry.github.io/sentry-conventions/attributes/
span.setAttribute('http.url', sanitizedUrl);

@@ -150,3 +78,2 @@ span.setAttribute(SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);

}
options.instrumentation?.requestHook?.(span, request);

@@ -156,16 +83,14 @@ },

outgoingRequestApplyCustomAttributes: options.instrumentation?.applyCustomAttributesOnSpan,
} ;
};
// This is Sentry-specific instrumentation for outgoing request breadcrumbs & trace propagation
// This is Sentry-specific instrumentation for outgoing request
// breadcrumbs & trace propagation. It uses the diagnostic channels on
// node versions that support it, falling back to monkey-patching when
// needed.
instrumentSentryHttp(sentryHttpInstrumentationOptions);
// This is the "regular" OTEL instrumentation that emits outgoing request spans
if (useOtelHttpInstrumentation) {
const instrumentationConfig = getConfigWithDefaults(options);
instrumentOtelHttp(instrumentationConfig);
}
},
processEvent(event) {
// Note: We always run this, even if spans are disabled
// The reason being that e.g. the remix integration disables span creation here but still wants to use the ignore status codes option
// Always run this, even if spans are disabled
// The reason being that e.g. the remix integration disables span
// creation here but still wants to use the ignore status codes option
return serverSpans.processEvent(event);

@@ -176,53 +101,3 @@ },

function getConfigWithDefaults(options = {}) {
const instrumentationConfig = {
// This is handled by the SentryHttpInstrumentation on Node 22+
disableOutgoingRequestInstrumentation: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL,
ignoreOutgoingRequestHook: request => {
const url = getRequestUrl(request);
if (!url) {
return false;
}
const _ignoreOutgoingRequests = options.ignoreOutgoingRequests;
if (_ignoreOutgoingRequests?.(url, request)) {
return true;
}
return false;
},
requireParentforOutgoingSpans: false,
requestHook: (span, req) => {
addOriginToSpan(span, 'auto.http.otel.http');
// Sanitize data URLs to prevent long base64 strings in span attributes
const url = getRequestUrl(req );
if (url.startsWith('data:')) {
const sanitizedUrl = stripDataUrlContent(url);
span.setAttribute('http.url', sanitizedUrl);
span.setAttribute(SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);
span.updateName(`${(req ).method || 'GET'} ${sanitizedUrl}`);
}
options.instrumentation?.requestHook?.(span, req);
},
responseHook: (span, res) => {
options.instrumentation?.responseHook?.(span, res);
},
applyCustomAttributesOnSpan: (
span,
request,
response,
) => {
options.instrumentation?.applyCustomAttributesOnSpan?.(span, request, response);
},
} ;
return instrumentationConfig;
}
export { _shouldUseOtelHttpInstrumentation, httpIntegration, instrumentOtelHttp, instrumentSentryHttp };
export { httpIntegration, instrumentSentryHttp };
//# sourceMappingURL=http.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"http.js","sources":["../../../src/integrations/http.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 {\n defineIntegration,\n getClient,\n hasSpansEnabled,\n SEMANTIC_ATTRIBUTE_URL_FULL,\n stripDataUrlContent,\n} from '@sentry/core';\nimport type { HTTPModuleRequestIncomingMessage, NodeClient, SentryHttpInstrumentationOptions } from '@sentry/node-core';\nimport {\n addOriginToSpan,\n generateInstrumentOnce,\n getRequestUrl,\n httpServerIntegration,\n httpServerSpansIntegration,\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\n// The `http.client.request.created` diagnostics channel, needed for trace propagation,\n// was added in Node 22.12.0 (backported from 23.2.0). Earlier 22.x versions don't have it.\nconst FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL =\n (NODE_VERSION.major === 22 && NODE_VERSION.minor >= 12) ||\n (NODE_VERSION.major === 23 && NODE_VERSION.minor >= 2) ||\n NODE_VERSION.major >= 24;\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 * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing HTTP requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when `skipOpenTelemetrySetup: true` is configured and you want\n * to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry's HttpInstrumentation.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\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 * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n incomingRequestSpanHook?: (span: Span, request: IncomingMessage, response: ServerResponse) => void;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\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], [301, 303], [305, 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\nexport const 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({\n ...config,\n // This is hard-coded and can never be overridden by the user\n disableIncomingRequestInstrumentation: true,\n });\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 // The OTel HttpInstrumentation (>=0.213.0) has a guard (`_httpPatched`/`_httpsPatched`)\n // that prevents patching `http`/`https` when loaded by both CJS `require()` and ESM `import`.\n // In environments like AWS Lambda, the runtime loads `http` via CJS first (for the Runtime API),\n // and then the user's ESM handler imports `node:http`. The guard blocks ESM patching after CJS,\n // which breaks HTTP spans for ESM handlers. We disable this guard to allow both to be patched.\n // TODO(andrei): Remove once https://github.com/open-telemetry/opentelemetry-js/issues/6489 is fixed.\n try {\n const noopDescriptor = { get: () => false, set: () => {} };\n Object.defineProperty(instrumentation, '_httpPatched', noopDescriptor);\n Object.defineProperty(instrumentation, '_httpsPatched', noopDescriptor);\n } catch {\n // ignore errors here...\n }\n\n return instrumentation;\n});\n\n/** Exported only for tests. */\nexport function _shouldUseOtelHttpInstrumentation(\n options: HttpOptions,\n clientOptions: Partial<NodeClientOptions> = {},\n): 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 a Node version\n // that fully supports the necessary diagnostics channels for trace propagation\n if (!hasSpansEnabled(clientOptions) && FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL) {\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 spans = options.spans ?? true;\n const disableIncomingRequestSpans = options.disableIncomingRequestSpans;\n\n const serverOptions = {\n sessions: options.trackIncomingRequestsAsSessions,\n sessionFlushingDelayMS: options.sessionFlushingDelayMS,\n ignoreRequestBody: options.ignoreIncomingRequestBody,\n maxRequestBodySize: options.maxIncomingRequestBodySize,\n } satisfies Parameters<typeof httpServerIntegration>[0];\n\n const serverSpansOptions = {\n ignoreIncomingRequests: options.ignoreIncomingRequests,\n ignoreStaticAssets: options.ignoreStaticAssets,\n ignoreStatusCodes: options.dropSpansForIncomingRequestStatusCodes,\n instrumentation: options.instrumentation,\n onSpanCreated: options.incomingRequestSpanHook,\n } satisfies Parameters<typeof httpServerSpansIntegration>[0];\n\n const server = httpServerIntegration(serverOptions);\n const serverSpans = httpServerSpansIntegration(serverSpansOptions);\n\n const enableServerSpans = spans && !disableIncomingRequestSpans;\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n const clientOptions = client.getOptions();\n\n if (enableServerSpans && hasSpansEnabled(clientOptions)) {\n serverSpans.setup(client);\n }\n },\n setupOnce() {\n const clientOptions = (getClient<NodeClient>()?.getOptions() || {}) satisfies Partial<NodeClientOptions>;\n const useOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation(options, clientOptions);\n\n server.setupOnce();\n\n const sentryHttpInstrumentationOptions = {\n breadcrumbs: options.breadcrumbs,\n propagateTraceInOutgoingRequests:\n typeof options.tracePropagation === 'boolean'\n ? options.tracePropagation\n : FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL || !useOtelHttpInstrumentation,\n createSpansForOutgoingRequests: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL,\n spans: options.spans,\n ignoreOutgoingRequests: options.ignoreOutgoingRequests,\n outgoingRequestHook: (span: Span, request: ClientRequest) => {\n // Sanitize data URLs to prevent long base64 strings in span attributes\n const url = getRequestUrl(request);\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n span.setAttribute('http.url', sanitizedUrl);\n span.setAttribute(SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);\n span.updateName(`${request.method || 'GET'} ${sanitizedUrl}`);\n }\n\n options.instrumentation?.requestHook?.(span, request);\n },\n outgoingResponseHook: options.instrumentation?.responseHook,\n outgoingRequestApplyCustomAttributes: options.instrumentation?.applyCustomAttributesOnSpan,\n } satisfies SentryHttpInstrumentationOptions;\n\n // This is Sentry-specific instrumentation for outgoing request breadcrumbs & trace propagation\n instrumentSentryHttp(sentryHttpInstrumentationOptions);\n\n // This is the \"regular\" OTEL instrumentation that emits outgoing request spans\n if (useOtelHttpInstrumentation) {\n const instrumentationConfig = getConfigWithDefaults(options);\n instrumentOtelHttp(instrumentationConfig);\n }\n },\n processEvent(event) {\n // Note: We always run this, even if spans are disabled\n // The reason being that e.g. the remix integration disables span creation here but still wants to use the ignore status codes option\n return serverSpans.processEvent(event);\n },\n };\n});\n\nfunction getConfigWithDefaults(options: Partial<HttpOptions> = {}): HttpInstrumentationConfig {\n const instrumentationConfig = {\n // This is handled by the SentryHttpInstrumentation on Node 22+\n disableOutgoingRequestInstrumentation: FULLY_SUPPORTS_HTTP_DIAGNOSTICS_CHANNEL,\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 requireParentforOutgoingSpans: false,\n requestHook: (span, req) => {\n addOriginToSpan(span, 'auto.http.otel.http');\n\n // Sanitize data URLs to prevent long base64 strings in span attributes\n const url = getRequestUrl(req as ClientRequest);\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n span.setAttribute('http.url', sanitizedUrl);\n span.setAttribute(SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);\n span.updateName(`${(req as ClientRequest).method || 'GET'} ${sanitizedUrl}`);\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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"}
{"version":3,"file":"http.js","sources":["../../../src/integrations/http.ts"],"sourcesContent":["import type { RequestOptions } from 'node:http';\nimport type { HttpClientRequest, HttpIncomingMessage, HttpServerResponse, Span } from '@sentry/core';\nimport {\n defineIntegration,\n hasSpansEnabled,\n SEMANTIC_ATTRIBUTE_URL_FULL,\n stripDataUrlContent,\n getRequestUrlFromClientRequest,\n} from '@sentry/core';\nimport type {\n NodeClient,\n SentryHttpInstrumentationOptions,\n HttpServerIntegrationOptions,\n HttpServerSpansIntegrationOptions,\n} from '@sentry/node-core';\nimport {\n generateInstrumentOnce,\n httpServerIntegration,\n httpServerSpansIntegration,\n SentryHttpInstrumentation,\n} from '@sentry/node-core';\n\nconst INTEGRATION_NAME = 'Http';\n\n// TODO(v11): Consolidate all the various HTTP integration options into one,\n// and deprecate the duplicated and aliased options.\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 * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing HTTP requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when `skipOpenTelemetrySetup: true` is configured and you want\n * to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry's HttpInstrumentation.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\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: HttpIncomingMessage) => boolean;\n\n /**\n * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n incomingRequestSpanHook?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\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], [301, 303], [305, 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: HttpIncomingMessage | HttpClientRequest) => void;\n responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: HttpIncomingMessage | HttpClientRequest,\n response: HttpIncomingMessage | HttpServerResponse,\n ) => void;\n };\n}\n\nexport const instrumentSentryHttp = generateInstrumentOnce<SentryHttpInstrumentationOptions>(\n `${INTEGRATION_NAME}.sentry`,\n options => {\n return new SentryHttpInstrumentation(options);\n },\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 spans = options.spans ?? true;\n const disableIncomingRequestSpans = options.disableIncomingRequestSpans;\n const enableServerSpans = spans && !disableIncomingRequestSpans;\n\n const serverOptions = {\n sessions: options.trackIncomingRequestsAsSessions,\n sessionFlushingDelayMS: options.sessionFlushingDelayMS,\n ignoreRequestBody: options.ignoreIncomingRequestBody,\n maxRequestBodySize: options.maxIncomingRequestBodySize,\n } satisfies HttpServerIntegrationOptions;\n\n const serverSpansOptions: HttpServerSpansIntegrationOptions = {\n ignoreIncomingRequests: options.ignoreIncomingRequests,\n ignoreStaticAssets: options.ignoreStaticAssets,\n ignoreStatusCodes: options.dropSpansForIncomingRequestStatusCodes,\n instrumentation: options.instrumentation,\n onSpanCreated: options.incomingRequestSpanHook,\n };\n\n const server = httpServerIntegration(serverOptions);\n const serverSpans = httpServerSpansIntegration(serverSpansOptions);\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n const clientOptions = client.getOptions();\n\n if (enableServerSpans && hasSpansEnabled(clientOptions)) {\n serverSpans.setup(client);\n }\n },\n setupOnce() {\n server.setupOnce();\n\n const sentryHttpInstrumentationOptions: SentryHttpInstrumentationOptions = {\n breadcrumbs: options.breadcrumbs,\n spans,\n propagateTraceInOutgoingRequests: options.tracePropagation ?? true,\n createSpansForOutgoingRequests: spans,\n ignoreOutgoingRequests: options.ignoreOutgoingRequests,\n outgoingRequestHook: (span: Span, request: HttpClientRequest) => {\n // Sanitize data URLs to prevent long base64 strings in span attributes\n const url = getRequestUrlFromClientRequest(request);\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n // TODO(v11): Update these to the Sentry semantic attributes.\n // https://getsentry.github.io/sentry-conventions/attributes/\n span.setAttribute('http.url', sanitizedUrl);\n span.setAttribute(SEMANTIC_ATTRIBUTE_URL_FULL, sanitizedUrl);\n span.updateName(`${request.method || 'GET'} ${sanitizedUrl}`);\n }\n options.instrumentation?.requestHook?.(span, request);\n },\n outgoingResponseHook: options.instrumentation?.responseHook,\n outgoingRequestApplyCustomAttributes: options.instrumentation?.applyCustomAttributesOnSpan,\n };\n\n // This is Sentry-specific instrumentation for outgoing request\n // breadcrumbs & trace propagation. It uses the diagnostic channels on\n // node versions that support it, falling back to monkey-patching when\n // needed.\n instrumentSentryHttp(sentryHttpInstrumentationOptions);\n },\n processEvent(event) {\n // Always run this, even if spans are disabled\n // The reason being that e.g. the remix integration disables span\n // creation here but still wants to use the ignore status codes option\n return serverSpans.processEvent(event);\n },\n };\n});\n"],"names":[],"mappings":"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"}

@@ -1,2 +0,2 @@

import { instrumentSentryHttp, instrumentOtelHttp } from '../http.js';
import { instrumentSentryHttp } from '../http.js';
import { instrumentAmqplib, amqplibIntegration } from './amqplib.js';

@@ -26,3 +26,3 @@ import { instrumentAnthropicAi, anthropicAIIntegration } from './anthropic-ai/index.js';

import { prismaIntegration } from './prisma.js';
import { instrumentRedis, redisIntegration } from './redis.js';
import { instrumentRedis, redisIntegration } from './redis/index.js';
import { instrumentTedious, tediousIntegration } from './tedious.js';

@@ -75,3 +75,2 @@ import { instrumentVercelAi, vercelAIIntegration } from './vercelai/index.js';

instrumentSentryHttp,
instrumentOtelHttp,
instrumentExpress,

@@ -78,0 +77,0 @@ instrumentConnect,

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentOtelHttp, instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { googleGenAIIntegration, instrumentGoogleGenAI } from './google-genai';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { honoIntegration, instrumentHono } from './hono';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLangChain, langChainIntegration } from './langchain';\nimport { instrumentLangGraph, langGraphIntegration } from './langgraph';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n honoIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n // AI providers\n // LangChain must come first to disable AI provider integrations before they instrument\n langChainIntegration(),\n langGraphIntegration(),\n vercelAIIntegration(),\n openAIIntegration(),\n anthropicAIIntegration(),\n googleGenAIIntegration(),\n postgresJsIntegration(),\n firebaseIntegration(),\n ];\n}\n\n/**\n * Get a list of methods to instrument OTEL, when preload instrumentation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => void) & { id: string })[] {\n return [\n instrumentSentryHttp,\n instrumentOtelHttp,\n instrumentExpress,\n instrumentConnect,\n instrumentFastify,\n instrumentFastifyV3,\n instrumentHapi,\n instrumentHono,\n instrumentKafka,\n instrumentKoa,\n instrumentLruMemoizer,\n instrumentMongo,\n instrumentMongoose,\n instrumentMysql,\n instrumentMysql2,\n instrumentPostgres,\n instrumentHapi,\n instrumentGraphql,\n instrumentRedis,\n instrumentTedious,\n instrumentGenericPool,\n instrumentAmqplib,\n instrumentLangChain,\n instrumentVercelAi,\n instrumentOpenAi,\n instrumentPostgresJs,\n instrumentFirebase,\n instrumentAnthropicAi,\n instrumentGoogleGenAI,\n instrumentLangGraph,\n ];\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA;AACA;AACA;AACO,SAAS,8BAA8B,GAAkB;AAChE,EAAE,OAAO;AACT,IAAI,kBAAkB,EAAE;AACxB,IAAI,kBAAkB,EAAE;AACxB,IAAI,kBAAkB,EAAE;AACxB,IAAI,eAAe,EAAE;AACrB,IAAI,gBAAgB,EAAE;AACtB,IAAI,mBAAmB,EAAE;AACzB,IAAI,gBAAgB,EAAE;AACtB,IAAI,iBAAiB,EAAE;AACvB,IAAI,gBAAgB,EAAE;AACtB,IAAI,mBAAmB,EAAE;AACzB,IAAI,iBAAiB,EAAE;AACvB,IAAI,eAAe,EAAE;AACrB,IAAI,cAAc,EAAE;AACpB,IAAI,kBAAkB,EAAE;AACxB,IAAI,kBAAkB,EAAE;AACxB,IAAI,sBAAsB,EAAE;AAC5B,IAAI,gBAAgB,EAAE;AACtB,IAAI,kBAAkB,EAAE;AACxB,IAAI,sBAAsB,EAAE;AAC5B;AACA;AACA,IAAI,oBAAoB,EAAE;AAC1B,IAAI,oBAAoB,EAAE;AAC1B,IAAI,mBAAmB,EAAE;AACzB,IAAI,iBAAiB,EAAE;AACvB,IAAI,sBAAsB,EAAE;AAC5B,IAAI,sBAAsB,EAAE;AAC5B,IAAI,qBAAqB,EAAE;AAC3B,IAAI,mBAAmB,EAAE;AACzB,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACO,SAAS,wCAAwC,GAAmD;AAC3G,EAAE,OAAO;AACT,IAAI,oBAAoB;AACxB,IAAI,kBAAkB;AACtB,IAAI,iBAAiB;AACrB,IAAI,iBAAiB;AACrB,IAAI,iBAAiB;AACrB,IAAI,mBAAmB;AACvB,IAAI,cAAc;AAClB,IAAI,cAAc;AAClB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,qBAAqB;AACzB,IAAI,eAAe;AACnB,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,gBAAgB;AACpB,IAAI,kBAAkB;AACtB,IAAI,cAAc;AAClB,IAAI,iBAAiB;AACrB,IAAI,eAAe;AACnB,IAAI,iBAAiB;AACrB,IAAI,qBAAqB;AACzB,IAAI,iBAAiB;AACrB,IAAI,mBAAmB;AACvB,IAAI,kBAAkB;AACtB,IAAI,gBAAgB;AACpB,IAAI,oBAAoB;AACxB,IAAI,kBAAkB;AACtB,IAAI,qBAAqB;AACzB,IAAI,qBAAqB;AACzB,IAAI,mBAAmB;AACvB,GAAG;AACH;;;;"}
{"version":3,"file":"index.js","sources":["../../../../src/integrations/tracing/index.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { instrumentSentryHttp } from '../http';\nimport { amqplibIntegration, instrumentAmqplib } from './amqplib';\nimport { anthropicAIIntegration, instrumentAnthropicAi } from './anthropic-ai';\nimport { connectIntegration, instrumentConnect } from './connect';\nimport { expressIntegration, instrumentExpress } from './express';\nimport { fastifyIntegration, instrumentFastify, instrumentFastifyV3 } from './fastify';\nimport { firebaseIntegration, instrumentFirebase } from './firebase';\nimport { genericPoolIntegration, instrumentGenericPool } from './genericPool';\nimport { googleGenAIIntegration, instrumentGoogleGenAI } from './google-genai';\nimport { graphqlIntegration, instrumentGraphql } from './graphql';\nimport { hapiIntegration, instrumentHapi } from './hapi';\nimport { honoIntegration, instrumentHono } from './hono';\nimport { instrumentKafka, kafkaIntegration } from './kafka';\nimport { instrumentKoa, koaIntegration } from './koa';\nimport { instrumentLangChain, langChainIntegration } from './langchain';\nimport { instrumentLangGraph, langGraphIntegration } from './langgraph';\nimport { instrumentLruMemoizer, lruMemoizerIntegration } from './lrumemoizer';\nimport { instrumentMongo, mongoIntegration } from './mongo';\nimport { instrumentMongoose, mongooseIntegration } from './mongoose';\nimport { instrumentMysql, mysqlIntegration } from './mysql';\nimport { instrumentMysql2, mysql2Integration } from './mysql2';\nimport { instrumentOpenAi, openAIIntegration } from './openai';\nimport { instrumentPostgres, postgresIntegration } from './postgres';\nimport { instrumentPostgresJs, postgresJsIntegration } from './postgresjs';\nimport { prismaIntegration } from './prisma';\nimport { instrumentRedis, redisIntegration } from './redis';\nimport { instrumentTedious, tediousIntegration } from './tedious';\nimport { instrumentVercelAi, vercelAIIntegration } from './vercelai';\n\n/**\n * With OTEL, all performance integrations will be added, as OTEL only initializes them when the patched package is actually required.\n */\nexport function getAutoPerformanceIntegrations(): Integration[] {\n return [\n expressIntegration(),\n fastifyIntegration(),\n graphqlIntegration(),\n honoIntegration(),\n mongoIntegration(),\n mongooseIntegration(),\n mysqlIntegration(),\n mysql2Integration(),\n redisIntegration(),\n postgresIntegration(),\n prismaIntegration(),\n hapiIntegration(),\n koaIntegration(),\n connectIntegration(),\n tediousIntegration(),\n genericPoolIntegration(),\n kafkaIntegration(),\n amqplibIntegration(),\n lruMemoizerIntegration(),\n // AI providers\n // LangChain must come first to disable AI provider integrations before they instrument\n langChainIntegration(),\n langGraphIntegration(),\n vercelAIIntegration(),\n openAIIntegration(),\n anthropicAIIntegration(),\n googleGenAIIntegration(),\n postgresJsIntegration(),\n firebaseIntegration(),\n ];\n}\n\n/**\n * Get a list of methods to instrument OTEL, when preload instrumentation.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => void) & { id: string })[] {\n return [\n instrumentSentryHttp,\n instrumentExpress,\n instrumentConnect,\n instrumentFastify,\n instrumentFastifyV3,\n instrumentHapi,\n instrumentHono,\n instrumentKafka,\n instrumentKoa,\n instrumentLruMemoizer,\n instrumentMongo,\n instrumentMongoose,\n instrumentMysql,\n instrumentMysql2,\n instrumentPostgres,\n instrumentHapi,\n instrumentGraphql,\n instrumentRedis,\n instrumentTedious,\n instrumentGenericPool,\n instrumentAmqplib,\n instrumentLangChain,\n instrumentVercelAi,\n instrumentOpenAi,\n instrumentPostgresJs,\n instrumentFirebase,\n instrumentAnthropicAi,\n instrumentGoogleGenAI,\n instrumentLangGraph,\n ];\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA;AACA;AACA;AACO,SAAS,8BAA8B,GAAkB;AAChE,EAAE,OAAO;AACT,IAAI,kBAAkB,EAAE;AACxB,IAAI,kBAAkB,EAAE;AACxB,IAAI,kBAAkB,EAAE;AACxB,IAAI,eAAe,EAAE;AACrB,IAAI,gBAAgB,EAAE;AACtB,IAAI,mBAAmB,EAAE;AACzB,IAAI,gBAAgB,EAAE;AACtB,IAAI,iBAAiB,EAAE;AACvB,IAAI,gBAAgB,EAAE;AACtB,IAAI,mBAAmB,EAAE;AACzB,IAAI,iBAAiB,EAAE;AACvB,IAAI,eAAe,EAAE;AACrB,IAAI,cAAc,EAAE;AACpB,IAAI,kBAAkB,EAAE;AACxB,IAAI,kBAAkB,EAAE;AACxB,IAAI,sBAAsB,EAAE;AAC5B,IAAI,gBAAgB,EAAE;AACtB,IAAI,kBAAkB,EAAE;AACxB,IAAI,sBAAsB,EAAE;AAC5B;AACA;AACA,IAAI,oBAAoB,EAAE;AAC1B,IAAI,oBAAoB,EAAE;AAC1B,IAAI,mBAAmB,EAAE;AACzB,IAAI,iBAAiB,EAAE;AACvB,IAAI,sBAAsB,EAAE;AAC5B,IAAI,sBAAsB,EAAE;AAC5B,IAAI,qBAAqB,EAAE;AAC3B,IAAI,mBAAmB,EAAE;AACzB,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACO,SAAS,wCAAwC,GAAmD;AAC3G,EAAE,OAAO;AACT,IAAI,oBAAoB;AACxB,IAAI,iBAAiB;AACrB,IAAI,iBAAiB;AACrB,IAAI,iBAAiB;AACrB,IAAI,mBAAmB;AACvB,IAAI,cAAc;AAClB,IAAI,cAAc;AAClB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,qBAAqB;AACzB,IAAI,eAAe;AACnB,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,gBAAgB;AACpB,IAAI,kBAAkB;AACtB,IAAI,cAAc;AAClB,IAAI,iBAAiB;AACrB,IAAI,eAAe;AACnB,IAAI,iBAAiB;AACrB,IAAI,qBAAqB;AACzB,IAAI,iBAAiB;AACrB,IAAI,mBAAmB;AACvB,IAAI,kBAAkB;AACtB,IAAI,gBAAgB;AACpB,IAAI,oBAAoB;AACxB,IAAI,kBAAkB;AACtB,IAAI,qBAAqB;AACzB,IAAI,qBAAqB;AACzB,IAAI,mBAAmB;AACvB,GAAG;AACH;;;;"}

@@ -1,1 +0,1 @@

{"type":"module","version":"10.51.0","sideEffects":false}
{"type":"module","version":"10.52.0","sideEffects":false}

@@ -1,1 +0,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);\n } else {\n result.push(el);\n }\n });\n };\n\n flattenHelper(input);\n return result;\n}\n"],"names":[],"mappings":"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"}
{"version":3,"file":"redisCache.js","sources":["../../../src/utils/redisCache.ts"],"sourcesContent":["export type IORedisCommandArgs = Array<string | Buffer | number | unknown[]>;\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);\n } else {\n result.push(el);\n }\n });\n };\n\n flattenHelper(input);\n return result;\n}\n"],"names":[],"mappings":"AAEA,MAAM,mBAAA,GAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC;;MAEtC,YAAA,GAAe,CAAC,KAAK,EAAE,MAAM;MAC7B,YAAA,GAAe,CAAC,KAAK,EAAE,OAAO;AAC3C;;AAEA;AACA;AACO,SAAS,YAAY,CAAC,aAAa,EAAY,OAAO,EAAmB;AAChF,EAAE,OAAO,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;AACtD;;AAEA;AACO,SAAS,iBAAiB;AACjC,EAAE,OAAO;AACT,EAA0E;AAC1E,EAAE,IAAI,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE;AAC3C,IAAI,OAAO,WAAW;AACtB,EAAE,CAAA,MAAO,IAAI,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE;AAClD,IAAI,OAAO,WAAW;AACtB,EAAE,OAAO;AACT,IAAI,OAAO,SAAS;AACpB,EAAE;AACF;;AAEA,SAAS,YAAY,CAAC,GAAG,EAAU,QAAQ,EAAqB;AAChE,EAAE,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAA,IAAU,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACxD;;AAEA;AACO,SAAS,iBAAiB,CAAC,YAAY,EAAU,OAAO,EAA4C;AAC3G,EAAE,IAAI;AACN,IAAI,IAAI,OAAO,CAAC,MAAA,KAAW,CAAC,EAAE;AAC9B,MAAM,OAAO,SAAS;AACtB,IAAI;;AAEJ;AACA,IAAI,MAAM,UAAA,GAAa,CAAC,GAAG,KAAiD;AAC5E,MAAM,IAAI,OAAO,QAAQ,QAAA,IAAY,OAAO,GAAA,KAAQ,QAAA,IAAY,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AACtF,QAAQ,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;AAC/B,MAAM,CAAA,MAAO,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AACrC,QAAQ,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAA,IAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACvD,MAAM,OAAO;AACb,QAAQ,OAAO,CAAC,WAAW,CAAC;AAC5B,MAAM;AACN,IAAI,CAAC;;AAEL,IAAI,MAAM,QAAA,GAAW,OAAO,CAAC,CAAC,CAAC;AAC/B,IAAI,IAAI,YAAY,CAAC,mBAAmB,EAAE,YAAY,CAAA,IAAK,QAAA,IAAY,IAAI,EAAE;AAC7E,MAAM,OAAO,UAAU,CAAC,QAAQ,CAAC;AACjC,IAAI;;AAEJ,IAAI,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAA,IAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACvD,EAAE,EAAE,MAAM;AACV,IAAI,OAAO,SAAS;AACpB,EAAE;AACF;;AAEA;AACA;AACO,SAAS,sBAAsB,CAAC,YAAY,EAAU,IAAI,EAAY,QAAQ,EAAqB;AAC1G,EAAE,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE;AACxC,IAAI,OAAO,KAAK;AAChB,EAAE;;AAEF,EAAE,KAAK,MAAM,GAAA,IAAO,IAAI,EAAE;AAC1B,IAAI,IAAI,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE;AACrC,MAAM,OAAO,IAAI;AACjB,IAAI;AACJ,EAAE;AACF,EAAE,OAAO,KAAK;AACd;;AAEA;AACO,SAAS,sBAAsB,CAAC,QAAQ,EAA+B;AAC9E,EAAE,MAAM,OAAA,GAAU,CAAC,KAAK,KAAkC;AAC1D,IAAI,IAAI;AACR,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC,UAAU;AACzD,WAAW,IAAI,OAAO,KAAA,KAAU,QAAQ,EAAE,OAAO,KAAK,CAAC,MAAM;AAC7D,WAAW,IAAI,OAAO,UAAU,QAAQ,EAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM;AACxE,WAAW,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,SAAS,EAAE,OAAO,CAAC;AAC9D,MAAM,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM;AACzC,IAAI,EAAE,MAAM;AACZ,MAAM,OAAO,SAAS;AACtB,IAAI;AACJ,EAAE,CAAC;;AAEH,EAAE,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ;AAC/B,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAsB,IAAI,KAAK;AACzD,QAAQ,MAAM,IAAA,GAAO,OAAO,CAAC,IAAI,CAAC;AAClC,QAAQ,OAAO,OAAO,IAAA,KAAS,QAAA,IAAY,GAAA,KAAQ,SAAA,GAAY,MAAM,IAAA,GAAO,IAAI,IAAI,GAAG;AACvF,MAAM,CAAC,EAAE,CAAC;AACV,MAAM,OAAO,CAAC,QAAQ,CAAC;AACvB;;AAIA,SAAS,OAAO,CAAI,KAAK,EAAuB;AAChD,EAAE,MAAM,MAAM,GAAQ,EAAE;;AAExB,EAAE,MAAM,aAAA,GAAgB,CAAC,KAAK,KAA2B;AACzD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAyB;AAC9C,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;AAC7B,QAAQ,aAAa,CAAC,EAAE,CAAC;AACzB,MAAM,OAAO;AACb,QAAQ,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;AACvB,MAAM;AACN,IAAI,CAAC,CAAC;AACN,EAAE,CAAC;;AAEH,EAAE,aAAa,CAAC,KAAK,CAAC;AACtB,EAAE,OAAO,MAAM;AACf;;;;"}

@@ -1,6 +0,4 @@

import { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } from 'node:http';
import { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';
import { Span } from '@sentry/core';
import { HTTPModuleRequestIncomingMessage, SentryHttpInstrumentationOptions } from '@sentry/node-core';
import { NodeClientOptions } from '../types';
import { RequestOptions } from 'node:http';
import { HttpClientRequest, HttpIncomingMessage, HttpServerResponse, Span } from '@sentry/core';
import { SentryHttpInstrumentationOptions } from '@sentry/node-core';
interface HttpOptions {

@@ -64,3 +62,3 @@ /**

*/
ignoreIncomingRequests?: (urlPath: string, request: IncomingMessage) => boolean;
ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;
/**

@@ -70,3 +68,3 @@ * A hook that can be used to mutate the span for incoming requests.

*/
incomingRequestSpanHook?: (span: Span, request: IncomingMessage, response: ServerResponse) => void;
incomingRequestSpanHook?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;
/**

@@ -122,5 +120,5 @@ * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.

instrumentation?: {
requestHook?: (span: Span, req: ClientRequest | HTTPModuleRequestIncomingMessage) => void;
responseHook?: (span: Span, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;
applyCustomAttributesOnSpan?: (span: Span, request: ClientRequest | HTTPModuleRequestIncomingMessage, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;
requestHook?: (span: Span, req: HttpIncomingMessage | HttpClientRequest) => void;
responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;
applyCustomAttributesOnSpan?: (span: Span, request: HttpIncomingMessage | HttpClientRequest, response: HttpIncomingMessage | HttpServerResponse) => void;
};

@@ -131,7 +129,2 @@ }

};
export declare const instrumentOtelHttp: ((options?: HttpInstrumentationConfig | undefined) => import("@opentelemetry/instrumentation").Instrumentation<import("@opentelemetry/instrumentation").InstrumentationConfig>) & {
id: string;
};
/** Exported only for tests. */
export declare function _shouldUseOtelHttpInstrumentation(options: HttpOptions, clientOptions?: Partial<NodeClientOptions>): boolean;
/**

@@ -138,0 +131,0 @@ * The http integration instruments Node's internal http and https modules.

@@ -1,2 +0,2 @@

import { CommandArgs as IORedisCommandArgs } from '@opentelemetry/instrumentation-ioredis';
export type IORedisCommandArgs = Array<string | Buffer | number | unknown[]>;
export declare const GET_COMMANDS: string[];

@@ -3,0 +3,0 @@ export declare const SET_COMMANDS: string[];

@@ -1,6 +0,4 @@

import type { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } from 'node:http';
import type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';
import type { Span } from '@sentry/core';
import type { HTTPModuleRequestIncomingMessage, SentryHttpInstrumentationOptions } from '@sentry/node-core';
import type { NodeClientOptions } from '../types';
import type { RequestOptions } from 'node:http';
import type { HttpClientRequest, HttpIncomingMessage, HttpServerResponse, Span } from '@sentry/core';
import type { SentryHttpInstrumentationOptions } from '@sentry/node-core';
interface HttpOptions {

@@ -64,3 +62,3 @@ /**

*/
ignoreIncomingRequests?: (urlPath: string, request: IncomingMessage) => boolean;
ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;
/**

@@ -70,3 +68,3 @@ * A hook that can be used to mutate the span for incoming requests.

*/
incomingRequestSpanHook?: (span: Span, request: IncomingMessage, response: ServerResponse) => void;
incomingRequestSpanHook?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;
/**

@@ -119,5 +117,5 @@ * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.

instrumentation?: {
requestHook?: (span: Span, req: ClientRequest | HTTPModuleRequestIncomingMessage) => void;
responseHook?: (span: Span, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;
applyCustomAttributesOnSpan?: (span: Span, request: ClientRequest | HTTPModuleRequestIncomingMessage, response: HTTPModuleRequestIncomingMessage | ServerResponse) => void;
requestHook?: (span: Span, req: HttpIncomingMessage | HttpClientRequest) => void;
responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;
applyCustomAttributesOnSpan?: (span: Span, request: HttpIncomingMessage | HttpClientRequest, response: HttpIncomingMessage | HttpServerResponse) => void;
};

@@ -128,7 +126,2 @@ }

};
export declare const instrumentOtelHttp: ((options?: HttpInstrumentationConfig | undefined) => import("@opentelemetry/instrumentation").Instrumentation<import("@opentelemetry/instrumentation").InstrumentationConfig>) & {
id: string;
};
/** Exported only for tests. */
export declare function _shouldUseOtelHttpInstrumentation(options: HttpOptions, clientOptions?: Partial<NodeClientOptions>): boolean;
/**

@@ -135,0 +128,0 @@ * The http integration instruments Node's internal http and https modules.

@@ -1,1 +0,1 @@

{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/integrations/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhG,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAErF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAQzC,OAAO,KAAK,EAAE,gCAAgC,EAAc,gCAAgC,EAAE,MAAM,mBAAmB,CAAC;AAUxH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAalD,UAAU,WAAW;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;OAKG;IACH,+BAA+B,CAAC,EAAE,OAAO,CAAC;IAE1C;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;;;;;OASG;IACH,sBAAsB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAE3E;;;;;;;;;OASG;IACH,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC;IAEhF;;;OAGG;IACH,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;IAEnG;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;OAMG;IACH,sCAAsC,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAEvE;;;;;;OAMG;IACH,yBAAyB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAE9E;;;;;;;;;;;;;OAaG;IACH,0BAA0B,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAEpE;;;OAGG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAEtC;;OAEG;IACH,eAAe,CAAC,EAAE;QAChB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,GAAG,gCAAgC,KAAK,IAAI,CAAC;QAC1F,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,gCAAgC,GAAG,cAAc,KAAK,IAAI,CAAC;QACjG,2BAA2B,CAAC,EAAE,CAC5B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,aAAa,GAAG,gCAAgC,EACzD,QAAQ,EAAE,gCAAgC,GAAG,cAAc,KACxD,IAAI,CAAC;KACX,CAAC;CACH;AAED,eAAO,MAAM,oBAAoB;;CAKhC,CAAC;AAEF,eAAO,MAAM,kBAAkB;;CAiC7B,CAAC;AAEH,+BAA+B;AAC/B,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,WAAW,EACpB,aAAa,GAAE,OAAO,CAAC,iBAAiB,CAAM,GAC7C,OAAO,CAkBT;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,2EA+E1B,CAAC"}
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/integrations/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAQrG,OAAO,KAAK,EAEV,gCAAgC,EAGjC,MAAM,mBAAmB,CAAC;AAY3B,UAAU,WAAW;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;OAKG;IACH,+BAA+B,CAAC,EAAE,OAAO,CAAC;IAE1C;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;;;;;;OASG;IACH,sBAAsB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAE3E;;;;;;;;;OASG;IACH,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC;IAEpF;;;OAGG;IACH,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAE3G;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;OAMG;IACH,sCAAsC,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAEvE;;;;;;OAMG;IACH,yBAAyB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAE9E;;;;;;;;;;;;;OAaG;IACH,0BAA0B,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAEpE;;;OAGG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAEtC;;OAEG;IACH,eAAe,CAAC,EAAE;QAChB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,mBAAmB,GAAG,iBAAiB,KAAK,IAAI,CAAC;QACjF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,mBAAmB,GAAG,kBAAkB,KAAK,IAAI,CAAC;QACxF,2BAA2B,CAAC,EAAE,CAC5B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,mBAAmB,GAAG,iBAAiB,EAChD,QAAQ,EAAE,mBAAmB,GAAG,kBAAkB,KAC/C,IAAI,CAAC;KACX,CAAC;CACH;AAED,eAAO,MAAM,oBAAoB;;CAKhC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,2EAuE1B,CAAC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AA8BhD;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,WAAW,EAAE,CAgC9D;AAED;;GAEG;AAEH,wBAAgB,wCAAwC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,CAiCzG"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AA8BhD;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,WAAW,EAAE,CAgC9D;AAED;;GAEG;AAEH,wBAAgB,wCAAwC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,CAgCzG"}

@@ -1,2 +0,2 @@

import type { CommandArgs as IORedisCommandArgs } from '@opentelemetry/instrumentation-ioredis';
export type IORedisCommandArgs = Array<string | Buffer | number | unknown[]>;
export declare const GET_COMMANDS: string[];

@@ -3,0 +3,0 @@ export declare const SET_COMMANDS: string[];

@@ -1,1 +0,1 @@

{"version":3,"file":"redisCache.d.ts","sourceRoot":"","sources":["../../../src/utils/redisCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,IAAI,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAIhG,eAAO,MAAM,YAAY,UAAkB,CAAC;AAC5C,eAAO,MAAM,YAAY,UAAmB,CAAC;AAG7C;6FAC6F;AAC7F,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE9E;AAED,yDAAyD;AACzD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,GACd,WAAW,GAAG,WAAW,GAAG,cAAc,GAAG,aAAa,GAAG,SAAS,CAQxE;AAMD,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,EAAE,GAAG,SAAS,CA0BzG;AAED;uEACuE;AACvE,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAWxG;AAED,wDAAwD;AACxD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAmB5E"}
{"version":3,"file":"redisCache.d.ts","sourceRoot":"","sources":["../../../src/utils/redisCache.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,CAAC,CAAC;AAI7E,eAAO,MAAM,YAAY,UAAkB,CAAC;AAC5C,eAAO,MAAM,YAAY,UAAmB,CAAC;AAG7C;6FAC6F;AAC7F,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE9E;AAED,yDAAyD;AACzD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,GACd,WAAW,GAAG,WAAW,GAAG,cAAc,GAAG,aAAa,GAAG,SAAS,CAQxE;AAMD,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,EAAE,GAAG,SAAS,CA0BzG;AAED;uEACuE;AACvE,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAWxG;AAED,wDAAwD;AACxD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAmB5E"}
{
"name": "@sentry/node",
"version": "10.51.0",
"version": "10.52.0",
"description": "Sentry Node SDK using OpenTelemetry for performance instrumentation",

@@ -79,3 +79,2 @@ "repository": "git://github.com/getsentry/sentry-javascript.git",

"@opentelemetry/instrumentation-http": "0.214.0",
"@opentelemetry/instrumentation-ioredis": "0.62.0",
"@opentelemetry/instrumentation-kafkajs": "0.23.0",

@@ -90,3 +89,2 @@ "@opentelemetry/instrumentation-knex": "0.58.0",

"@opentelemetry/instrumentation-pg": "0.66.0",
"@opentelemetry/instrumentation-redis": "0.62.0",
"@opentelemetry/instrumentation-tedious": "0.33.0",

@@ -97,5 +95,5 @@ "@opentelemetry/sdk-trace-base": "^2.6.1",

"@fastify/otel": "0.18.0",
"@sentry/core": "10.51.0",
"@sentry/node-core": "10.51.0",
"@sentry/opentelemetry": "10.51.0",
"@sentry/core": "10.52.0",
"@sentry/node-core": "10.52.0",
"@sentry/opentelemetry": "10.52.0",
"import-in-the-middle": "^3.0.0"

@@ -102,0 +100,0 @@ },

Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const instrumentationIoredis = require('@opentelemetry/instrumentation-ioredis');
const instrumentationRedis = require('@opentelemetry/instrumentation-redis');
const core = require('@sentry/core');
const nodeCore = require('@sentry/node-core');
const redisCache = require('../../utils/redisCache.js');
const INTEGRATION_NAME = 'Redis';
/* Only exported for testing purposes */
exports._redisOptions = {};
/* Only exported for testing purposes */
const cacheResponseHook = (
span,
redisCommand,
cmdArgs,
response,
) => {
span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.redis');
const safeKey = redisCache.getCacheKeySafely(redisCommand, cmdArgs);
const cacheOperation = redisCache.getCacheOperation(redisCommand);
if (
!safeKey ||
!cacheOperation ||
!exports._redisOptions.cachePrefixes ||
!redisCache.shouldConsiderForCache(redisCommand, safeKey, exports._redisOptions.cachePrefixes)
) {
// not relevant for cache
return;
}
// otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199
// We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/
const networkPeerAddress = core.spanToJSON(span).data['net.peer.name'];
const networkPeerPort = core.spanToJSON(span).data['net.peer.port'];
if (networkPeerPort && networkPeerAddress) {
span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });
}
const cacheItemSize = redisCache.calculateCacheItemSize(response);
if (cacheItemSize) {
span.setAttribute(core.SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);
}
if (redisCache.isInCommands(redisCache.GET_COMMANDS, redisCommand) && cacheItemSize !== undefined) {
span.setAttribute(core.SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);
}
span.setAttributes({
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,
[core.SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey,
});
// todo: change to string[] once EAP supports it
const spanDescription = safeKey.join(', ');
span.updateName(
exports._redisOptions.maxCacheKeyLength ? core.truncate(spanDescription, exports._redisOptions.maxCacheKeyLength) : spanDescription,
);
};
const instrumentIORedis = nodeCore.generateInstrumentOnce(`${INTEGRATION_NAME}.IORedis`, () => {
return new instrumentationIoredis.IORedisInstrumentation({
responseHook: cacheResponseHook,
});
});
const instrumentRedisModule = nodeCore.generateInstrumentOnce(`${INTEGRATION_NAME}.Redis`, () => {
return new instrumentationRedis.RedisInstrumentation({
responseHook: cacheResponseHook,
});
});
/** To be able to preload all Redis OTel instrumentations with just one ID ("Redis"), all the instrumentations are generated in this one function */
const instrumentRedis = Object.assign(
() => {
instrumentIORedis();
instrumentRedisModule();
// todo: implement them gradually
// new LegacyRedisInstrumentation({}),
},
{ id: INTEGRATION_NAME },
);
const _redisIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
exports._redisOptions = options;
instrumentRedis();
},
};
}) ;
/**
* Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and
* [ioredis](https://www.npmjs.com/package/ioredis) libraries.
*
* For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).
*
* @example
* ```javascript
* const Sentry = require('@sentry/node');
*
* Sentry.init({
* integrations: [Sentry.redisIntegration()],
* });
* ```
*/
const redisIntegration = core.defineIntegration(_redisIntegration);
exports.cacheResponseHook = cacheResponseHook;
exports.instrumentRedis = instrumentRedis;
exports.redisIntegration = redisIntegration;
//# sourceMappingURL=redis.js.map
{"version":3,"file":"redis.js","sources":["../../../../src/integrations/tracing/redis.ts"],"sourcesContent":["import type { Span } from '@opentelemetry/api';\nimport type { RedisResponseCustomAttributeFunction } from '@opentelemetry/instrumentation-ioredis';\nimport { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis';\nimport { RedisInstrumentation } from '@opentelemetry/instrumentation-redis';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n defineIntegration,\n SEMANTIC_ATTRIBUTE_CACHE_HIT,\n SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE,\n SEMANTIC_ATTRIBUTE_CACHE_KEY,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n truncate,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport {\n calculateCacheItemSize,\n GET_COMMANDS,\n getCacheKeySafely,\n getCacheOperation,\n isInCommands,\n shouldConsiderForCache,\n} from '../../utils/redisCache';\n\ninterface RedisOptions {\n /**\n * Define cache prefixes for cache keys that should be captured as a cache span.\n *\n * Setting this to, for example, `['user:']` will capture cache keys that start with `user:`.\n */\n cachePrefixes?: string[];\n /**\n * Maximum length of the cache key added to the span description. If the key exceeds this length, it will be truncated.\n *\n * Passing `0` will use the full cache key without truncation.\n *\n * By default, the full cache key is used.\n */\n maxCacheKeyLength?: number;\n}\n\nconst INTEGRATION_NAME = 'Redis';\n\n/* Only exported for testing purposes */\nexport let _redisOptions: RedisOptions = {};\n\n/* Only exported for testing purposes */\nexport const cacheResponseHook: RedisResponseCustomAttributeFunction = (\n span: Span,\n redisCommand,\n cmdArgs,\n response,\n) => {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.redis');\n\n const safeKey = getCacheKeySafely(redisCommand, cmdArgs);\n const cacheOperation = getCacheOperation(redisCommand);\n\n if (\n !safeKey ||\n !cacheOperation ||\n !_redisOptions.cachePrefixes ||\n !shouldConsiderForCache(redisCommand, safeKey, _redisOptions.cachePrefixes)\n ) {\n // not relevant for cache\n return;\n }\n\n // otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199\n // We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/\n const networkPeerAddress = spanToJSON(span).data['net.peer.name'];\n const networkPeerPort = spanToJSON(span).data['net.peer.port'];\n if (networkPeerPort && networkPeerAddress) {\n span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });\n }\n\n const cacheItemSize = calculateCacheItemSize(response);\n\n if (cacheItemSize) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);\n }\n\n if (isInCommands(GET_COMMANDS, redisCommand) && cacheItemSize !== undefined) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);\n }\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,\n [SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey,\n });\n\n // todo: change to string[] once EAP supports it\n const spanDescription = safeKey.join(', ');\n\n span.updateName(\n _redisOptions.maxCacheKeyLength ? truncate(spanDescription, _redisOptions.maxCacheKeyLength) : spanDescription,\n );\n};\n\nconst instrumentIORedis = generateInstrumentOnce(`${INTEGRATION_NAME}.IORedis`, () => {\n return new IORedisInstrumentation({\n responseHook: cacheResponseHook,\n });\n});\n\nconst instrumentRedisModule = generateInstrumentOnce(`${INTEGRATION_NAME}.Redis`, () => {\n return new RedisInstrumentation({\n responseHook: cacheResponseHook,\n });\n});\n\n/** To be able to preload all Redis OTel instrumentations with just one ID (\"Redis\"), all the instrumentations are generated in this one function */\nexport const instrumentRedis = Object.assign(\n (): void => {\n instrumentIORedis();\n instrumentRedisModule();\n\n // todo: implement them gradually\n // new LegacyRedisInstrumentation({}),\n },\n { id: INTEGRATION_NAME },\n);\n\nconst _redisIntegration = ((options: RedisOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n _redisOptions = options;\n instrumentRedis();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and\n * [ioredis](https://www.npmjs.com/package/ioredis) libraries.\n *\n * For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.redisIntegration()],\n * });\n * ```\n */\nexport const redisIntegration = defineIntegration(_redisIntegration);\n"],"names":["_redisOptions","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","getCacheKeySafely","getCacheOperation","shouldConsiderForCache","spanToJSON","calculateCacheItemSize","SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE","isInCommands","GET_COMMANDS","SEMANTIC_ATTRIBUTE_CACHE_HIT","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_CACHE_KEY","truncate","generateInstrumentOnce","IORedisInstrumentation","RedisInstrumentation","defineIntegration"],"mappings":"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"}
import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis';
import { RedisInstrumentation } from '@opentelemetry/instrumentation-redis';
import { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, spanToJSON, SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, SEMANTIC_ATTRIBUTE_CACHE_HIT, SEMANTIC_ATTRIBUTE_CACHE_KEY, SEMANTIC_ATTRIBUTE_SENTRY_OP, truncate } from '@sentry/core';
import { generateInstrumentOnce } from '@sentry/node-core';
import { getCacheKeySafely, getCacheOperation, shouldConsiderForCache, calculateCacheItemSize, isInCommands, GET_COMMANDS } from '../../utils/redisCache.js';
const INTEGRATION_NAME = 'Redis';
/* Only exported for testing purposes */
let _redisOptions = {};
/* Only exported for testing purposes */
const cacheResponseHook = (
span,
redisCommand,
cmdArgs,
response,
) => {
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.redis');
const safeKey = getCacheKeySafely(redisCommand, cmdArgs);
const cacheOperation = getCacheOperation(redisCommand);
if (
!safeKey ||
!cacheOperation ||
!_redisOptions.cachePrefixes ||
!shouldConsiderForCache(redisCommand, safeKey, _redisOptions.cachePrefixes)
) {
// not relevant for cache
return;
}
// otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199
// We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/
const networkPeerAddress = spanToJSON(span).data['net.peer.name'];
const networkPeerPort = spanToJSON(span).data['net.peer.port'];
if (networkPeerPort && networkPeerAddress) {
span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });
}
const cacheItemSize = calculateCacheItemSize(response);
if (cacheItemSize) {
span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);
}
if (isInCommands(GET_COMMANDS, redisCommand) && cacheItemSize !== undefined) {
span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);
}
span.setAttributes({
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,
[SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey,
});
// todo: change to string[] once EAP supports it
const spanDescription = safeKey.join(', ');
span.updateName(
_redisOptions.maxCacheKeyLength ? truncate(spanDescription, _redisOptions.maxCacheKeyLength) : spanDescription,
);
};
const instrumentIORedis = generateInstrumentOnce(`${INTEGRATION_NAME}.IORedis`, () => {
return new IORedisInstrumentation({
responseHook: cacheResponseHook,
});
});
const instrumentRedisModule = generateInstrumentOnce(`${INTEGRATION_NAME}.Redis`, () => {
return new RedisInstrumentation({
responseHook: cacheResponseHook,
});
});
/** To be able to preload all Redis OTel instrumentations with just one ID ("Redis"), all the instrumentations are generated in this one function */
const instrumentRedis = Object.assign(
() => {
instrumentIORedis();
instrumentRedisModule();
// todo: implement them gradually
// new LegacyRedisInstrumentation({}),
},
{ id: INTEGRATION_NAME },
);
const _redisIntegration = ((options = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
_redisOptions = options;
instrumentRedis();
},
};
}) ;
/**
* Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and
* [ioredis](https://www.npmjs.com/package/ioredis) libraries.
*
* For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).
*
* @example
* ```javascript
* const Sentry = require('@sentry/node');
*
* Sentry.init({
* integrations: [Sentry.redisIntegration()],
* });
* ```
*/
const redisIntegration = defineIntegration(_redisIntegration);
export { _redisOptions, cacheResponseHook, instrumentRedis, redisIntegration };
//# sourceMappingURL=redis.js.map
{"version":3,"file":"redis.js","sources":["../../../../src/integrations/tracing/redis.ts"],"sourcesContent":["import type { Span } from '@opentelemetry/api';\nimport type { RedisResponseCustomAttributeFunction } from '@opentelemetry/instrumentation-ioredis';\nimport { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis';\nimport { RedisInstrumentation } from '@opentelemetry/instrumentation-redis';\nimport type { IntegrationFn } from '@sentry/core';\nimport {\n defineIntegration,\n SEMANTIC_ATTRIBUTE_CACHE_HIT,\n SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE,\n SEMANTIC_ATTRIBUTE_CACHE_KEY,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n truncate,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport {\n calculateCacheItemSize,\n GET_COMMANDS,\n getCacheKeySafely,\n getCacheOperation,\n isInCommands,\n shouldConsiderForCache,\n} from '../../utils/redisCache';\n\ninterface RedisOptions {\n /**\n * Define cache prefixes for cache keys that should be captured as a cache span.\n *\n * Setting this to, for example, `['user:']` will capture cache keys that start with `user:`.\n */\n cachePrefixes?: string[];\n /**\n * Maximum length of the cache key added to the span description. If the key exceeds this length, it will be truncated.\n *\n * Passing `0` will use the full cache key without truncation.\n *\n * By default, the full cache key is used.\n */\n maxCacheKeyLength?: number;\n}\n\nconst INTEGRATION_NAME = 'Redis';\n\n/* Only exported for testing purposes */\nexport let _redisOptions: RedisOptions = {};\n\n/* Only exported for testing purposes */\nexport const cacheResponseHook: RedisResponseCustomAttributeFunction = (\n span: Span,\n redisCommand,\n cmdArgs,\n response,\n) => {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.redis');\n\n const safeKey = getCacheKeySafely(redisCommand, cmdArgs);\n const cacheOperation = getCacheOperation(redisCommand);\n\n if (\n !safeKey ||\n !cacheOperation ||\n !_redisOptions.cachePrefixes ||\n !shouldConsiderForCache(redisCommand, safeKey, _redisOptions.cachePrefixes)\n ) {\n // not relevant for cache\n return;\n }\n\n // otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199\n // We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/\n const networkPeerAddress = spanToJSON(span).data['net.peer.name'];\n const networkPeerPort = spanToJSON(span).data['net.peer.port'];\n if (networkPeerPort && networkPeerAddress) {\n span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });\n }\n\n const cacheItemSize = calculateCacheItemSize(response);\n\n if (cacheItemSize) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);\n }\n\n if (isInCommands(GET_COMMANDS, redisCommand) && cacheItemSize !== undefined) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);\n }\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,\n [SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey,\n });\n\n // todo: change to string[] once EAP supports it\n const spanDescription = safeKey.join(', ');\n\n span.updateName(\n _redisOptions.maxCacheKeyLength ? truncate(spanDescription, _redisOptions.maxCacheKeyLength) : spanDescription,\n );\n};\n\nconst instrumentIORedis = generateInstrumentOnce(`${INTEGRATION_NAME}.IORedis`, () => {\n return new IORedisInstrumentation({\n responseHook: cacheResponseHook,\n });\n});\n\nconst instrumentRedisModule = generateInstrumentOnce(`${INTEGRATION_NAME}.Redis`, () => {\n return new RedisInstrumentation({\n responseHook: cacheResponseHook,\n });\n});\n\n/** To be able to preload all Redis OTel instrumentations with just one ID (\"Redis\"), all the instrumentations are generated in this one function */\nexport const instrumentRedis = Object.assign(\n (): void => {\n instrumentIORedis();\n instrumentRedisModule();\n\n // todo: implement them gradually\n // new LegacyRedisInstrumentation({}),\n },\n { id: INTEGRATION_NAME },\n);\n\nconst _redisIntegration = ((options: RedisOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n _redisOptions = options;\n instrumentRedis();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and\n * [ioredis](https://www.npmjs.com/package/ioredis) libraries.\n *\n * For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.redisIntegration()],\n * });\n * ```\n */\nexport const redisIntegration = defineIntegration(_redisIntegration);\n"],"names":[],"mappings":"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"}
import { RedisResponseCustomAttributeFunction } from '@opentelemetry/instrumentation-ioredis';
interface RedisOptions {
/**
* Define cache prefixes for cache keys that should be captured as a cache span.
*
* Setting this to, for example, `['user:']` will capture cache keys that start with `user:`.
*/
cachePrefixes?: string[];
/**
* Maximum length of the cache key added to the span description. If the key exceeds this length, it will be truncated.
*
* Passing `0` will use the full cache key without truncation.
*
* By default, the full cache key is used.
*/
maxCacheKeyLength?: number;
}
export declare let _redisOptions: RedisOptions;
export declare const cacheResponseHook: RedisResponseCustomAttributeFunction;
/** To be able to preload all Redis OTel instrumentations with just one ID ("Redis"), all the instrumentations are generated in this one function */
export declare const instrumentRedis: (() => void) & {
id: string;
};
/**
* Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and
* [ioredis](https://www.npmjs.com/package/ioredis) libraries.
*
* For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).
*
* @example
* ```javascript
* const Sentry = require('@sentry/node');
*
* Sentry.init({
* integrations: [Sentry.redisIntegration()],
* });
* ```
*/
export declare const redisIntegration: (options?: RedisOptions | undefined) => import("@sentry/core").Integration;
export {};
//# sourceMappingURL=redis.d.ts.map
import type { RedisResponseCustomAttributeFunction } from '@opentelemetry/instrumentation-ioredis';
interface RedisOptions {
/**
* Define cache prefixes for cache keys that should be captured as a cache span.
*
* Setting this to, for example, `['user:']` will capture cache keys that start with `user:`.
*/
cachePrefixes?: string[];
/**
* Maximum length of the cache key added to the span description. If the key exceeds this length, it will be truncated.
*
* Passing `0` will use the full cache key without truncation.
*
* By default, the full cache key is used.
*/
maxCacheKeyLength?: number;
}
export declare let _redisOptions: RedisOptions;
export declare const cacheResponseHook: RedisResponseCustomAttributeFunction;
/** To be able to preload all Redis OTel instrumentations with just one ID ("Redis"), all the instrumentations are generated in this one function */
export declare const instrumentRedis: (() => void) & {
id: string;
};
/**
* Adds Sentry tracing instrumentation for the [redis](https://www.npmjs.com/package/redis) and
* [ioredis](https://www.npmjs.com/package/ioredis) libraries.
*
* For more information, see the [`redisIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/redis/).
*
* @example
* ```javascript
* const Sentry = require('@sentry/node');
*
* Sentry.init({
* integrations: [Sentry.redisIntegration()],
* });
* ```
*/
export declare const redisIntegration: (options?: RedisOptions | undefined) => import("@sentry/core").Integration;
export {};
//# sourceMappingURL=redis.d.ts.map
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../../../src/integrations/tracing/redis.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AAwBnG,UAAU,YAAY;IACpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAKD,eAAO,IAAI,aAAa,EAAE,YAAiB,CAAC;AAG5C,eAAO,MAAM,iBAAiB,EAAE,oCAkD/B,CAAC;AAcF,qJAAqJ;AACrJ,eAAO,MAAM,eAAe,SACtB,IAAI;;CAQT,CAAC;AAYF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,4EAAuC,CAAC"}