@sentry/node 10.51.0 → 10.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/build/cjs/index.js +4 -4
  2. package/build/cjs/integrations/http.js +18 -145
  3. package/build/cjs/integrations/http.js.map +1 -1
  4. package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js +8 -8
  5. package/build/cjs/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
  6. package/build/cjs/integrations/tracing/google-genai/instrumentation.js +9 -9
  7. package/build/cjs/integrations/tracing/google-genai/instrumentation.js.map +1 -1
  8. package/build/cjs/integrations/tracing/index.js +21 -22
  9. package/build/cjs/integrations/tracing/index.js.map +1 -1
  10. package/build/cjs/integrations/tracing/langchain/instrumentation.js +12 -12
  11. package/build/cjs/integrations/tracing/langchain/instrumentation.js.map +1 -1
  12. package/build/cjs/integrations/tracing/langgraph/instrumentation.js +12 -12
  13. package/build/cjs/integrations/tracing/langgraph/instrumentation.js.map +1 -1
  14. package/build/cjs/integrations/tracing/openai/instrumentation.js +11 -11
  15. package/build/cjs/integrations/tracing/openai/instrumentation.js.map +1 -1
  16. package/build/cjs/integrations/tracing/postgresjs.js +10 -10
  17. package/build/cjs/integrations/tracing/postgresjs.js.map +1 -1
  18. package/build/cjs/integrations/tracing/{redis.js → redis/index.js} +18 -10
  19. package/build/cjs/integrations/tracing/redis/index.js.map +1 -0
  20. package/build/cjs/integrations/tracing/redis/redis-dc-subscriber.js +186 -0
  21. package/build/cjs/integrations/tracing/redis/redis-dc-subscriber.js.map +1 -0
  22. package/build/cjs/integrations/tracing/redis/vendored/ioredis-instrumentation.js +255 -0
  23. package/build/cjs/integrations/tracing/redis/vendored/ioredis-instrumentation.js.map +1 -0
  24. package/build/cjs/integrations/tracing/redis/vendored/redis-common.js +74 -0
  25. package/build/cjs/integrations/tracing/redis/vendored/redis-common.js.map +1 -0
  26. package/build/cjs/integrations/tracing/redis/vendored/redis-instrumentation.js +685 -0
  27. package/build/cjs/integrations/tracing/redis/vendored/redis-instrumentation.js.map +1 -0
  28. package/build/cjs/integrations/tracing/redis/vendored/semconv.js +47 -0
  29. package/build/cjs/integrations/tracing/redis/vendored/semconv.js.map +1 -0
  30. package/build/cjs/utils/redisCache.js.map +1 -1
  31. package/build/esm/index.js +1 -1
  32. package/build/esm/integrations/http.js +21 -146
  33. package/build/esm/integrations/http.js.map +1 -1
  34. package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js +8 -8
  35. package/build/esm/integrations/tracing/anthropic-ai/instrumentation.js.map +1 -1
  36. package/build/esm/integrations/tracing/google-genai/instrumentation.js +9 -9
  37. package/build/esm/integrations/tracing/google-genai/instrumentation.js.map +1 -1
  38. package/build/esm/integrations/tracing/index.js +2 -3
  39. package/build/esm/integrations/tracing/index.js.map +1 -1
  40. package/build/esm/integrations/tracing/langchain/instrumentation.js +12 -12
  41. package/build/esm/integrations/tracing/langchain/instrumentation.js.map +1 -1
  42. package/build/esm/integrations/tracing/langgraph/instrumentation.js +12 -12
  43. package/build/esm/integrations/tracing/langgraph/instrumentation.js.map +1 -1
  44. package/build/esm/integrations/tracing/openai/instrumentation.js +11 -11
  45. package/build/esm/integrations/tracing/openai/instrumentation.js.map +1 -1
  46. package/build/esm/integrations/tracing/postgresjs.js +10 -10
  47. package/build/esm/integrations/tracing/postgresjs.js.map +1 -1
  48. package/build/esm/integrations/tracing/{redis.js → redis/index.js} +17 -9
  49. package/build/esm/integrations/tracing/redis/index.js.map +1 -0
  50. package/build/esm/integrations/tracing/redis/redis-dc-subscriber.js +184 -0
  51. package/build/esm/integrations/tracing/redis/redis-dc-subscriber.js.map +1 -0
  52. package/build/esm/integrations/tracing/redis/vendored/ioredis-instrumentation.js +253 -0
  53. package/build/esm/integrations/tracing/redis/vendored/ioredis-instrumentation.js.map +1 -0
  54. package/build/esm/integrations/tracing/redis/vendored/redis-common.js +72 -0
  55. package/build/esm/integrations/tracing/redis/vendored/redis-common.js.map +1 -0
  56. package/build/esm/integrations/tracing/redis/vendored/redis-instrumentation.js +683 -0
  57. package/build/esm/integrations/tracing/redis/vendored/redis-instrumentation.js.map +1 -0
  58. package/build/esm/integrations/tracing/redis/vendored/semconv.js +39 -0
  59. package/build/esm/integrations/tracing/redis/vendored/semconv.js.map +1 -0
  60. package/build/esm/package.json +1 -1
  61. package/build/esm/utils/redisCache.js.map +1 -1
  62. package/build/types/integrations/http.d.ts +8 -15
  63. package/build/types/integrations/http.d.ts.map +1 -1
  64. package/build/types/integrations/tracing/index.d.ts.map +1 -1
  65. package/build/types/integrations/tracing/{redis.d.ts → redis/index.d.ts} +3 -3
  66. package/build/types/integrations/tracing/redis/index.d.ts.map +1 -0
  67. package/build/types/integrations/tracing/redis/redis-dc-subscriber.d.ts +17 -0
  68. package/build/types/integrations/tracing/redis/redis-dc-subscriber.d.ts.map +1 -0
  69. package/build/types/integrations/tracing/redis/vendored/ioredis-instrumentation.d.ts +15 -0
  70. package/build/types/integrations/tracing/redis/vendored/ioredis-instrumentation.d.ts.map +1 -0
  71. package/build/types/integrations/tracing/redis/vendored/redis-common.d.ts +6 -0
  72. package/build/types/integrations/tracing/redis/vendored/redis-common.d.ts.map +1 -0
  73. package/build/types/integrations/tracing/redis/vendored/redis-instrumentation.d.ts +16 -0
  74. package/build/types/integrations/tracing/redis/vendored/redis-instrumentation.d.ts.map +1 -0
  75. package/build/types/integrations/tracing/redis/vendored/semconv.d.ts +8 -0
  76. package/build/types/integrations/tracing/redis/vendored/semconv.d.ts.map +1 -0
  77. package/build/types/integrations/tracing/redis/vendored/types.d.ts +58 -0
  78. package/build/types/integrations/tracing/redis/vendored/types.d.ts.map +1 -0
  79. package/build/types/utils/redisCache.d.ts +1 -1
  80. package/build/types/utils/redisCache.d.ts.map +1 -1
  81. package/build/types-ts3.8/integrations/http.d.ts +8 -15
  82. package/build/types-ts3.8/integrations/tracing/{redis.d.ts → redis/index.d.ts} +3 -3
  83. package/build/types-ts3.8/integrations/tracing/redis/redis-dc-subscriber.d.ts +17 -0
  84. package/build/types-ts3.8/integrations/tracing/redis/vendored/ioredis-instrumentation.d.ts +15 -0
  85. package/build/types-ts3.8/integrations/tracing/redis/vendored/redis-common.d.ts +6 -0
  86. package/build/types-ts3.8/integrations/tracing/redis/vendored/redis-instrumentation.d.ts +16 -0
  87. package/build/types-ts3.8/integrations/tracing/redis/vendored/semconv.d.ts +8 -0
  88. package/build/types-ts3.8/integrations/tracing/redis/vendored/types.d.ts +58 -0
  89. package/build/types-ts3.8/utils/redisCache.d.ts +1 -1
  90. package/package.json +4 -6
  91. package/build/cjs/integrations/tracing/redis.js.map +0 -1
  92. package/build/esm/integrations/tracing/redis.js.map +0 -1
  93. package/build/types/integrations/tracing/redis.d.ts.map +0 -1
@@ -0,0 +1,685 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const api = require('@opentelemetry/api');
4
+ const core = require('@sentry/core');
5
+ const instrumentation = require('@opentelemetry/instrumentation');
6
+ const semanticConventions = require('@opentelemetry/semantic-conventions');
7
+ const redisCommon = require('./redis-common.js');
8
+ const semconv = require('./semconv.js');
9
+
10
+ /*
11
+ * Copyright The OpenTelemetry Authors
12
+ *
13
+ * Licensed under the Apache License, Version 2.0 (the "License");
14
+ * you may not use this file except in compliance with the License.
15
+ * You may obtain a copy of the License at
16
+ *
17
+ * https://www.apache.org/licenses/LICENSE-2.0
18
+ *
19
+ * Unless required by applicable law or agreed to in writing, software
20
+ * distributed under the License is distributed on an "AS IS" BASIS,
21
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ * See the License for the specific language governing permissions and
23
+ * limitations under the License.
24
+ *
25
+ * NOTICE from the Sentry authors:
26
+ * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/instrumentation-redis-v0.62.0/packages/instrumentation-redis
27
+ * - Upstream version: @opentelemetry/instrumentation-redis@0.62.0
28
+ * - Minor TypeScript adjustments for this repository's compiler settings
29
+ */
30
+ /* eslint-disable -- vendored @opentelemetry/instrumentation-redis */
31
+
32
+
33
+ const PACKAGE_NAME = '@opentelemetry/instrumentation-redis';
34
+ const PACKAGE_VERSION = '0.62.0';
35
+
36
+ // ---- Internal types ----
37
+
38
+ const OTEL_OPEN_SPANS = Symbol('opentelemetry.instrumentation.redis.open_spans');
39
+ const MULTI_COMMAND_OPTIONS = Symbol('opentelemetry.instrumentation.redis.multi_command_options');
40
+
41
+ // ---- v4-v5 utils ----
42
+
43
+ function removeCredentialsFromDBConnectionStringAttribute(
44
+ diagLogger,
45
+ url,
46
+ ) {
47
+ if (typeof url !== 'string' || !url) {
48
+ return undefined;
49
+ }
50
+ try {
51
+ const u = new URL(url);
52
+ u.searchParams.delete('user_pwd');
53
+ u.username = '';
54
+ u.password = '';
55
+ return u.href;
56
+ } catch (err) {
57
+ diagLogger.error('failed to sanitize redis connection url', err);
58
+ }
59
+ return undefined;
60
+ }
61
+
62
+ function getClientAttributes(
63
+ diagLogger,
64
+ options,
65
+ semconvStability,
66
+ ) {
67
+ const attributes = {};
68
+ if (semconvStability & instrumentation.SemconvStability.OLD) {
69
+ Object.assign(attributes, {
70
+ [semconv.ATTR_DB_SYSTEM]: semconv.DB_SYSTEM_VALUE_REDIS,
71
+ [semconv.ATTR_NET_PEER_NAME]: options?.socket?.host,
72
+ [semconv.ATTR_NET_PEER_PORT]: options?.socket?.port,
73
+ [semconv.ATTR_DB_CONNECTION_STRING]: removeCredentialsFromDBConnectionStringAttribute(diagLogger, options?.url),
74
+ });
75
+ }
76
+ if (semconvStability & instrumentation.SemconvStability.STABLE) {
77
+ Object.assign(attributes, {
78
+ [semanticConventions.ATTR_DB_SYSTEM_NAME]: semconv.DB_SYSTEM_NAME_VALUE_REDIS,
79
+ [semanticConventions.ATTR_SERVER_ADDRESS]: options?.socket?.host,
80
+ [semanticConventions.ATTR_SERVER_PORT]: options?.socket?.port,
81
+ });
82
+ }
83
+ return attributes;
84
+ }
85
+
86
+ // ---- v2-v3 utils ----
87
+
88
+ function endSpanV2(span, err) {
89
+ if (err) {
90
+ span.setStatus({
91
+ code: api.SpanStatusCode.ERROR,
92
+ message: err.message,
93
+ });
94
+ }
95
+ span.end();
96
+ }
97
+
98
+ function getTracedCreateClient(original) {
99
+ return function createClientTrace() {
100
+ const client = original.apply(this, arguments);
101
+ return api.context.bind(api.context.active(), client);
102
+ };
103
+ }
104
+
105
+ function getTracedCreateStreamTrace(original) {
106
+ return function create_stream_trace() {
107
+ if (!Object.prototype.hasOwnProperty.call(this, 'stream')) {
108
+ Object.defineProperty(this, 'stream', {
109
+ get() {
110
+ return this._patched_redis_stream;
111
+ },
112
+ set(val) {
113
+ api.context.bind(api.context.active(), val);
114
+ this._patched_redis_stream = val;
115
+ },
116
+ });
117
+ }
118
+ return original.apply(this, arguments);
119
+ };
120
+ }
121
+
122
+ // ---- RedisInstrumentationV2_V3 ----
123
+
124
+ class RedisInstrumentationV2_V3 extends instrumentation.InstrumentationBase {
125
+ static __initStatic() {this.COMPONENT = 'redis';}
126
+
127
+ constructor(config = {}) {
128
+ super(PACKAGE_NAME, PACKAGE_VERSION, config);
129
+ this._semconvStability = config.semconvStability
130
+ ? config.semconvStability
131
+ : instrumentation.semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
132
+ }
133
+
134
+ setConfig(config = {}) {
135
+ super.setConfig(config);
136
+ this._semconvStability = config.semconvStability
137
+ ? config.semconvStability
138
+ : instrumentation.semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
139
+ }
140
+
141
+ init() {
142
+ return [
143
+ new instrumentation.InstrumentationNodeModuleDefinition(
144
+ 'redis',
145
+ ['>=2.6.0 <4'],
146
+ (moduleExports) => {
147
+ if (instrumentation.isWrapped(moduleExports.RedisClient.prototype['internal_send_command'])) {
148
+ this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');
149
+ }
150
+ this._wrap(moduleExports.RedisClient.prototype, 'internal_send_command', this._getPatchInternalSendCommand());
151
+ if (instrumentation.isWrapped(moduleExports.RedisClient.prototype['create_stream'])) {
152
+ this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');
153
+ }
154
+ this._wrap(moduleExports.RedisClient.prototype, 'create_stream', this._getPatchCreateStream());
155
+ if (instrumentation.isWrapped(moduleExports.createClient)) {
156
+ this._unwrap(moduleExports, 'createClient');
157
+ }
158
+ this._wrap(moduleExports, 'createClient', this._getPatchCreateClient());
159
+ return moduleExports;
160
+ },
161
+ (moduleExports) => {
162
+ if (moduleExports === undefined) return;
163
+ this._unwrap(moduleExports.RedisClient.prototype, 'internal_send_command');
164
+ this._unwrap(moduleExports.RedisClient.prototype, 'create_stream');
165
+ this._unwrap(moduleExports, 'createClient');
166
+ },
167
+ ),
168
+ ];
169
+ }
170
+
171
+ _getPatchInternalSendCommand() {
172
+ const instrumentation$1 = this;
173
+ return function internal_send_command(original) {
174
+ return function internal_send_command_trace( cmd) {
175
+ if (arguments.length !== 1 || typeof cmd !== 'object') {
176
+ return original.apply(this, arguments);
177
+ }
178
+ const config = instrumentation$1.getConfig();
179
+ const hasNoParentSpan = api.trace.getSpan(api.context.active()) === undefined;
180
+ if (config.requireParentSpan === true && hasNoParentSpan) {
181
+ return original.apply(this, arguments);
182
+ }
183
+ const dbStatementSerializer = config?.dbStatementSerializer || redisCommon.defaultDbStatementSerializer;
184
+ const attributes = {};
185
+ if (instrumentation$1._semconvStability & instrumentation.SemconvStability.OLD) {
186
+ Object.assign(attributes, {
187
+ [semconv.ATTR_DB_SYSTEM]: semconv.DB_SYSTEM_VALUE_REDIS,
188
+ [semconv.ATTR_DB_STATEMENT]: dbStatementSerializer(cmd.command, cmd.args),
189
+ });
190
+ }
191
+ if (instrumentation$1._semconvStability & instrumentation.SemconvStability.STABLE) {
192
+ Object.assign(attributes, {
193
+ [semanticConventions.ATTR_DB_SYSTEM_NAME]: semconv.DB_SYSTEM_NAME_VALUE_REDIS,
194
+ [semanticConventions.ATTR_DB_OPERATION_NAME]: cmd.command,
195
+ [semanticConventions.ATTR_DB_QUERY_TEXT]: dbStatementSerializer(cmd.command, cmd.args),
196
+ });
197
+ }
198
+ attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
199
+ const span = instrumentation$1.tracer.startSpan(`${RedisInstrumentationV2_V3.COMPONENT}-${cmd.command}`, {
200
+ kind: api.SpanKind.CLIENT,
201
+ attributes,
202
+ });
203
+ if (this.connection_options) {
204
+ const connectionAttributes = {};
205
+ if (instrumentation$1._semconvStability & instrumentation.SemconvStability.OLD) {
206
+ Object.assign(connectionAttributes, {
207
+ [semconv.ATTR_NET_PEER_NAME]: this.connection_options.host,
208
+ [semconv.ATTR_NET_PEER_PORT]: this.connection_options.port,
209
+ });
210
+ }
211
+ if (instrumentation$1._semconvStability & instrumentation.SemconvStability.STABLE) {
212
+ Object.assign(connectionAttributes, {
213
+ [semanticConventions.ATTR_SERVER_ADDRESS]: this.connection_options.host,
214
+ [semanticConventions.ATTR_SERVER_PORT]: this.connection_options.port,
215
+ });
216
+ }
217
+ span.setAttributes(connectionAttributes);
218
+ }
219
+ if (this.address && instrumentation$1._semconvStability & instrumentation.SemconvStability.OLD) {
220
+ span.setAttribute(semconv.ATTR_DB_CONNECTION_STRING, `redis://${this.address}`);
221
+ }
222
+ const originalCallback = arguments[0].callback;
223
+ if (originalCallback) {
224
+ const originalContext = api.context.active();
225
+ arguments[0].callback = function callback( err, reply) {
226
+ if (config?.responseHook) {
227
+ const responseHook = config.responseHook;
228
+ instrumentation.safeExecuteInTheMiddle(
229
+ () => {
230
+ responseHook(span, cmd.command, cmd.args, reply);
231
+ },
232
+ (e) => {
233
+ if (e) {
234
+ instrumentation$1._diag.error('Error executing responseHook', e);
235
+ }
236
+ },
237
+ true,
238
+ );
239
+ }
240
+ endSpanV2(span, err);
241
+ return api.context.with(originalContext, originalCallback, this, ...arguments);
242
+ };
243
+ }
244
+ try {
245
+ return original.apply(this, arguments);
246
+ } catch (rethrow) {
247
+ endSpanV2(span, rethrow );
248
+ throw rethrow;
249
+ }
250
+ };
251
+ };
252
+ }
253
+
254
+ _getPatchCreateClient() {
255
+ return function createClient(original) {
256
+ return getTracedCreateClient(original);
257
+ };
258
+ }
259
+
260
+ _getPatchCreateStream() {
261
+ return function createReadStream(original) {
262
+ return getTracedCreateStreamTrace(original);
263
+ };
264
+ }
265
+ } RedisInstrumentationV2_V3.__initStatic();
266
+
267
+ // ---- RedisInstrumentationV4_V5 ----
268
+
269
+ class RedisInstrumentationV4_V5 extends instrumentation.InstrumentationBase {
270
+ static __initStatic2() {this.COMPONENT = 'redis';}
271
+
272
+ constructor(config = {}) {
273
+ super(PACKAGE_NAME, PACKAGE_VERSION, config);
274
+ this._semconvStability = config.semconvStability
275
+ ? config.semconvStability
276
+ : instrumentation.semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
277
+ }
278
+
279
+ setConfig(config = {}) {
280
+ super.setConfig(config);
281
+ this._semconvStability = config.semconvStability
282
+ ? config.semconvStability
283
+ : instrumentation.semconvStabilityFromStr('database', process.env['OTEL_SEMCONV_STABILITY_OPT_IN']);
284
+ }
285
+
286
+ init() {
287
+ return [
288
+ this._getInstrumentationNodeModuleDefinition('@redis/client'),
289
+ this._getInstrumentationNodeModuleDefinition('@node-redis/client'),
290
+ ];
291
+ }
292
+
293
+ _getInstrumentationNodeModuleDefinition(basePackageName) {
294
+ const commanderModuleFile = new instrumentation.InstrumentationNodeModuleFile(
295
+ `${basePackageName}/dist/lib/commander.js`,
296
+ ['^1.0.0'],
297
+ (moduleExports, moduleVersion) => {
298
+ const transformCommandArguments = moduleExports.transformCommandArguments;
299
+ if (!transformCommandArguments) {
300
+ this._diag.error('internal instrumentation error, missing transformCommandArguments function');
301
+ return moduleExports;
302
+ }
303
+ const functionToPatch = moduleVersion?.startsWith('1.0.') ? 'extendWithCommands' : 'attachCommands';
304
+ if (instrumentation.isWrapped(moduleExports?.[functionToPatch])) {
305
+ this._unwrap(moduleExports, functionToPatch);
306
+ }
307
+ this._wrap(moduleExports, functionToPatch, this._getPatchExtendWithCommands(transformCommandArguments));
308
+ return moduleExports;
309
+ },
310
+ (moduleExports) => {
311
+ if (instrumentation.isWrapped(moduleExports?.extendWithCommands)) {
312
+ this._unwrap(moduleExports, 'extendWithCommands');
313
+ }
314
+ if (instrumentation.isWrapped(moduleExports?.attachCommands)) {
315
+ this._unwrap(moduleExports, 'attachCommands');
316
+ }
317
+ },
318
+ );
319
+
320
+ const multiCommanderModule = new instrumentation.InstrumentationNodeModuleFile(
321
+ `${basePackageName}/dist/lib/client/multi-command.js`,
322
+ ['^1.0.0', '>=5.0.0 <5.12.0'],
323
+ (moduleExports) => {
324
+ const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;
325
+ if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.exec)) {
326
+ this._unwrap(redisClientMultiCommandPrototype, 'exec');
327
+ }
328
+ this._wrap(redisClientMultiCommandPrototype, 'exec', this._getPatchMultiCommandsExec(false));
329
+ if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {
330
+ this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');
331
+ }
332
+ this._wrap(redisClientMultiCommandPrototype, 'execAsPipeline', this._getPatchMultiCommandsExec(true));
333
+ if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.addCommand)) {
334
+ this._unwrap(redisClientMultiCommandPrototype, 'addCommand');
335
+ }
336
+ this._wrap(redisClientMultiCommandPrototype, 'addCommand', this._getPatchMultiCommandsAddCommand());
337
+ return moduleExports;
338
+ },
339
+ (moduleExports) => {
340
+ const redisClientMultiCommandPrototype = moduleExports?.default?.prototype;
341
+ if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.exec)) {
342
+ this._unwrap(redisClientMultiCommandPrototype, 'exec');
343
+ }
344
+ if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.execAsPipeline)) {
345
+ this._unwrap(redisClientMultiCommandPrototype, 'execAsPipeline');
346
+ }
347
+ if (instrumentation.isWrapped(redisClientMultiCommandPrototype?.addCommand)) {
348
+ this._unwrap(redisClientMultiCommandPrototype, 'addCommand');
349
+ }
350
+ },
351
+ );
352
+
353
+ const clientIndexModule = new instrumentation.InstrumentationNodeModuleFile(
354
+ `${basePackageName}/dist/lib/client/index.js`,
355
+ ['^1.0.0', '>=5.0.0 <5.12.0'],
356
+ (moduleExports) => {
357
+ const redisClientPrototype = moduleExports?.default?.prototype;
358
+ if (redisClientPrototype?.multi) {
359
+ if (instrumentation.isWrapped(redisClientPrototype?.multi)) {
360
+ this._unwrap(redisClientPrototype, 'multi');
361
+ }
362
+ this._wrap(redisClientPrototype, 'multi', this._getPatchRedisClientMulti());
363
+ }
364
+ if (redisClientPrototype?.MULTI) {
365
+ if (instrumentation.isWrapped(redisClientPrototype?.MULTI)) {
366
+ this._unwrap(redisClientPrototype, 'MULTI');
367
+ }
368
+ this._wrap(redisClientPrototype, 'MULTI', this._getPatchRedisClientMulti());
369
+ }
370
+ if (instrumentation.isWrapped(redisClientPrototype?.sendCommand)) {
371
+ this._unwrap(redisClientPrototype, 'sendCommand');
372
+ }
373
+ this._wrap(redisClientPrototype, 'sendCommand', this._getPatchRedisClientSendCommand());
374
+ if (instrumentation.isWrapped(redisClientPrototype?.connect)) {
375
+ this._unwrap(redisClientPrototype, 'connect');
376
+ }
377
+ this._wrap(redisClientPrototype, 'connect', this._getPatchedClientConnect());
378
+ return moduleExports;
379
+ },
380
+ (moduleExports) => {
381
+ const redisClientPrototype = moduleExports?.default?.prototype;
382
+ if (instrumentation.isWrapped(redisClientPrototype?.multi)) {
383
+ this._unwrap(redisClientPrototype, 'multi');
384
+ }
385
+ if (instrumentation.isWrapped(redisClientPrototype?.MULTI)) {
386
+ this._unwrap(redisClientPrototype, 'MULTI');
387
+ }
388
+ if (instrumentation.isWrapped(redisClientPrototype?.sendCommand)) {
389
+ this._unwrap(redisClientPrototype, 'sendCommand');
390
+ }
391
+ if (instrumentation.isWrapped(redisClientPrototype?.connect)) {
392
+ this._unwrap(redisClientPrototype, 'connect');
393
+ }
394
+ },
395
+ );
396
+
397
+ return new instrumentation.InstrumentationNodeModuleDefinition(
398
+ basePackageName,
399
+ ['^1.0.0', '>=5.0.0 <5.12.0'],
400
+ (moduleExports) => moduleExports,
401
+ () => {},
402
+ [commanderModuleFile, multiCommanderModule, clientIndexModule],
403
+ );
404
+ }
405
+
406
+ _getPatchExtendWithCommands(transformCommandArguments) {
407
+ const plugin = this;
408
+ return function extendWithCommandsPatchWrapper(original) {
409
+ return function extendWithCommandsPatch( config) {
410
+ if (config?.BaseClass?.name !== 'RedisClient') {
411
+ return original.apply(this, arguments);
412
+ }
413
+ const origExecutor = config.executor;
414
+ config.executor = function ( command, args) {
415
+ const redisCommandArguments = transformCommandArguments(command, args).args;
416
+ return plugin._traceClientCommand(origExecutor, this, arguments, redisCommandArguments);
417
+ };
418
+ return original.apply(this, arguments);
419
+ };
420
+ };
421
+ }
422
+
423
+ _getPatchMultiCommandsExec(isPipeline) {
424
+ const plugin = this;
425
+ return function execPatchWrapper(original) {
426
+ return function execPatch() {
427
+ const execRes = original.apply(this, arguments);
428
+ if (typeof execRes?.then !== 'function') {
429
+ plugin._diag.error('non-promise result when patching exec/execAsPipeline');
430
+ return execRes;
431
+ }
432
+ return execRes
433
+ .then((redisRes) => {
434
+ const openSpans = this[OTEL_OPEN_SPANS];
435
+ plugin._endSpansWithRedisReplies(openSpans, redisRes, isPipeline);
436
+ return redisRes;
437
+ })
438
+ .catch((err) => {
439
+ const openSpans = this[OTEL_OPEN_SPANS];
440
+ if (!openSpans) {
441
+ plugin._diag.error('cannot find open spans to end for multi/pipeline');
442
+ } else {
443
+ const replies =
444
+ err.constructor.name === 'MultiErrorReply'
445
+ ? (err ).replies
446
+ : new Array(openSpans.length).fill(err);
447
+ plugin._endSpansWithRedisReplies(openSpans, replies, isPipeline);
448
+ }
449
+ return Promise.reject(err);
450
+ });
451
+ };
452
+ };
453
+ }
454
+
455
+ _getPatchMultiCommandsAddCommand() {
456
+ const plugin = this;
457
+ return function addCommandWrapper(original) {
458
+ return function addCommandPatch( args) {
459
+ return plugin._traceClientCommand(original, this, arguments, args);
460
+ };
461
+ };
462
+ }
463
+
464
+ _getPatchRedisClientMulti() {
465
+ return function multiPatchWrapper(original) {
466
+ return function multiPatch() {
467
+ const multiRes = original.apply(this, arguments);
468
+ multiRes[MULTI_COMMAND_OPTIONS] = this.options;
469
+ return multiRes;
470
+ };
471
+ };
472
+ }
473
+
474
+ _getPatchRedisClientSendCommand() {
475
+ const plugin = this;
476
+ return function sendCommandWrapper(original) {
477
+ return function sendCommandPatch( args) {
478
+ return plugin._traceClientCommand(original, this, arguments, args);
479
+ };
480
+ };
481
+ }
482
+
483
+ _getPatchedClientConnect() {
484
+ const plugin = this;
485
+ return function connectWrapper(original) {
486
+ return function patchedConnect() {
487
+ const options = this.options;
488
+ const attributes = getClientAttributes(plugin._diag, options, plugin._semconvStability);
489
+ attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
490
+ const span = plugin.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-connect`, {
491
+ kind: api.SpanKind.CLIENT,
492
+ attributes,
493
+ });
494
+ const res = api.context.with(api.trace.setSpan(api.context.active(), span), () => {
495
+ return original.apply(this);
496
+ });
497
+ return res
498
+ .then((result) => {
499
+ span.end();
500
+ return result;
501
+ })
502
+ .catch((error) => {
503
+ span.recordException(error);
504
+ span.setStatus({
505
+ code: api.SpanStatusCode.ERROR,
506
+ message: error.message,
507
+ });
508
+ span.end();
509
+ return Promise.reject(error);
510
+ });
511
+ };
512
+ };
513
+ }
514
+
515
+ _traceClientCommand(
516
+ origFunction,
517
+ origThis,
518
+ origArguments,
519
+ redisCommandArguments,
520
+ ) {
521
+ const hasNoParentSpan = api.trace.getSpan(api.context.active()) === undefined;
522
+ if (hasNoParentSpan && this.getConfig().requireParentSpan) {
523
+ return origFunction.apply(origThis, origArguments);
524
+ }
525
+ const clientOptions = origThis.options || origThis[MULTI_COMMAND_OPTIONS];
526
+ const commandName = redisCommandArguments[0] ;
527
+ const commandArgs = redisCommandArguments.slice(1);
528
+ const dbStatementSerializer = this.getConfig().dbStatementSerializer || redisCommon.defaultDbStatementSerializer;
529
+ const attributes = getClientAttributes(this._diag, clientOptions, this._semconvStability);
530
+ if (this._semconvStability & instrumentation.SemconvStability.STABLE) {
531
+ attributes[semanticConventions.ATTR_DB_OPERATION_NAME] = commandName;
532
+ }
533
+ try {
534
+ const dbStatement = dbStatementSerializer(commandName, commandArgs);
535
+ if (dbStatement != null) {
536
+ if (this._semconvStability & instrumentation.SemconvStability.OLD) {
537
+ attributes[semconv.ATTR_DB_STATEMENT] = dbStatement;
538
+ }
539
+ if (this._semconvStability & instrumentation.SemconvStability.STABLE) {
540
+ attributes[semanticConventions.ATTR_DB_QUERY_TEXT] = dbStatement;
541
+ }
542
+ }
543
+ } catch (e) {
544
+ this._diag.error('dbStatementSerializer throw an exception', e, { commandName });
545
+ }
546
+ attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = 'auto.db.otel.redis';
547
+ const span = this.tracer.startSpan(`${RedisInstrumentationV4_V5.COMPONENT}-${commandName}`, {
548
+ kind: api.SpanKind.CLIENT,
549
+ attributes,
550
+ });
551
+ const res = api.context.with(api.trace.setSpan(api.context.active(), span), () => {
552
+ return origFunction.apply(origThis, origArguments);
553
+ });
554
+ if (typeof res?.then === 'function') {
555
+ res.then(
556
+ (redisRes) => {
557
+ this._endSpanWithResponse(span, commandName, commandArgs, redisRes, undefined);
558
+ },
559
+ (err) => {
560
+ this._endSpanWithResponse(span, commandName, commandArgs, null, err);
561
+ },
562
+ );
563
+ } else {
564
+ const redisClientMultiCommand = res;
565
+ redisClientMultiCommand[OTEL_OPEN_SPANS] = redisClientMultiCommand[OTEL_OPEN_SPANS] || [];
566
+ redisClientMultiCommand[OTEL_OPEN_SPANS].push({
567
+ span,
568
+ commandName,
569
+ commandArgs,
570
+ });
571
+ }
572
+ return res;
573
+ }
574
+
575
+ _endSpansWithRedisReplies(openSpans, replies, isPipeline = false) {
576
+ if (!openSpans) {
577
+ return this._diag.error('cannot find open spans to end for redis multi/pipeline');
578
+ }
579
+ if (replies.length !== openSpans.length) {
580
+ return this._diag.error('number of multi command spans does not match response from redis');
581
+ }
582
+ const allCommands = openSpans.map(s => s.commandName);
583
+ const allSameCommand = allCommands.every(cmd => cmd === allCommands[0]);
584
+ const operationName = allSameCommand
585
+ ? (isPipeline ? 'PIPELINE ' : 'MULTI ') + allCommands[0]
586
+ : isPipeline
587
+ ? 'PIPELINE'
588
+ : 'MULTI';
589
+ for (let i = 0; i < openSpans.length; i++) {
590
+ const { span, commandArgs } = openSpans[i];
591
+ const currCommandRes = replies[i];
592
+ const [res, err] = currCommandRes instanceof Error ? [null, currCommandRes] : [currCommandRes, undefined];
593
+ if (this._semconvStability & instrumentation.SemconvStability.STABLE) {
594
+ span.setAttribute(semanticConventions.ATTR_DB_OPERATION_NAME, operationName);
595
+ }
596
+ this._endSpanWithResponse(span, allCommands[i], commandArgs, res, err);
597
+ }
598
+ }
599
+
600
+ _endSpanWithResponse(
601
+ span,
602
+ commandName,
603
+ commandArgs,
604
+ response,
605
+ error,
606
+ ) {
607
+ const { responseHook } = this.getConfig();
608
+ if (!error && responseHook) {
609
+ try {
610
+ responseHook(span, commandName, commandArgs, response);
611
+ } catch (err) {
612
+ this._diag.error('responseHook throw an exception', err);
613
+ }
614
+ }
615
+ if (error) {
616
+ span.recordException(error);
617
+ span.setStatus({ code: api.SpanStatusCode.ERROR, message: error?.message });
618
+ }
619
+ span.end();
620
+ }
621
+ } RedisInstrumentationV4_V5.__initStatic2();
622
+
623
+ // ---- RedisInstrumentation (wrapper) ----
624
+
625
+ const DEFAULT_CONFIG = {
626
+ requireParentSpan: false,
627
+ };
628
+
629
+ class RedisInstrumentation extends instrumentation.InstrumentationBase {
630
+
631
+ __init() {this.initialized = false;}
632
+
633
+ constructor(config = {}) {
634
+ const resolvedConfig = { ...DEFAULT_CONFIG, ...config };
635
+ super(PACKAGE_NAME, PACKAGE_VERSION, resolvedConfig);RedisInstrumentation.prototype.__init.call(this); this.instrumentationV2_V3 = new RedisInstrumentationV2_V3(this.getConfig());
636
+ this.instrumentationV4_V5 = new RedisInstrumentationV4_V5(this.getConfig());
637
+ this.initialized = true;
638
+ }
639
+
640
+ setConfig(config = {}) {
641
+ const newConfig = { ...DEFAULT_CONFIG, ...config };
642
+ super.setConfig(newConfig);
643
+ if (!this.initialized) {
644
+ return;
645
+ }
646
+ this.instrumentationV2_V3.setConfig(newConfig);
647
+ this.instrumentationV4_V5.setConfig(newConfig);
648
+ }
649
+
650
+ init() {}
651
+
652
+ getModuleDefinitions() {
653
+ return [...this.instrumentationV2_V3.getModuleDefinitions(), ...this.instrumentationV4_V5.getModuleDefinitions()];
654
+ }
655
+
656
+ setTracerProvider(tracerProvider) {
657
+ super.setTracerProvider(tracerProvider);
658
+ if (!this.initialized) {
659
+ return;
660
+ }
661
+ this.instrumentationV2_V3.setTracerProvider(tracerProvider);
662
+ this.instrumentationV4_V5.setTracerProvider(tracerProvider);
663
+ }
664
+
665
+ enable() {
666
+ super.enable();
667
+ if (!this.initialized) {
668
+ return;
669
+ }
670
+ this.instrumentationV2_V3.enable();
671
+ this.instrumentationV4_V5.enable();
672
+ }
673
+
674
+ disable() {
675
+ super.disable();
676
+ if (!this.initialized) {
677
+ return;
678
+ }
679
+ this.instrumentationV2_V3.disable();
680
+ this.instrumentationV4_V5.disable();
681
+ }
682
+ }
683
+
684
+ exports.RedisInstrumentation = RedisInstrumentation;
685
+ //# sourceMappingURL=redis-instrumentation.js.map