@sentry/node 10.61.0 → 10.62.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 (99) hide show
  1. package/build/cjs/integrations/tracing/amqplib/index.js +2 -10
  2. package/build/cjs/integrations/tracing/amqplib/index.js.map +1 -1
  3. package/build/cjs/integrations/tracing/amqplib/vendored/instrumentation.js +117 -0
  4. package/build/cjs/integrations/tracing/amqplib/vendored/instrumentation.js.map +1 -0
  5. package/build/cjs/integrations/tracing/amqplib/vendored/patches.js +185 -0
  6. package/build/cjs/integrations/tracing/amqplib/vendored/patches.js.map +1 -0
  7. package/build/cjs/integrations/tracing/amqplib/vendored/semconv.js +21 -1
  8. package/build/cjs/integrations/tracing/amqplib/vendored/semconv.js.map +1 -1
  9. package/build/cjs/integrations/tracing/amqplib/vendored/types.js +0 -6
  10. package/build/cjs/integrations/tracing/amqplib/vendored/types.js.map +1 -1
  11. package/build/cjs/integrations/tracing/amqplib/vendored/utils.js +71 -80
  12. package/build/cjs/integrations/tracing/amqplib/vendored/utils.js.map +1 -1
  13. package/build/cjs/integrations/tracing/firebase/firebase.js +1 -24
  14. package/build/cjs/integrations/tracing/firebase/firebase.js.map +1 -1
  15. package/build/cjs/integrations/tracing/firebase/otel/firebaseInstrumentation.js +3 -11
  16. package/build/cjs/integrations/tracing/firebase/otel/firebaseInstrumentation.js.map +1 -1
  17. package/build/cjs/integrations/tracing/firebase/otel/patches/firestore.js +33 -72
  18. package/build/cjs/integrations/tracing/firebase/otel/patches/firestore.js.map +1 -1
  19. package/build/cjs/integrations/tracing/firebase/otel/patches/functions.js +46 -105
  20. package/build/cjs/integrations/tracing/firebase/otel/patches/functions.js.map +1 -1
  21. package/build/cjs/integrations/tracing/redis/index.js +5 -3
  22. package/build/cjs/integrations/tracing/redis/index.js.map +1 -1
  23. package/build/cjs/integrations/tracing/vercelai/index.js +3 -0
  24. package/build/cjs/integrations/tracing/vercelai/index.js.map +1 -1
  25. package/build/esm/integrations/tracing/amqplib/index.js +3 -11
  26. package/build/esm/integrations/tracing/amqplib/index.js.map +1 -1
  27. package/build/esm/integrations/tracing/amqplib/vendored/instrumentation.js +115 -0
  28. package/build/esm/integrations/tracing/amqplib/vendored/instrumentation.js.map +1 -0
  29. package/build/esm/integrations/tracing/amqplib/vendored/patches.js +177 -0
  30. package/build/esm/integrations/tracing/amqplib/vendored/patches.js.map +1 -0
  31. package/build/esm/integrations/tracing/amqplib/vendored/semconv.js +12 -2
  32. package/build/esm/integrations/tracing/amqplib/vendored/semconv.js.map +1 -1
  33. package/build/esm/integrations/tracing/amqplib/vendored/types.js +1 -6
  34. package/build/esm/integrations/tracing/amqplib/vendored/types.js.map +1 -1
  35. package/build/esm/integrations/tracing/amqplib/vendored/utils.js +68 -78
  36. package/build/esm/integrations/tracing/amqplib/vendored/utils.js.map +1 -1
  37. package/build/esm/integrations/tracing/firebase/firebase.js +3 -26
  38. package/build/esm/integrations/tracing/firebase/firebase.js.map +1 -1
  39. package/build/esm/integrations/tracing/firebase/otel/firebaseInstrumentation.js +3 -11
  40. package/build/esm/integrations/tracing/firebase/otel/firebaseInstrumentation.js.map +1 -1
  41. package/build/esm/integrations/tracing/firebase/otel/patches/firestore.js +34 -73
  42. package/build/esm/integrations/tracing/firebase/otel/patches/firestore.js.map +1 -1
  43. package/build/esm/integrations/tracing/firebase/otel/patches/functions.js +47 -106
  44. package/build/esm/integrations/tracing/firebase/otel/patches/functions.js.map +1 -1
  45. package/build/esm/integrations/tracing/redis/index.js +6 -4
  46. package/build/esm/integrations/tracing/redis/index.js.map +1 -1
  47. package/build/esm/integrations/tracing/vercelai/index.js +3 -0
  48. package/build/esm/integrations/tracing/vercelai/index.js.map +1 -1
  49. package/build/esm/package.json +1 -1
  50. package/build/types/integrations/tracing/amqplib/index.d.ts +1 -1
  51. package/build/types/integrations/tracing/amqplib/index.d.ts.map +1 -1
  52. package/build/types/integrations/tracing/amqplib/vendored/instrumentation.d.ts +11 -0
  53. package/build/types/integrations/tracing/amqplib/vendored/instrumentation.d.ts.map +1 -0
  54. package/build/types/integrations/tracing/amqplib/vendored/patches.d.ts +11 -0
  55. package/build/types/integrations/tracing/amqplib/vendored/patches.d.ts.map +1 -0
  56. package/build/types/integrations/tracing/amqplib/vendored/semconv.d.ts +25 -37
  57. package/build/types/integrations/tracing/amqplib/vendored/semconv.d.ts.map +1 -1
  58. package/build/types/integrations/tracing/amqplib/vendored/types.d.ts +0 -81
  59. package/build/types/integrations/tracing/amqplib/vendored/types.d.ts.map +1 -1
  60. package/build/types/integrations/tracing/amqplib/vendored/utils.d.ts +16 -9
  61. package/build/types/integrations/tracing/amqplib/vendored/utils.d.ts.map +1 -1
  62. package/build/types/integrations/tracing/firebase/firebase.d.ts.map +1 -1
  63. package/build/types/integrations/tracing/firebase/otel/firebaseInstrumentation.d.ts +4 -9
  64. package/build/types/integrations/tracing/firebase/otel/firebaseInstrumentation.d.ts.map +1 -1
  65. package/build/types/integrations/tracing/firebase/otel/patches/firestore.d.ts +2 -5
  66. package/build/types/integrations/tracing/firebase/otel/patches/firestore.d.ts.map +1 -1
  67. package/build/types/integrations/tracing/firebase/otel/patches/functions.d.ts +3 -8
  68. package/build/types/integrations/tracing/firebase/otel/patches/functions.d.ts.map +1 -1
  69. package/build/types/integrations/tracing/firebase/otel/types.d.ts +0 -20
  70. package/build/types/integrations/tracing/firebase/otel/types.d.ts.map +1 -1
  71. package/build/types/integrations/tracing/redis/index.d.ts.map +1 -1
  72. package/build/types/integrations/tracing/vercelai/index.d.ts +0 -1
  73. package/build/types/integrations/tracing/vercelai/index.d.ts.map +1 -1
  74. package/build/types-ts3.8/integrations/tracing/amqplib/index.d.ts +1 -1
  75. package/build/types-ts3.8/integrations/tracing/amqplib/vendored/instrumentation.d.ts +11 -0
  76. package/build/types-ts3.8/integrations/tracing/amqplib/vendored/patches.d.ts +11 -0
  77. package/build/types-ts3.8/integrations/tracing/amqplib/vendored/semconv.d.ts +25 -37
  78. package/build/types-ts3.8/integrations/tracing/amqplib/vendored/types.d.ts +0 -81
  79. package/build/types-ts3.8/integrations/tracing/amqplib/vendored/utils.d.ts +16 -9
  80. package/build/types-ts3.8/integrations/tracing/firebase/otel/firebaseInstrumentation.d.ts +4 -9
  81. package/build/types-ts3.8/integrations/tracing/firebase/otel/patches/firestore.d.ts +2 -5
  82. package/build/types-ts3.8/integrations/tracing/firebase/otel/patches/functions.d.ts +3 -8
  83. package/build/types-ts3.8/integrations/tracing/firebase/otel/types.d.ts +0 -20
  84. package/build/types-ts3.8/integrations/tracing/vercelai/index.d.ts +0 -1
  85. package/package.json +5 -5
  86. package/build/cjs/integrations/tracing/amqplib/vendored/amqplib.js +0 -452
  87. package/build/cjs/integrations/tracing/amqplib/vendored/amqplib.js.map +0 -1
  88. package/build/cjs/integrations/tracing/amqplib/vendored/semconv-obsolete.js +0 -24
  89. package/build/cjs/integrations/tracing/amqplib/vendored/semconv-obsolete.js.map +0 -1
  90. package/build/esm/integrations/tracing/amqplib/vendored/amqplib.js +0 -450
  91. package/build/esm/integrations/tracing/amqplib/vendored/amqplib.js.map +0 -1
  92. package/build/esm/integrations/tracing/amqplib/vendored/semconv-obsolete.js +0 -13
  93. package/build/esm/integrations/tracing/amqplib/vendored/semconv-obsolete.js.map +0 -1
  94. package/build/types/integrations/tracing/amqplib/vendored/amqplib.d.ts +0 -26
  95. package/build/types/integrations/tracing/amqplib/vendored/amqplib.d.ts.map +0 -1
  96. package/build/types/integrations/tracing/amqplib/vendored/semconv-obsolete.d.ts +0 -63
  97. package/build/types/integrations/tracing/amqplib/vendored/semconv-obsolete.d.ts.map +0 -1
  98. package/build/types-ts3.8/integrations/tracing/amqplib/vendored/amqplib.d.ts +0 -26
  99. package/build/types-ts3.8/integrations/tracing/amqplib/vendored/semconv-obsolete.d.ts +0 -63
@@ -0,0 +1,177 @@
1
+ import { timestampInSeconds, continueTrace, withActiveSpan, SPAN_STATUS_ERROR } from '@sentry/core';
2
+ import { EndOperation } from './types.js';
3
+ import { getConnectionAttributesFromUrl, getConnectionAttributesFromServer, CONNECTION_ATTRIBUTES, CHANNEL_IS_CONFIRM_PUBLISHING, startPublishSpan, CHANNEL_SPANS_NOT_ENDED, CHANNEL_CONSUME_TIMEOUT_TIMER, getHeaderAsString, startConsumeSpan, MESSAGE_STORED_SPAN } from './utils.js';
4
+
5
+ const CONSUME_TIMEOUT_MS = 1e3 * 60;
6
+ function endConsumerSpan(message, isRejected, operation, requeue) {
7
+ const storedSpan = message[MESSAGE_STORED_SPAN];
8
+ if (!storedSpan) {
9
+ return;
10
+ }
11
+ if (isRejected !== false) {
12
+ storedSpan.setStatus({
13
+ code: SPAN_STATUS_ERROR,
14
+ message: operation !== EndOperation.ChannelClosed && operation !== EndOperation.ChannelError ? `${operation} called on message${requeue === true ? " with requeue" : requeue === false ? " without requeue" : ""}` : operation
15
+ });
16
+ }
17
+ storedSpan.end();
18
+ message[MESSAGE_STORED_SPAN] = void 0;
19
+ }
20
+ function endAllSpansOnChannel(channel, isRejected, operation, requeue) {
21
+ const spansNotEnded = channel[CHANNEL_SPANS_NOT_ENDED] ?? [];
22
+ spansNotEnded.forEach((msgDetails) => {
23
+ endConsumerSpan(msgDetails.msg, isRejected, operation, requeue);
24
+ });
25
+ channel[CHANNEL_SPANS_NOT_ENDED] = [];
26
+ }
27
+ function checkConsumeTimeoutOnChannel(channel) {
28
+ const currentTime = timestampInSeconds();
29
+ const spansNotEnded = channel[CHANNEL_SPANS_NOT_ENDED] ?? [];
30
+ let i;
31
+ for (i = 0; i < spansNotEnded.length; i++) {
32
+ const currMessage = spansNotEnded[i];
33
+ const timeFromConsumeMs = (currentTime - currMessage.timeOfConsume) * 1e3;
34
+ if (timeFromConsumeMs < CONSUME_TIMEOUT_MS) {
35
+ break;
36
+ }
37
+ endConsumerSpan(currMessage.msg, null, EndOperation.InstrumentationTimeout, true);
38
+ }
39
+ spansNotEnded.splice(0, i);
40
+ }
41
+ function getConnectPatch(original) {
42
+ return function patchedConnect(url, socketOptions, openCallback) {
43
+ return original.call(this, url, socketOptions, function(err, conn) {
44
+ if (err == null) {
45
+ const urlAttributes = getConnectionAttributesFromUrl(url);
46
+ const serverAttributes = getConnectionAttributesFromServer(conn);
47
+ conn[CONNECTION_ATTRIBUTES] = {
48
+ ...urlAttributes,
49
+ ...serverAttributes
50
+ };
51
+ }
52
+ openCallback.apply(this, arguments);
53
+ });
54
+ };
55
+ }
56
+ function getChannelEmitPatch(original) {
57
+ return function emit(eventName) {
58
+ if (eventName === "close") {
59
+ endAllSpansOnChannel(this, true, EndOperation.ChannelClosed, void 0);
60
+ const activeTimer = this[CHANNEL_CONSUME_TIMEOUT_TIMER];
61
+ if (activeTimer) {
62
+ clearInterval(activeTimer);
63
+ }
64
+ this[CHANNEL_CONSUME_TIMEOUT_TIMER] = void 0;
65
+ } else if (eventName === "error") {
66
+ endAllSpansOnChannel(this, true, EndOperation.ChannelError, void 0);
67
+ }
68
+ return original.apply(this, arguments);
69
+ };
70
+ }
71
+ function getAckAllPatch(isRejected, endOperation) {
72
+ return (original) => function ackAll(requeueOrEmpty) {
73
+ endAllSpansOnChannel(this, isRejected, endOperation, requeueOrEmpty);
74
+ return original.apply(this, arguments);
75
+ };
76
+ }
77
+ function getAckPatch(isRejected, endOperation) {
78
+ return (original) => function ack(message, allUpToOrRequeue, requeue) {
79
+ const channel = this;
80
+ const requeueResolved = endOperation === EndOperation.Reject ? allUpToOrRequeue : requeue;
81
+ const spansNotEnded = channel[CHANNEL_SPANS_NOT_ENDED] ?? [];
82
+ const msgIndex = spansNotEnded.findIndex((msgDetails) => msgDetails.msg === message);
83
+ if (msgIndex < 0) {
84
+ endConsumerSpan(message, isRejected, endOperation, requeueResolved);
85
+ } else if (endOperation !== EndOperation.Reject && allUpToOrRequeue) {
86
+ for (let i = 0; i <= msgIndex; i++) {
87
+ endConsumerSpan(spansNotEnded[i].msg, isRejected, endOperation, requeueResolved);
88
+ }
89
+ spansNotEnded.splice(0, msgIndex + 1);
90
+ } else {
91
+ endConsumerSpan(message, isRejected, endOperation, requeueResolved);
92
+ spansNotEnded.splice(msgIndex, 1);
93
+ }
94
+ return original.apply(this, arguments);
95
+ };
96
+ }
97
+ function getConsumePatch(original) {
98
+ return function consume(queue, onMessage, options) {
99
+ const channel = this;
100
+ if (!Object.prototype.hasOwnProperty.call(channel, CHANNEL_SPANS_NOT_ENDED)) {
101
+ const timer = setInterval(() => {
102
+ checkConsumeTimeoutOnChannel(channel);
103
+ }, CONSUME_TIMEOUT_MS);
104
+ timer.unref();
105
+ channel[CHANNEL_CONSUME_TIMEOUT_TIMER] = timer;
106
+ channel[CHANNEL_SPANS_NOT_ENDED] = [];
107
+ }
108
+ const patchedOnMessage = function(msg) {
109
+ if (!msg) {
110
+ return onMessage.call(this, msg);
111
+ }
112
+ const headers = msg.properties.headers ?? {};
113
+ const sentryTrace = getHeaderAsString(headers, "sentry-trace");
114
+ const baggage = getHeaderAsString(headers, "baggage");
115
+ continueTrace({ sentryTrace, baggage }, () => {
116
+ const span = startConsumeSpan(queue, msg, channel);
117
+ if (!options?.noAck) {
118
+ channel[CHANNEL_SPANS_NOT_ENDED].push({ msg, timeOfConsume: timestampInSeconds() });
119
+ msg[MESSAGE_STORED_SPAN] = span;
120
+ }
121
+ withActiveSpan(span, () => {
122
+ onMessage.call(this, msg);
123
+ });
124
+ if (options?.noAck) {
125
+ span.end();
126
+ }
127
+ });
128
+ };
129
+ const callArgs = Array.prototype.slice.call(arguments);
130
+ callArgs[1] = patchedOnMessage;
131
+ return original.apply(this, callArgs);
132
+ };
133
+ }
134
+ function getConfirmedPublishPatch(original) {
135
+ return function confirmedPublish(exchange, routingKey, content, options, callback) {
136
+ const channel = this;
137
+ const { span, modifiedOptions } = startPublishSpan(exchange, routingKey, channel, options);
138
+ const patchedOnConfirm = function(err, ok) {
139
+ try {
140
+ withActiveSpan(span, () => {
141
+ callback?.call(this, err, ok);
142
+ });
143
+ } finally {
144
+ if (err) {
145
+ span.setStatus({ code: SPAN_STATUS_ERROR, message: "message confirmation has been nack'ed" });
146
+ }
147
+ span.end();
148
+ }
149
+ };
150
+ const argumentsCopy = [...arguments];
151
+ argumentsCopy[3] = modifiedOptions;
152
+ argumentsCopy[4] = patchedOnConfirm;
153
+ channel[CHANNEL_IS_CONFIRM_PUBLISHING] = true;
154
+ try {
155
+ return original.apply(this, argumentsCopy);
156
+ } finally {
157
+ channel[CHANNEL_IS_CONFIRM_PUBLISHING] = false;
158
+ }
159
+ };
160
+ }
161
+ function getPublishPatch(original) {
162
+ return function publish(exchange, routingKey, content, options) {
163
+ if (this[CHANNEL_IS_CONFIRM_PUBLISHING]) {
164
+ return original.apply(this, arguments);
165
+ }
166
+ const channel = this;
167
+ const { span, modifiedOptions } = startPublishSpan(exchange, routingKey, channel, options);
168
+ const argumentsCopy = [...arguments];
169
+ argumentsCopy[3] = modifiedOptions;
170
+ const originalRes = original.apply(this, argumentsCopy);
171
+ span.end();
172
+ return originalRes;
173
+ };
174
+ }
175
+
176
+ export { getAckAllPatch, getAckPatch, getChannelEmitPatch, getConfirmedPublishPatch, getConnectPatch, getConsumePatch, getPublishPatch };
177
+ //# sourceMappingURL=patches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patches.js","sources":["../../../../../../src/integrations/tracing/amqplib/vendored/patches.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-amqplib\n * - Upstream version: @opentelemetry/instrumentation-amqplib@0.65.0\n * - The channel/connection patches were extracted from the instrumentation class into standalone factories\n * and migrated to Sentry's span APIs; origin is folded into span creation instead of `index.ts` hooks\n * - Cross-service trace propagation uses Sentry's `getTraceData`/`continueTrace` instead of the OTel propagator\n * - Replaced the OTel context-key confirm-channel marker with a synchronous flag on the channel instance\n * - Dropped the instrumentation config and all hooks (publish/publishConfirm/consume/consumeEnd) and the\n * `useLinksForConsume` path; the SDK never used them\n */\n\nimport { continueTrace, SPAN_STATUS_ERROR, timestampInSeconds, withActiveSpan } from '@sentry/core';\nimport type { Connection, Options, Replies } from './amqplib-types';\nimport { EndOperation, type ConsumeMessage, type Message } from './types';\nimport type {\n InstrumentationConnection,\n InstrumentationConsumeChannel,\n InstrumentationConsumeMessage,\n InstrumentationMessage,\n InstrumentationPublishChannel,\n} from './utils';\nimport {\n CHANNEL_CONSUME_TIMEOUT_TIMER,\n CHANNEL_IS_CONFIRM_PUBLISHING,\n CHANNEL_SPANS_NOT_ENDED,\n CONNECTION_ATTRIBUTES,\n getConnectionAttributesFromServer,\n getConnectionAttributesFromUrl,\n getHeaderAsString,\n MESSAGE_STORED_SPAN,\n startConsumeSpan,\n startPublishSpan,\n} from './utils';\n\n// To prevent reference leaks from un-acked messages, their spans are closed after this timeout. The\n// upstream instrumentation exposed this as the `consumeTimeoutMs` option; the SDK always used the default.\nconst CONSUME_TIMEOUT_MS = 1000 * 60; // 1 minute\n\nfunction endConsumerSpan(\n message: InstrumentationMessage,\n isRejected: boolean | null,\n operation: EndOperation,\n requeue: boolean | undefined,\n): void {\n const storedSpan = message[MESSAGE_STORED_SPAN];\n if (!storedSpan) {\n return;\n }\n if (isRejected !== false) {\n storedSpan.setStatus({\n code: SPAN_STATUS_ERROR,\n message:\n operation !== EndOperation.ChannelClosed && operation !== EndOperation.ChannelError\n ? `${operation} called on message${\n requeue === true ? ' with requeue' : requeue === false ? ' without requeue' : ''\n }`\n : operation,\n });\n }\n storedSpan.end();\n message[MESSAGE_STORED_SPAN] = undefined;\n}\n\nfunction endAllSpansOnChannel(\n channel: InstrumentationConsumeChannel,\n isRejected: boolean,\n operation: EndOperation,\n requeue: boolean | undefined,\n): void {\n const spansNotEnded: { msg: Message }[] = channel[CHANNEL_SPANS_NOT_ENDED] ?? [];\n spansNotEnded.forEach(msgDetails => {\n endConsumerSpan(msgDetails.msg, isRejected, operation, requeue);\n });\n channel[CHANNEL_SPANS_NOT_ENDED] = [];\n}\n\nfunction checkConsumeTimeoutOnChannel(channel: InstrumentationConsumeChannel): void {\n const currentTime = timestampInSeconds();\n const spansNotEnded = channel[CHANNEL_SPANS_NOT_ENDED] ?? [];\n let i: number;\n for (i = 0; i < spansNotEnded.length; i++) {\n const currMessage = spansNotEnded[i]!;\n const timeFromConsumeMs = (currentTime - currMessage.timeOfConsume) * 1000;\n if (timeFromConsumeMs < CONSUME_TIMEOUT_MS) {\n break;\n }\n endConsumerSpan(currMessage.msg, null, EndOperation.InstrumentationTimeout, true);\n }\n spansNotEnded.splice(0, i);\n}\n\nexport function getConnectPatch(\n original: (\n url: string | Options.Connect,\n socketOptions: any,\n openCallback: (err: any, connection: Connection) => void,\n ) => Connection,\n) {\n return function patchedConnect(\n this: unknown,\n url: string | Options.Connect,\n socketOptions: any,\n openCallback: Function,\n ): Connection {\n return original.call(this, url, socketOptions, function (this: unknown, err: any, conn: InstrumentationConnection) {\n if (err == null) {\n const urlAttributes = getConnectionAttributesFromUrl(url);\n const serverAttributes = getConnectionAttributesFromServer(conn);\n conn[CONNECTION_ATTRIBUTES] = {\n ...urlAttributes,\n ...serverAttributes,\n };\n }\n openCallback.apply(this, arguments);\n });\n };\n}\n\nexport function getChannelEmitPatch(original: Function) {\n return function emit(this: InstrumentationConsumeChannel, eventName: string): void {\n if (eventName === 'close') {\n endAllSpansOnChannel(this, true, EndOperation.ChannelClosed, undefined);\n const activeTimer = this[CHANNEL_CONSUME_TIMEOUT_TIMER];\n if (activeTimer) {\n clearInterval(activeTimer);\n }\n this[CHANNEL_CONSUME_TIMEOUT_TIMER] = undefined;\n } else if (eventName === 'error') {\n endAllSpansOnChannel(this, true, EndOperation.ChannelError, undefined);\n }\n return original.apply(this, arguments);\n };\n}\n\nexport function getAckAllPatch(isRejected: boolean, endOperation: EndOperation) {\n return (original: Function) =>\n function ackAll(this: InstrumentationConsumeChannel, requeueOrEmpty?: boolean): void {\n endAllSpansOnChannel(this, isRejected, endOperation, requeueOrEmpty);\n return original.apply(this, arguments);\n };\n}\n\nexport function getAckPatch(isRejected: boolean, endOperation: EndOperation) {\n return (original: Function) =>\n function ack(\n this: InstrumentationConsumeChannel,\n message: Message,\n allUpToOrRequeue?: boolean,\n requeue?: boolean,\n ): void {\n const channel = this;\n // we use this patch in the reject function as well, but it has a different signature\n const requeueResolved = endOperation === EndOperation.Reject ? allUpToOrRequeue : requeue;\n\n const spansNotEnded: { msg: Message }[] = channel[CHANNEL_SPANS_NOT_ENDED] ?? [];\n const msgIndex = spansNotEnded.findIndex(msgDetails => msgDetails.msg === message);\n if (msgIndex < 0) {\n // should not happen in the happy flow, but possible if the user calls ack twice with the same message\n endConsumerSpan(message, isRejected, endOperation, requeueResolved);\n } else if (endOperation !== EndOperation.Reject && allUpToOrRequeue) {\n for (let i = 0; i <= msgIndex; i++) {\n endConsumerSpan(spansNotEnded[i]!.msg, isRejected, endOperation, requeueResolved);\n }\n spansNotEnded.splice(0, msgIndex + 1);\n } else {\n endConsumerSpan(message, isRejected, endOperation, requeueResolved);\n spansNotEnded.splice(msgIndex, 1);\n }\n return original.apply(this, arguments);\n };\n}\n\nexport function getConsumePatch(original: Function) {\n return function consume(\n this: InstrumentationConsumeChannel,\n queue: string,\n onMessage: (msg: ConsumeMessage | null) => void,\n options?: Options.Consume,\n ): Promise<Replies.Consume> {\n const channel = this;\n if (!Object.prototype.hasOwnProperty.call(channel, CHANNEL_SPANS_NOT_ENDED)) {\n const timer = setInterval(() => {\n checkConsumeTimeoutOnChannel(channel);\n }, CONSUME_TIMEOUT_MS);\n timer.unref();\n channel[CHANNEL_CONSUME_TIMEOUT_TIMER] = timer;\n channel[CHANNEL_SPANS_NOT_ENDED] = [];\n }\n\n const patchedOnMessage = function (this: unknown, msg: InstrumentationConsumeMessage | null): void {\n // msg is expected to be null for a consumer cancel notification\n // https://www.rabbitmq.com/consumer-cancel.html\n // in this case, we do not start a span, as this is not a real message.\n if (!msg) {\n return onMessage.call(this, msg);\n }\n\n const headers = msg.properties.headers ?? {};\n const sentryTrace = getHeaderAsString(headers, 'sentry-trace');\n const baggage = getHeaderAsString(headers, 'baggage');\n\n // Continue the producer's trace so the consumer span is parented to the message's producer.\n continueTrace({ sentryTrace, baggage }, () => {\n const span = startConsumeSpan(queue, msg, channel);\n\n if (!options?.noAck) {\n // store the message on the channel so we can close the span on ackAll etc\n channel[CHANNEL_SPANS_NOT_ENDED]!.push({ msg, timeOfConsume: timestampInSeconds() });\n // store the span on the message so we can end it when the user calls 'ack' on it\n msg[MESSAGE_STORED_SPAN] = span;\n }\n withActiveSpan(span, () => {\n onMessage.call(this, msg);\n });\n\n if (options?.noAck) {\n span.end();\n }\n });\n };\n\n // Copy `arguments` instead of mutating it: in CJS builds it's aliased to the named parameters,\n // so `arguments[1] = ...` would also reassign `onMessage` to `patchedOnMessage`, making the wrapper\n // call itself and recurse infinitely.\n const callArgs = Array.prototype.slice.call(arguments);\n callArgs[1] = patchedOnMessage;\n return original.apply(this, callArgs);\n };\n}\n\nexport function getConfirmedPublishPatch(original: Function) {\n return function confirmedPublish(\n this: InstrumentationPublishChannel,\n exchange: string,\n routingKey: string,\n content: Buffer,\n options?: Options.Publish,\n callback?: (err: any, ok: Replies.Empty) => void,\n ): boolean {\n const channel = this;\n const { span, modifiedOptions } = startPublishSpan(exchange, routingKey, channel, options);\n\n const patchedOnConfirm = function (this: unknown, err: any, ok: Replies.Empty): void {\n try {\n withActiveSpan(span, () => {\n callback?.call(this, err, ok);\n });\n } finally {\n if (err) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: \"message confirmation has been nack'ed\" });\n }\n span.end();\n }\n };\n\n // The confirm channel publish stores the message and registers a broker-confirm callback; the span\n // ends in that callback. The confirm publish internally delegates to the base channel publish, so we\n // flag the channel to stop the base publish patch from creating a second span. The inner call is\n // synchronous, so a flag on the instance is enough and avoids the OTel context machinery.\n const argumentsCopy = [...arguments];\n argumentsCopy[3] = modifiedOptions;\n argumentsCopy[4] = patchedOnConfirm;\n channel[CHANNEL_IS_CONFIRM_PUBLISHING] = true;\n try {\n return original.apply(this, argumentsCopy);\n } finally {\n channel[CHANNEL_IS_CONFIRM_PUBLISHING] = false;\n }\n };\n}\n\nexport function getPublishPatch(original: Function) {\n return function publish(\n this: InstrumentationPublishChannel,\n exchange: string,\n routingKey: string,\n content: Buffer,\n options?: Options.Publish,\n ): boolean {\n if (this[CHANNEL_IS_CONFIRM_PUBLISHING]) {\n // already instrumented by the confirm-channel publish patch\n return original.apply(this, arguments);\n }\n const channel = this;\n const { span, modifiedOptions } = startPublishSpan(exchange, routingKey, channel, options);\n\n // calling the normal channel publish function only stores the message in the queue; it does not send\n // it and wait for an ack, so the span duration is expected to be very short.\n const argumentsCopy = [...arguments];\n argumentsCopy[3] = modifiedOptions;\n const originalRes = original.apply(this, argumentsCopy);\n span.end();\n return originalRes;\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,17 @@
1
- const ATTR_MESSAGING_OPERATION = "messaging.operation";
2
1
  const ATTR_MESSAGING_SYSTEM = "messaging.system";
2
+ const ATTR_MESSAGING_OPERATION = "messaging.operation";
3
3
  const ATTR_NET_PEER_NAME = "net.peer.name";
4
4
  const ATTR_NET_PEER_PORT = "net.peer.port";
5
+ const ATTR_MESSAGING_DESTINATION = "messaging.destination";
6
+ const ATTR_MESSAGING_DESTINATION_KIND = "messaging.destination_kind";
7
+ const ATTR_MESSAGING_RABBITMQ_ROUTING_KEY = "messaging.rabbitmq.routing_key";
8
+ const ATTR_MESSAGING_PROTOCOL = "messaging.protocol";
9
+ const ATTR_MESSAGING_PROTOCOL_VERSION = "messaging.protocol_version";
10
+ const ATTR_MESSAGING_URL = "messaging.url";
11
+ const OLD_ATTR_MESSAGING_MESSAGE_ID = "messaging.message_id";
12
+ const ATTR_MESSAGING_CONVERSATION_ID = "messaging.conversation_id";
13
+ const MESSAGING_DESTINATION_KIND_VALUE_TOPIC = "topic";
14
+ const MESSAGING_OPERATION_VALUE_PROCESS = "process";
5
15
 
6
- export { ATTR_MESSAGING_OPERATION, ATTR_MESSAGING_SYSTEM, ATTR_NET_PEER_NAME, ATTR_NET_PEER_PORT };
16
+ export { ATTR_MESSAGING_CONVERSATION_ID, ATTR_MESSAGING_DESTINATION, ATTR_MESSAGING_DESTINATION_KIND, ATTR_MESSAGING_OPERATION, ATTR_MESSAGING_PROTOCOL, ATTR_MESSAGING_PROTOCOL_VERSION, ATTR_MESSAGING_RABBITMQ_ROUTING_KEY, ATTR_MESSAGING_SYSTEM, ATTR_MESSAGING_URL, ATTR_NET_PEER_NAME, ATTR_NET_PEER_PORT, MESSAGING_DESTINATION_KIND_VALUE_TOPIC, MESSAGING_OPERATION_VALUE_PROCESS, OLD_ATTR_MESSAGING_MESSAGE_ID };
7
17
  //# sourceMappingURL=semconv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"semconv.js","sources":["../../../../../../src/integrations/tracing/amqplib/vendored/semconv.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-amqplib\n * - Upstream version: @opentelemetry/instrumentation-amqplib@0.65.0\n */\n/* eslint-disable */\n\n/*\n * This file contains a copy of unstable semantic convention definitions\n * used by this package.\n * @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv\n */\n\n/**\n * Deprecated, use `messaging.operation.type` instead.\n *\n * @example publish\n * @example create\n * @example process\n *\n * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.\n *\n * @deprecated Replaced by `messaging.operation.type`.\n */\nexport const ATTR_MESSAGING_OPERATION = 'messaging.operation' as const;\n\n/**\n * The messaging system as identified by the client instrumentation.\n *\n * @note The actual messaging system may differ from the one known by the client. For example, when using Kafka client libraries to communicate with Azure Event Hubs, the `messaging.system` is set to `kafka` based on the instrumentation's best knowledge.\n *\n * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.\n */\nexport const ATTR_MESSAGING_SYSTEM = 'messaging.system' as const;\n\n/**\n * Deprecated, use `server.address` on client spans and `client.address` on server spans.\n *\n * @example example.com\n *\n * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.\n *\n * @deprecated Replaced by `server.address` on client spans and `client.address` on server spans.\n */\nexport const ATTR_NET_PEER_NAME = 'net.peer.name' as const;\n\n/**\n * Deprecated, use `server.port` on client spans and `client.port` on server spans.\n *\n * @example 8080\n *\n * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.\n *\n * @deprecated Replaced by `server.port` on client spans and `client.port` on server spans.\n */\nexport const ATTR_NET_PEER_PORT = 'net.peer.port' as const;\n"],"names":[],"mappings":"AA2BO,MAAM,wBAAA,GAA2B;AASjC,MAAM,qBAAA,GAAwB;AAW9B,MAAM,kBAAA,GAAqB;AAW3B,MAAM,kBAAA,GAAqB;;;;"}
1
+ {"version":3,"file":"semconv.js","sources":["../../../../../../src/integrations/tracing/amqplib/vendored/semconv.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-amqplib\n * - Upstream version: @opentelemetry/instrumentation-amqplib@0.65.0\n * - Merged the upstream `semconv.ts` and `semconv-obsolete.ts` into a single file containing only the\n * constants this instrumentation emits. These mirror the (now legacy) messaging semantic conventions\n * that the SDK has always emitted; the `@deprecated` annotations were dropped since these vendored\n * copies are intentionally the chosen output and we don't want to flag every usage site.\n */\n\n/** The messaging system as identified by the client instrumentation, e.g. `rabbitmq`. */\nexport const ATTR_MESSAGING_SYSTEM = 'messaging.system' as const;\n\n/** A string identifying the kind of message consumption. */\nexport const ATTR_MESSAGING_OPERATION = 'messaging.operation' as const;\n\n/** Host name of the message broker. */\nexport const ATTR_NET_PEER_NAME = 'net.peer.name' as const;\n\n/** Port of the message broker. */\nexport const ATTR_NET_PEER_PORT = 'net.peer.port' as const;\n\n/** The message destination name (the exchange for amqplib). */\nexport const ATTR_MESSAGING_DESTINATION = 'messaging.destination' as const;\n\n/** The kind of message destination. */\nexport const ATTR_MESSAGING_DESTINATION_KIND = 'messaging.destination_kind' as const;\n\n/** RabbitMQ message routing key. */\nexport const ATTR_MESSAGING_RABBITMQ_ROUTING_KEY = 'messaging.rabbitmq.routing_key' as const;\n\n/** The name of the transport protocol. */\nexport const ATTR_MESSAGING_PROTOCOL = 'messaging.protocol' as const;\n\n/** The version of the transport protocol. */\nexport const ATTR_MESSAGING_PROTOCOL_VERSION = 'messaging.protocol_version' as const;\n\n/** Connection string. */\nexport const ATTR_MESSAGING_URL = 'messaging.url' as const;\n\n/** A value used by the messaging system as an identifier for the message, represented as a string. */\nexport const OLD_ATTR_MESSAGING_MESSAGE_ID = 'messaging.message_id' as const;\n\n/** The conversation ID (a.k.a. correlation ID) identifying the conversation the message belongs to. */\nexport const ATTR_MESSAGING_CONVERSATION_ID = 'messaging.conversation_id' as const;\n\n/** Value for `messaging.destination_kind` when the destination is a topic. */\nexport const MESSAGING_DESTINATION_KIND_VALUE_TOPIC = 'topic' as const;\n\n/** Value for `messaging.operation` when the message is being processed by a consumer. */\nexport const MESSAGING_OPERATION_VALUE_PROCESS = 'process' as const;\n"],"names":[],"mappings":"AAcO,MAAM,qBAAA,GAAwB;AAG9B,MAAM,wBAAA,GAA2B;AAGjC,MAAM,kBAAA,GAAqB;AAG3B,MAAM,kBAAA,GAAqB;AAG3B,MAAM,0BAAA,GAA6B;AAGnC,MAAM,+BAAA,GAAkC;AAGxC,MAAM,mCAAA,GAAsC;AAG5C,MAAM,uBAAA,GAA0B;AAGhC,MAAM,+BAAA,GAAkC;AAGxC,MAAM,kBAAA,GAAqB;AAG3B,MAAM,6BAAA,GAAgC;AAGtC,MAAM,8BAAA,GAAiC;AAGvC,MAAM,sCAAA,GAAyC;AAG/C,MAAM,iCAAA,GAAoC;;;;"}
@@ -10,11 +10,6 @@ var EndOperation = /* @__PURE__ */ ((EndOperation2) => {
10
10
  EndOperation2["InstrumentationTimeout"] = "instrumentation timeout";
11
11
  return EndOperation2;
12
12
  })(EndOperation || {});
13
- const DEFAULT_CONFIG = {
14
- consumeTimeoutMs: 1e3 * 60,
15
- // 1 minute
16
- useLinksForConsume: false
17
- };
18
13
 
19
- export { DEFAULT_CONFIG, EndOperation };
14
+ export { EndOperation };
20
15
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../../../../../../src/integrations/tracing/amqplib/vendored/types.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-amqplib\n * - Upstream version: @opentelemetry/instrumentation-amqplib@0.65.0\n */\n/* eslint-disable */\n\nimport { Span } from '@opentelemetry/api';\nimport { InstrumentationConfig } from '@opentelemetry/instrumentation';\n\nexport interface PublishInfo {\n moduleVersion: string | undefined;\n exchange: string;\n routingKey: string;\n content: Buffer;\n options?: AmqplibPublishOptions;\n isConfirmChannel?: boolean;\n}\n\nexport interface PublishConfirmedInfo extends PublishInfo {\n confirmError?: any;\n}\n\nexport interface ConsumeInfo {\n moduleVersion: string | undefined;\n msg: ConsumeMessage;\n}\n\nexport interface ConsumeEndInfo {\n msg: ConsumeMessage;\n rejected: boolean | null;\n endOperation: EndOperation;\n}\n\nexport interface AmqplibPublishCustomAttributeFunction {\n (span: Span, publishInfo: PublishInfo): void;\n}\n\nexport interface AmqplibPublishConfirmCustomAttributeFunction {\n (span: Span, publishConfirmedInto: PublishConfirmedInfo): void;\n}\n\nexport interface AmqplibConsumeCustomAttributeFunction {\n (span: Span, consumeInfo: ConsumeInfo): void;\n}\n\nexport interface AmqplibConsumeEndCustomAttributeFunction {\n (span: Span, consumeEndInfo: ConsumeEndInfo): void;\n}\n\nexport enum EndOperation {\n AutoAck = 'auto ack',\n Ack = 'ack',\n AckAll = 'ackAll',\n Reject = 'reject',\n Nack = 'nack',\n NackAll = 'nackAll',\n ChannelClosed = 'channel closed',\n ChannelError = 'channel error',\n InstrumentationTimeout = 'instrumentation timeout',\n}\n\nexport interface AmqplibInstrumentationConfig extends InstrumentationConfig {\n /** hook for adding custom attributes before publish message is sent */\n publishHook?: AmqplibPublishCustomAttributeFunction;\n\n /** hook for adding custom attributes after publish message is confirmed by the broker */\n publishConfirmHook?: AmqplibPublishConfirmCustomAttributeFunction;\n\n /** hook for adding custom attributes before consumer message is processed */\n consumeHook?: AmqplibConsumeCustomAttributeFunction;\n\n /** hook for adding custom attributes after consumer message is acked to server */\n consumeEndHook?: AmqplibConsumeEndCustomAttributeFunction;\n\n /**\n * When user is setting up consume callback, it is user's responsibility to call\n * ack/nack etc on the msg to resolve it in the server.\n * If user is not calling the ack, the message will stay in the queue until\n * channel is closed, or until server timeout expires (if configured).\n * While we wait for the ack, a reference to the message is stored in plugin, which\n * will never be garbage collected.\n * To prevent memory leak, plugin has it's own configuration of timeout, which\n * will close the span if user did not call ack after this timeout.\n * If timeout is not big enough, span might be closed with 'InstrumentationTimeout',\n * and then received valid ack from the user later which will not be instrumented.\n *\n * Default is 1 minute\n */\n consumeTimeoutMs?: number;\n\n /** option to use a span link for the consume message instead of continuing a trace */\n useLinksForConsume?: boolean;\n}\n\nexport const DEFAULT_CONFIG: AmqplibInstrumentationConfig = {\n consumeTimeoutMs: 1000 * 60, // 1 minute\n useLinksForConsume: false,\n};\n\n// The following types are vendored from `@types/amqplib@0.10.1` - commit SHA: 4205e03127692a40b4871709a7134fe4e2ed5510\n\n// Vendored from: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/4205e03127692a40b4871709a7134fe4e2ed5510/types/amqplib/properties.d.ts#L108\n// This exists in `@types/amqplib` as `Options.Publish`. We're renaming things\n// here to avoid importing the whole Options namespace.\nexport interface AmqplibPublishOptions {\n expiration?: string | number;\n userId?: string;\n CC?: string | string[];\n\n mandatory?: boolean;\n persistent?: boolean;\n deliveryMode?: boolean | number;\n BCC?: string | string[];\n\n contentType?: string;\n contentEncoding?: string;\n headers?: any;\n priority?: number;\n correlationId?: string;\n replyTo?: string;\n messageId?: string;\n timestamp?: number;\n type?: string;\n appId?: string;\n}\n\n// Vendored from: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/4205e03127692a40b4871709a7134fe4e2ed5510/types/amqplib/properties.d.ts#L142\nexport interface Message {\n content: Buffer;\n fields: MessageFields;\n properties: MessageProperties;\n}\n\nexport interface ConsumeMessage extends Message {\n fields: ConsumeMessageFields;\n}\n\nexport interface CommonMessageFields {\n deliveryTag: number;\n redelivered: boolean;\n exchange: string;\n routingKey: string;\n}\n\nexport interface MessageFields extends CommonMessageFields {\n messageCount?: number;\n consumerTag?: string;\n}\n\nexport interface ConsumeMessageFields extends CommonMessageFields {\n deliveryTag: number;\n}\n\nexport interface MessageProperties {\n contentType: any | undefined;\n contentEncoding: any | undefined;\n headers: any;\n deliveryMode: any | undefined;\n priority: any | undefined;\n correlationId: any | undefined;\n replyTo: any | undefined;\n expiration: any | undefined;\n messageId: any | undefined;\n timestamp: any | undefined;\n type: any | undefined;\n userId: any | undefined;\n appId: any | undefined;\n clusterId: any | undefined;\n}\n"],"names":["EndOperation"],"mappings":"AAqDO,IAAK,YAAA,qBAAAA,aAAAA,KAAL;AACL,EAAAA,cAAA,SAAA,CAAA,GAAU,UAAA;AACV,EAAAA,cAAA,KAAA,CAAA,GAAM,KAAA;AACN,EAAAA,cAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,cAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,cAAA,MAAA,CAAA,GAAO,MAAA;AACP,EAAAA,cAAA,SAAA,CAAA,GAAU,SAAA;AACV,EAAAA,cAAA,eAAA,CAAA,GAAgB,gBAAA;AAChB,EAAAA,cAAA,cAAA,CAAA,GAAe,eAAA;AACf,EAAAA,cAAA,wBAAA,CAAA,GAAyB,yBAAA;AATf,EAAA,OAAAA,aAAAA;AAAA,CAAA,EAAA,YAAA,IAAA,EAAA;AA6CL,MAAM,cAAA,GAA+C;AAAA,EAC1D,kBAAkB,GAAA,GAAO,EAAA;AAAA;AAAA,EACzB,kBAAA,EAAoB;AACtB;;;;"}
1
+ {"version":3,"file":"types.js","sources":["../../../../../../src/integrations/tracing/amqplib/vendored/types.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-amqplib\n * - Upstream version: @opentelemetry/instrumentation-amqplib@0.65.0\n * - Some types vendored from @types/amqplib with simplifications\n * - Dropped the instrumentation config and all hooks; the SDK folds origin into span creation instead\n */\n\nexport enum EndOperation {\n AutoAck = 'auto ack',\n Ack = 'ack',\n AckAll = 'ackAll',\n Reject = 'reject',\n Nack = 'nack',\n NackAll = 'nackAll',\n ChannelClosed = 'channel closed',\n ChannelError = 'channel error',\n InstrumentationTimeout = 'instrumentation timeout',\n}\n\n// The following types are vendored from `@types/amqplib@0.10.1` - commit SHA: 4205e03127692a40b4871709a7134fe4e2ed5510\n\n// Vendored from: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/4205e03127692a40b4871709a7134fe4e2ed5510/types/amqplib/properties.d.ts#L142\nexport interface Message {\n content: Buffer;\n fields: MessageFields;\n properties: MessageProperties;\n}\n\nexport interface ConsumeMessage extends Message {\n fields: ConsumeMessageFields;\n}\n\nexport interface CommonMessageFields {\n deliveryTag: number;\n redelivered: boolean;\n exchange: string;\n routingKey: string;\n}\n\nexport interface MessageFields extends CommonMessageFields {\n messageCount?: number;\n consumerTag?: string;\n}\n\nexport interface ConsumeMessageFields extends CommonMessageFields {\n deliveryTag: number;\n}\n\nexport interface MessageProperties {\n contentType: any | undefined;\n contentEncoding: any | undefined;\n headers: any;\n deliveryMode: any | undefined;\n priority: any | undefined;\n correlationId: any | undefined;\n replyTo: any | undefined;\n expiration: any | undefined;\n messageId: any | undefined;\n timestamp: any | undefined;\n type: any | undefined;\n userId: any | undefined;\n appId: any | undefined;\n clusterId: any | undefined;\n}\n"],"names":["EndOperation"],"mappings":"AAWO,IAAK,YAAA,qBAAAA,aAAAA,KAAL;AACL,EAAAA,cAAA,SAAA,CAAA,GAAU,UAAA;AACV,EAAAA,cAAA,KAAA,CAAA,GAAM,KAAA;AACN,EAAAA,cAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,cAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,cAAA,MAAA,CAAA,GAAO,MAAA;AACP,EAAAA,cAAA,SAAA,CAAA,GAAU,SAAA;AACV,EAAAA,cAAA,eAAA,CAAA,GAAgB,gBAAA;AAChB,EAAAA,cAAA,cAAA,CAAA,GAAe,eAAA;AACf,EAAAA,cAAA,wBAAA,CAAA,GAAyB,yBAAA;AATf,EAAA,OAAAA,aAAAA;AAAA,CAAA,EAAA,YAAA,IAAA,EAAA;;;;"}
@@ -1,16 +1,16 @@
1
- import { createContextKey, diag } from '@opentelemetry/api';
2
- import { SemconvStability } from '@opentelemetry/instrumentation';
3
- import { ATTR_SERVER_ADDRESS, ATTR_SERVER_PORT } from '@opentelemetry/semantic-conventions';
4
- import { ATTR_NET_PEER_NAME, ATTR_NET_PEER_PORT, ATTR_MESSAGING_SYSTEM } from './semconv.js';
5
- import { ATTR_MESSAGING_URL, ATTR_MESSAGING_PROTOCOL, ATTR_MESSAGING_PROTOCOL_VERSION } from './semconv-obsolete.js';
1
+ import { SpanKind } from '@opentelemetry/api';
2
+ import { startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getTraceData } from '@sentry/core';
3
+ import { ATTR_MESSAGING_PROTOCOL, ATTR_NET_PEER_NAME, ATTR_NET_PEER_PORT, ATTR_MESSAGING_SYSTEM, MESSAGING_DESTINATION_KIND_VALUE_TOPIC, ATTR_MESSAGING_CONVERSATION_ID, OLD_ATTR_MESSAGING_MESSAGE_ID, ATTR_MESSAGING_RABBITMQ_ROUTING_KEY, ATTR_MESSAGING_DESTINATION_KIND, ATTR_MESSAGING_DESTINATION, ATTR_MESSAGING_PROTOCOL_VERSION, MESSAGING_OPERATION_VALUE_PROCESS, ATTR_MESSAGING_OPERATION, ATTR_MESSAGING_URL } from './semconv.js';
6
4
 
5
+ const PUBLISHER_ORIGIN = "auto.amqplib.otel.publisher";
6
+ const CONSUMER_ORIGIN = "auto.amqplib.otel.consumer";
7
7
  const MESSAGE_STORED_SPAN = /* @__PURE__ */ Symbol("opentelemetry.amqplib.message.stored-span");
8
8
  const CHANNEL_SPANS_NOT_ENDED = /* @__PURE__ */ Symbol("opentelemetry.amqplib.channel.spans-not-ended");
9
9
  const CHANNEL_CONSUME_TIMEOUT_TIMER = /* @__PURE__ */ Symbol(
10
10
  "opentelemetry.amqplib.channel.consumer-timeout-timer"
11
11
  );
12
12
  const CONNECTION_ATTRIBUTES = /* @__PURE__ */ Symbol("opentelemetry.amqplib.connection.attributes");
13
- const IS_CONFIRM_CHANNEL_CONTEXT_KEY = createContextKey("opentelemetry.amqplib.channel.is-confirm-channel");
13
+ const CHANNEL_IS_CONFIRM_PUBLISHING = /* @__PURE__ */ Symbol("sentry.amqplib.channel.is-confirm-publishing");
14
14
  const normalizeExchange = (exchangeName) => exchangeName !== "" ? exchangeName : "<default>";
15
15
  const censorPassword = (url) => {
16
16
  return url.replace(/:[^:@/]*@/, ":***@");
@@ -26,16 +26,6 @@ const getProtocol = (protocolFromUrl) => {
26
26
  const getHostname = (hostnameFromUrl) => {
27
27
  return hostnameFromUrl || "localhost";
28
28
  };
29
- const extractConnectionAttributeOrLog = (url, attributeKey, attributeValue, nameForLog) => {
30
- if (attributeValue) {
31
- return { [attributeKey]: attributeValue };
32
- } else {
33
- diag.error(`amqplib instrumentation: could not extract connection attribute ${nameForLog} from user supplied url`, {
34
- url
35
- });
36
- return {};
37
- }
38
- };
39
29
  const getConnectionAttributesFromServer = (conn) => {
40
30
  const product = conn.serverProperties.product?.toLowerCase?.();
41
31
  if (product) {
@@ -46,81 +36,81 @@ const getConnectionAttributesFromServer = (conn) => {
46
36
  return {};
47
37
  }
48
38
  };
49
- const getConnectionAttributesFromUrl = (url, netSemconvStability) => {
39
+ const getConnectionAttributesFromUrl = (url) => {
50
40
  const attributes = {
51
41
  [ATTR_MESSAGING_PROTOCOL_VERSION]: "0.9.1"
52
42
  // this is the only protocol supported by the instrumented library
53
43
  };
54
- url = url || "amqp://localhost";
55
- if (typeof url === "object") {
56
- const connectOptions = url;
44
+ const resolvedUrl = url || "amqp://localhost";
45
+ if (typeof resolvedUrl === "object") {
46
+ const connectOptions = resolvedUrl;
57
47
  const protocol = getProtocol(connectOptions?.protocol);
58
- Object.assign(attributes, {
59
- ...extractConnectionAttributeOrLog(url, ATTR_MESSAGING_PROTOCOL, protocol, "protocol")
60
- });
61
- const hostname = getHostname(connectOptions?.hostname);
62
- if (netSemconvStability & SemconvStability.OLD) {
63
- Object.assign(attributes, {
64
- ...extractConnectionAttributeOrLog(url, ATTR_NET_PEER_NAME, hostname, "hostname")
65
- });
66
- }
67
- if (netSemconvStability & SemconvStability.STABLE) {
68
- Object.assign(attributes, {
69
- ...extractConnectionAttributeOrLog(url, ATTR_SERVER_ADDRESS, hostname, "hostname")
70
- });
71
- }
72
- const port = getPort(connectOptions.port, protocol);
73
- if (netSemconvStability & SemconvStability.OLD) {
74
- Object.assign(attributes, extractConnectionAttributeOrLog(url, ATTR_NET_PEER_PORT, port, "port"));
75
- }
76
- if (netSemconvStability & SemconvStability.STABLE) {
77
- Object.assign(attributes, extractConnectionAttributeOrLog(url, ATTR_SERVER_PORT, port, "port"));
78
- }
48
+ attributes[ATTR_MESSAGING_PROTOCOL] = protocol;
49
+ attributes[ATTR_NET_PEER_NAME] = getHostname(connectOptions?.hostname);
50
+ attributes[ATTR_NET_PEER_PORT] = getPort(connectOptions.port, protocol);
79
51
  } else {
80
- const censoredUrl = censorPassword(url);
52
+ const censoredUrl = censorPassword(resolvedUrl);
81
53
  attributes[ATTR_MESSAGING_URL] = censoredUrl;
82
54
  try {
83
55
  const urlParts = new URL(censoredUrl);
84
56
  const protocol = getProtocol(urlParts.protocol);
85
- Object.assign(attributes, {
86
- ...extractConnectionAttributeOrLog(censoredUrl, ATTR_MESSAGING_PROTOCOL, protocol, "protocol")
87
- });
88
- const hostname = getHostname(urlParts.hostname);
89
- if (netSemconvStability & SemconvStability.OLD) {
90
- Object.assign(attributes, {
91
- ...extractConnectionAttributeOrLog(censoredUrl, ATTR_NET_PEER_NAME, hostname, "hostname")
92
- });
93
- }
94
- if (netSemconvStability & SemconvStability.STABLE) {
95
- Object.assign(attributes, {
96
- ...extractConnectionAttributeOrLog(censoredUrl, ATTR_SERVER_ADDRESS, hostname, "hostname")
97
- });
98
- }
99
- const port = getPort(urlParts.port ? parseInt(urlParts.port) : void 0, protocol);
100
- if (netSemconvStability & SemconvStability.OLD) {
101
- Object.assign(attributes, extractConnectionAttributeOrLog(censoredUrl, ATTR_NET_PEER_PORT, port, "port"));
102
- }
103
- if (netSemconvStability & SemconvStability.STABLE) {
104
- Object.assign(attributes, extractConnectionAttributeOrLog(censoredUrl, ATTR_SERVER_PORT, port, "port"));
105
- }
106
- } catch (err) {
107
- diag.error("amqplib instrumentation: error while extracting connection details from connection url", {
108
- censoredUrl,
109
- err
110
- });
57
+ attributes[ATTR_MESSAGING_PROTOCOL] = protocol;
58
+ attributes[ATTR_NET_PEER_NAME] = getHostname(urlParts.hostname);
59
+ attributes[ATTR_NET_PEER_PORT] = getPort(urlParts.port ? parseInt(urlParts.port) : void 0, protocol);
60
+ } catch {
111
61
  }
112
62
  }
113
63
  return attributes;
114
64
  };
115
- const markConfirmChannelTracing = (context) => {
116
- return context.setValue(IS_CONFIRM_CHANNEL_CONTEXT_KEY, true);
117
- };
118
- const unmarkConfirmChannelTracing = (context) => {
119
- return context.deleteValue(IS_CONFIRM_CHANNEL_CONTEXT_KEY);
120
- };
121
- const isConfirmChannelTracing = (context) => {
122
- return context.getValue(IS_CONFIRM_CHANNEL_CONTEXT_KEY) === true;
123
- };
65
+ function getHeaderAsString(headers, key) {
66
+ const value = headers?.[key];
67
+ if (value == null) {
68
+ return void 0;
69
+ }
70
+ return Array.isArray(value) ? String(value[0]) : String(value);
71
+ }
72
+ function startPublishSpan(exchange, routingKey, channel, options) {
73
+ const normalizedExchange = normalizeExchange(exchange);
74
+ const span = startInactiveSpan({
75
+ name: `publish ${normalizedExchange}`,
76
+ kind: SpanKind.PRODUCER,
77
+ attributes: {
78
+ ...channel.connection[CONNECTION_ATTRIBUTES],
79
+ [ATTR_MESSAGING_DESTINATION]: exchange,
80
+ [ATTR_MESSAGING_DESTINATION_KIND]: MESSAGING_DESTINATION_KIND_VALUE_TOPIC,
81
+ [ATTR_MESSAGING_RABBITMQ_ROUTING_KEY]: routingKey,
82
+ [OLD_ATTR_MESSAGING_MESSAGE_ID]: options?.messageId,
83
+ [ATTR_MESSAGING_CONVERSATION_ID]: options?.correlationId,
84
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: PUBLISHER_ORIGIN
85
+ }
86
+ });
87
+ const modifiedOptions = options ?? {};
88
+ modifiedOptions.headers = modifiedOptions.headers ?? {};
89
+ const traceData = getTraceData({ span });
90
+ if (traceData["sentry-trace"]) {
91
+ modifiedOptions.headers["sentry-trace"] = traceData["sentry-trace"];
92
+ }
93
+ if (traceData.baggage) {
94
+ modifiedOptions.headers["baggage"] = traceData.baggage;
95
+ }
96
+ return { span, modifiedOptions };
97
+ }
98
+ function startConsumeSpan(queue, msg, channel) {
99
+ return startInactiveSpan({
100
+ name: `${queue} process`,
101
+ kind: SpanKind.CONSUMER,
102
+ attributes: {
103
+ ...channel?.connection?.[CONNECTION_ATTRIBUTES],
104
+ [ATTR_MESSAGING_DESTINATION]: msg.fields?.exchange,
105
+ [ATTR_MESSAGING_DESTINATION_KIND]: MESSAGING_DESTINATION_KIND_VALUE_TOPIC,
106
+ [ATTR_MESSAGING_RABBITMQ_ROUTING_KEY]: msg.fields?.routingKey,
107
+ [ATTR_MESSAGING_OPERATION]: MESSAGING_OPERATION_VALUE_PROCESS,
108
+ [OLD_ATTR_MESSAGING_MESSAGE_ID]: msg?.properties.messageId,
109
+ [ATTR_MESSAGING_CONVERSATION_ID]: msg?.properties.correlationId,
110
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: CONSUMER_ORIGIN
111
+ }
112
+ });
113
+ }
124
114
 
125
- export { CHANNEL_CONSUME_TIMEOUT_TIMER, CHANNEL_SPANS_NOT_ENDED, CONNECTION_ATTRIBUTES, MESSAGE_STORED_SPAN, getConnectionAttributesFromServer, getConnectionAttributesFromUrl, isConfirmChannelTracing, markConfirmChannelTracing, normalizeExchange, unmarkConfirmChannelTracing };
115
+ export { CHANNEL_CONSUME_TIMEOUT_TIMER, CHANNEL_IS_CONFIRM_PUBLISHING, CHANNEL_SPANS_NOT_ENDED, CONNECTION_ATTRIBUTES, MESSAGE_STORED_SPAN, getConnectionAttributesFromServer, getConnectionAttributesFromUrl, getHeaderAsString, normalizeExchange, startConsumeSpan, startPublishSpan };
126
116
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../../../../src/integrations/tracing/amqplib/vendored/utils.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-amqplib\n * - Upstream version: @opentelemetry/instrumentation-amqplib@0.65.0\n * - Some types vendored from @types/amqplib with simplifications\n */\n/* eslint-disable */\n\nimport { Context, createContextKey, diag, Span, Attributes, AttributeValue } from '@opentelemetry/api';\nimport { SemconvStability } from '@opentelemetry/instrumentation';\nimport { ATTR_SERVER_ADDRESS, ATTR_SERVER_PORT } from '@opentelemetry/semantic-conventions';\nimport { ATTR_MESSAGING_SYSTEM, ATTR_NET_PEER_NAME, ATTR_NET_PEER_PORT } from './semconv';\nimport { ATTR_MESSAGING_PROTOCOL, ATTR_MESSAGING_PROTOCOL_VERSION, ATTR_MESSAGING_URL } from './semconv-obsolete';\nimport type { Connection, Channel, ConfirmChannel, Options } from './amqplib-types';\nimport type { ConsumeMessage, Message } from './types';\n\nexport const MESSAGE_STORED_SPAN: unique symbol = Symbol('opentelemetry.amqplib.message.stored-span');\nexport const CHANNEL_SPANS_NOT_ENDED: unique symbol = Symbol('opentelemetry.amqplib.channel.spans-not-ended');\nexport const CHANNEL_CONSUME_TIMEOUT_TIMER: unique symbol = Symbol(\n 'opentelemetry.amqplib.channel.consumer-timeout-timer',\n);\nexport const CONNECTION_ATTRIBUTES: unique symbol = Symbol('opentelemetry.amqplib.connection.attributes');\n\nexport type InstrumentationConnection = Connection & {\n [CONNECTION_ATTRIBUTES]?: Attributes;\n};\nexport type InstrumentationPublishChannel = (Channel | ConfirmChannel) & {\n connection: InstrumentationConnection;\n};\nexport type InstrumentationConsumeChannel = Channel & {\n connection: InstrumentationConnection;\n [CHANNEL_SPANS_NOT_ENDED]?: {\n msg: ConsumeMessage;\n timeOfConsume: number;\n }[];\n [CHANNEL_CONSUME_TIMEOUT_TIMER]?: NodeJS.Timeout;\n};\nexport type InstrumentationMessage = Message & {\n [MESSAGE_STORED_SPAN]?: Span;\n};\nexport type InstrumentationConsumeMessage = ConsumeMessage & {\n [MESSAGE_STORED_SPAN]?: Span;\n};\n\nconst IS_CONFIRM_CHANNEL_CONTEXT_KEY: symbol = createContextKey('opentelemetry.amqplib.channel.is-confirm-channel');\n\nexport const normalizeExchange = (exchangeName: string) => (exchangeName !== '' ? exchangeName : '<default>');\n\nconst censorPassword = (url: string): string => {\n return url.replace(/:[^:@/]*@/, ':***@');\n};\n\nconst getPort = (portFromUrl: number | undefined, resolvedProtocol: string): number => {\n // we are using the resolved protocol which is upper case\n // this code mimic the behavior of the amqplib which is used to set connection params\n return portFromUrl || (resolvedProtocol === 'AMQP' ? 5672 : 5671);\n};\n\nconst getProtocol = (protocolFromUrl: string | undefined): string => {\n const resolvedProtocol = protocolFromUrl || 'amqp';\n // the substring removed the ':' part of the protocol ('amqp:' -> 'amqp')\n const noEndingColon = resolvedProtocol.endsWith(':')\n ? resolvedProtocol.substring(0, resolvedProtocol.length - 1)\n : resolvedProtocol;\n // upper cases to match spec\n return noEndingColon.toUpperCase();\n};\n\nconst getHostname = (hostnameFromUrl: string | undefined): string => {\n // if user supplies empty hostname, it gets forwarded to 'net' package which default it to localhost.\n // https://nodejs.org/docs/latest-v12.x/api/net.html#net_socket_connect_options_connectlistener\n return hostnameFromUrl || 'localhost';\n};\n\nconst extractConnectionAttributeOrLog = (\n url: string | Options.Connect,\n attributeKey: string,\n attributeValue: AttributeValue,\n nameForLog: string,\n): Attributes => {\n if (attributeValue) {\n return { [attributeKey]: attributeValue };\n } else {\n diag.error(`amqplib instrumentation: could not extract connection attribute ${nameForLog} from user supplied url`, {\n url,\n });\n return {};\n }\n};\n\nexport const getConnectionAttributesFromServer = (conn: Connection): Attributes => {\n const product = conn.serverProperties.product?.toLowerCase?.();\n if (product) {\n return {\n [ATTR_MESSAGING_SYSTEM]: product,\n };\n } else {\n return {};\n }\n};\n\nexport const getConnectionAttributesFromUrl = (\n url: string | Options.Connect,\n netSemconvStability: SemconvStability,\n): Attributes => {\n const attributes: Attributes = {\n [ATTR_MESSAGING_PROTOCOL_VERSION]: '0.9.1', // this is the only protocol supported by the instrumented library\n };\n\n url = url || 'amqp://localhost';\n if (typeof url === 'object') {\n const connectOptions = url as Options.Connect;\n\n const protocol = getProtocol(connectOptions?.protocol);\n Object.assign(attributes, {\n ...extractConnectionAttributeOrLog(url, ATTR_MESSAGING_PROTOCOL, protocol, 'protocol'),\n });\n\n const hostname = getHostname(connectOptions?.hostname);\n if (netSemconvStability & SemconvStability.OLD) {\n Object.assign(attributes, {\n ...extractConnectionAttributeOrLog(url, ATTR_NET_PEER_NAME, hostname, 'hostname'),\n });\n }\n if (netSemconvStability & SemconvStability.STABLE) {\n Object.assign(attributes, {\n ...extractConnectionAttributeOrLog(url, ATTR_SERVER_ADDRESS, hostname, 'hostname'),\n });\n }\n\n const port = getPort(connectOptions.port, protocol);\n if (netSemconvStability & SemconvStability.OLD) {\n Object.assign(attributes, extractConnectionAttributeOrLog(url, ATTR_NET_PEER_PORT, port, 'port'));\n }\n if (netSemconvStability & SemconvStability.STABLE) {\n Object.assign(attributes, extractConnectionAttributeOrLog(url, ATTR_SERVER_PORT, port, 'port'));\n }\n } else {\n const censoredUrl = censorPassword(url);\n attributes[ATTR_MESSAGING_URL] = censoredUrl;\n try {\n const urlParts = new URL(censoredUrl);\n\n const protocol = getProtocol(urlParts.protocol);\n Object.assign(attributes, {\n ...extractConnectionAttributeOrLog(censoredUrl, ATTR_MESSAGING_PROTOCOL, protocol, 'protocol'),\n });\n\n const hostname = getHostname(urlParts.hostname);\n if (netSemconvStability & SemconvStability.OLD) {\n Object.assign(attributes, {\n ...extractConnectionAttributeOrLog(censoredUrl, ATTR_NET_PEER_NAME, hostname, 'hostname'),\n });\n }\n if (netSemconvStability & SemconvStability.STABLE) {\n Object.assign(attributes, {\n ...extractConnectionAttributeOrLog(censoredUrl, ATTR_SERVER_ADDRESS, hostname, 'hostname'),\n });\n }\n\n const port = getPort(urlParts.port ? parseInt(urlParts.port) : undefined, protocol);\n if (netSemconvStability & SemconvStability.OLD) {\n Object.assign(attributes, extractConnectionAttributeOrLog(censoredUrl, ATTR_NET_PEER_PORT, port, 'port'));\n }\n if (netSemconvStability & SemconvStability.STABLE) {\n Object.assign(attributes, extractConnectionAttributeOrLog(censoredUrl, ATTR_SERVER_PORT, port, 'port'));\n }\n } catch (err) {\n diag.error('amqplib instrumentation: error while extracting connection details from connection url', {\n censoredUrl,\n err,\n });\n }\n }\n return attributes;\n};\n\nexport const markConfirmChannelTracing = (context: Context) => {\n return context.setValue(IS_CONFIRM_CHANNEL_CONTEXT_KEY, true);\n};\n\nexport const unmarkConfirmChannelTracing = (context: Context) => {\n return context.deleteValue(IS_CONFIRM_CHANNEL_CONTEXT_KEY);\n};\n\nexport const isConfirmChannelTracing = (context: Context) => {\n return context.getValue(IS_CONFIRM_CHANNEL_CONTEXT_KEY) === true;\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../../../../../src/integrations/tracing/amqplib/vendored/utils.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-amqplib\n * - Upstream version: @opentelemetry/instrumentation-amqplib@0.65.0\n * - Some types vendored from @types/amqplib with simplifications\n * - Span creation extracted here and migrated to the @sentry/core API; origin folded into span creation\n * - Cross-service trace propagation uses Sentry's `getTraceData` instead of the OTel propagator\n * - Dropped the env-gated stable-semconv dual emission; only the (default) old semantic conventions are emitted\n * - Replaced the OTel context-key confirm-channel marker with a synchronous flag on the channel instance\n */\n\nimport { SpanKind } from '@opentelemetry/api';\nimport type { Span, SpanAttributes } from '@sentry/core';\nimport { getTraceData, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } from '@sentry/core';\nimport type { Channel, ConfirmChannel, Connection, Options } from './amqplib-types';\nimport {\n ATTR_MESSAGING_CONVERSATION_ID,\n ATTR_MESSAGING_DESTINATION,\n ATTR_MESSAGING_DESTINATION_KIND,\n ATTR_MESSAGING_OPERATION,\n ATTR_MESSAGING_PROTOCOL,\n ATTR_MESSAGING_PROTOCOL_VERSION,\n ATTR_MESSAGING_RABBITMQ_ROUTING_KEY,\n ATTR_MESSAGING_SYSTEM,\n ATTR_MESSAGING_URL,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n MESSAGING_DESTINATION_KIND_VALUE_TOPIC,\n MESSAGING_OPERATION_VALUE_PROCESS,\n OLD_ATTR_MESSAGING_MESSAGE_ID,\n} from './semconv';\nimport type { ConsumeMessage, Message } from './types';\n\nconst PUBLISHER_ORIGIN = 'auto.amqplib.otel.publisher';\nconst CONSUMER_ORIGIN = 'auto.amqplib.otel.consumer';\n\nexport const MESSAGE_STORED_SPAN: unique symbol = Symbol('opentelemetry.amqplib.message.stored-span');\nexport const CHANNEL_SPANS_NOT_ENDED: unique symbol = Symbol('opentelemetry.amqplib.channel.spans-not-ended');\nexport const CHANNEL_CONSUME_TIMEOUT_TIMER: unique symbol = Symbol(\n 'opentelemetry.amqplib.channel.consumer-timeout-timer',\n);\nexport const CONNECTION_ATTRIBUTES: unique symbol = Symbol('opentelemetry.amqplib.connection.attributes');\nexport const CHANNEL_IS_CONFIRM_PUBLISHING: unique symbol = Symbol('sentry.amqplib.channel.is-confirm-publishing');\n\nexport type InstrumentationConnection = Connection & {\n [CONNECTION_ATTRIBUTES]?: SpanAttributes;\n};\nexport type InstrumentationPublishChannel = (Channel | ConfirmChannel) & {\n connection: InstrumentationConnection;\n [CHANNEL_IS_CONFIRM_PUBLISHING]?: boolean;\n};\nexport type InstrumentationConsumeChannel = Channel & {\n connection: InstrumentationConnection;\n [CHANNEL_SPANS_NOT_ENDED]?: {\n msg: ConsumeMessage;\n timeOfConsume: number;\n }[];\n [CHANNEL_CONSUME_TIMEOUT_TIMER]?: NodeJS.Timeout;\n};\nexport type InstrumentationMessage = Message & {\n [MESSAGE_STORED_SPAN]?: Span;\n};\nexport type InstrumentationConsumeMessage = ConsumeMessage & {\n [MESSAGE_STORED_SPAN]?: Span;\n};\n\nexport const normalizeExchange = (exchangeName: string): string => (exchangeName !== '' ? exchangeName : '<default>');\n\nconst censorPassword = (url: string): string => {\n return url.replace(/:[^:@/]*@/, ':***@');\n};\n\nconst getPort = (portFromUrl: number | undefined, resolvedProtocol: string): number => {\n // we are using the resolved protocol which is upper case\n // this code mimics the behavior of amqplib which is used to set connection params\n return portFromUrl || (resolvedProtocol === 'AMQP' ? 5672 : 5671);\n};\n\nconst getProtocol = (protocolFromUrl: string | undefined): string => {\n const resolvedProtocol = protocolFromUrl || 'amqp';\n // the substring removes the ':' part of the protocol ('amqp:' -> 'amqp')\n const noEndingColon = resolvedProtocol.endsWith(':')\n ? resolvedProtocol.substring(0, resolvedProtocol.length - 1)\n : resolvedProtocol;\n // upper case to match spec\n return noEndingColon.toUpperCase();\n};\n\nconst getHostname = (hostnameFromUrl: string | undefined): string => {\n // if user supplies empty hostname, it gets forwarded to 'net' package which defaults it to localhost.\n // https://nodejs.org/docs/latest-v12.x/api/net.html#net_socket_connect_options_connectlistener\n return hostnameFromUrl || 'localhost';\n};\n\nexport const getConnectionAttributesFromServer = (conn: Connection): SpanAttributes => {\n const product = conn.serverProperties.product?.toLowerCase?.();\n if (product) {\n return {\n [ATTR_MESSAGING_SYSTEM]: product,\n };\n } else {\n return {};\n }\n};\n\nexport const getConnectionAttributesFromUrl = (url: string | Options.Connect): SpanAttributes => {\n const attributes: SpanAttributes = {\n [ATTR_MESSAGING_PROTOCOL_VERSION]: '0.9.1', // this is the only protocol supported by the instrumented library\n };\n\n const resolvedUrl = url || 'amqp://localhost';\n if (typeof resolvedUrl === 'object') {\n const connectOptions = resolvedUrl;\n\n const protocol = getProtocol(connectOptions?.protocol);\n attributes[ATTR_MESSAGING_PROTOCOL] = protocol;\n attributes[ATTR_NET_PEER_NAME] = getHostname(connectOptions?.hostname);\n attributes[ATTR_NET_PEER_PORT] = getPort(connectOptions.port, protocol);\n } else {\n const censoredUrl = censorPassword(resolvedUrl);\n attributes[ATTR_MESSAGING_URL] = censoredUrl;\n try {\n const urlParts = new URL(censoredUrl);\n\n const protocol = getProtocol(urlParts.protocol);\n attributes[ATTR_MESSAGING_PROTOCOL] = protocol;\n attributes[ATTR_NET_PEER_NAME] = getHostname(urlParts.hostname);\n attributes[ATTR_NET_PEER_PORT] = getPort(urlParts.port ? parseInt(urlParts.port) : undefined, protocol);\n } catch {\n // best-effort: a malformed url simply yields fewer connection attributes\n }\n }\n return attributes;\n};\n\n/** Reads a propagation header value off an amqplib message as a string. */\nexport function getHeaderAsString(headers: Record<string, unknown> | undefined, key: string): string | undefined {\n const value = headers?.[key];\n if (value == null) {\n return undefined;\n }\n return Array.isArray(value) ? String(value[0]) : String(value);\n}\n\n/** Starts an inactive producer span and propagates its trace into the publish `options.headers`. */\nexport function startPublishSpan(\n exchange: string,\n routingKey: string,\n channel: InstrumentationPublishChannel,\n options?: Options.Publish,\n): { span: Span; modifiedOptions: Options.Publish } {\n const normalizedExchange = normalizeExchange(exchange);\n\n const span = startInactiveSpan({\n name: `publish ${normalizedExchange}`,\n kind: SpanKind.PRODUCER,\n attributes: {\n ...channel.connection[CONNECTION_ATTRIBUTES],\n [ATTR_MESSAGING_DESTINATION]: exchange,\n [ATTR_MESSAGING_DESTINATION_KIND]: MESSAGING_DESTINATION_KIND_VALUE_TOPIC,\n [ATTR_MESSAGING_RABBITMQ_ROUTING_KEY]: routingKey,\n [OLD_ATTR_MESSAGING_MESSAGE_ID]: options?.messageId,\n [ATTR_MESSAGING_CONVERSATION_ID]: options?.correlationId,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: PUBLISHER_ORIGIN,\n },\n });\n\n const modifiedOptions = options ?? {};\n modifiedOptions.headers = modifiedOptions.headers ?? {};\n\n const traceData = getTraceData({ span });\n if (traceData['sentry-trace']) {\n modifiedOptions.headers['sentry-trace'] = traceData['sentry-trace'];\n }\n if (traceData.baggage) {\n modifiedOptions.headers['baggage'] = traceData.baggage;\n }\n\n return { span, modifiedOptions };\n}\n\n/** Starts an inactive consumer (process) span carrying the amqplib messaging attributes. */\nexport function startConsumeSpan(\n queue: string,\n msg: InstrumentationConsumeMessage,\n channel: InstrumentationConsumeChannel,\n): Span {\n return startInactiveSpan({\n name: `${queue} process`,\n kind: SpanKind.CONSUMER,\n attributes: {\n ...channel?.connection?.[CONNECTION_ATTRIBUTES],\n [ATTR_MESSAGING_DESTINATION]: msg.fields?.exchange,\n [ATTR_MESSAGING_DESTINATION_KIND]: MESSAGING_DESTINATION_KIND_VALUE_TOPIC,\n [ATTR_MESSAGING_RABBITMQ_ROUTING_KEY]: msg.fields?.routingKey,\n [ATTR_MESSAGING_OPERATION]: MESSAGING_OPERATION_VALUE_PROCESS,\n [OLD_ATTR_MESSAGING_MESSAGE_ID]: msg?.properties.messageId,\n [ATTR_MESSAGING_CONVERSATION_ID]: msg?.properties.correlationId,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: CONSUMER_ORIGIN,\n },\n });\n}\n"],"names":[],"mappings":"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"}
@@ -1,32 +1,9 @@
1
- import { defineIntegration, captureException, flush, SEMANTIC_ATTRIBUTE_SENTRY_OP } from '@sentry/core';
2
- import { generateInstrumentOnce, addOriginToSpan } from '@sentry/node-core';
1
+ import { defineIntegration } from '@sentry/core';
2
+ import { generateInstrumentOnce } from '@sentry/node-core';
3
3
  import { FirebaseInstrumentation } from './otel/firebaseInstrumentation.js';
4
4
 
5
5
  const INTEGRATION_NAME = "Firebase";
6
- const config = {
7
- firestoreSpanCreationHook: (span) => {
8
- addOriginToSpan(span, "auto.firebase.otel.firestore");
9
- span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, "db.query");
10
- },
11
- functions: {
12
- requestHook: (span) => {
13
- addOriginToSpan(span, "auto.firebase.otel.functions");
14
- span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, "http.request");
15
- },
16
- errorHook: async (_, error) => {
17
- if (error) {
18
- captureException(error, {
19
- mechanism: {
20
- type: "auto.firebase.otel.functions",
21
- handled: false
22
- }
23
- });
24
- await flush(2e3);
25
- }
26
- }
27
- }
28
- };
29
- const instrumentFirebase = generateInstrumentOnce(INTEGRATION_NAME, () => new FirebaseInstrumentation(config));
6
+ const instrumentFirebase = generateInstrumentOnce(INTEGRATION_NAME, () => new FirebaseInstrumentation());
30
7
  const _firebaseIntegration = (() => {
31
8
  return {
32
9
  name: INTEGRATION_NAME,
@@ -1 +1 @@
1
- {"version":3,"file":"firebase.js","sources":["../../../../../src/integrations/tracing/firebase/firebase.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { captureException, defineIntegration, flush, SEMANTIC_ATTRIBUTE_SENTRY_OP } from '@sentry/core';\nimport { addOriginToSpan, generateInstrumentOnce } from '@sentry/node-core';\nimport { FirebaseInstrumentation, type FirebaseInstrumentationConfig } from './otel';\n\nconst INTEGRATION_NAME = 'Firebase';\n\nconst config: FirebaseInstrumentationConfig = {\n firestoreSpanCreationHook: span => {\n addOriginToSpan(span, 'auto.firebase.otel.firestore');\n\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'db.query');\n },\n functions: {\n requestHook: span => {\n addOriginToSpan(span, 'auto.firebase.otel.functions');\n\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'http.request');\n },\n errorHook: async (_, error) => {\n if (error) {\n captureException(error, {\n mechanism: {\n type: 'auto.firebase.otel.functions',\n handled: false,\n },\n });\n await flush(2000);\n }\n },\n },\n};\n\nexport const instrumentFirebase = generateInstrumentOnce(INTEGRATION_NAME, () => new FirebaseInstrumentation(config));\n\nconst _firebaseIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentFirebase();\n },\n };\n}) satisfies IntegrationFn;\n\nexport const firebaseIntegration = defineIntegration(_firebaseIntegration);\n"],"names":[],"mappings":";;;;AAKA,MAAM,gBAAA,GAAmB,UAAA;AAEzB,MAAM,MAAA,GAAwC;AAAA,EAC5C,2BAA2B,CAAA,IAAA,KAAQ;AACjC,IAAA,eAAA,CAAgB,MAAM,8BAA8B,CAAA;AAEpD,IAAA,IAAA,CAAK,YAAA,CAAa,8BAA8B,UAAU,CAAA;AAAA,EAC5D,CAAA;AAAA,EACA,SAAA,EAAW;AAAA,IACT,aAAa,CAAA,IAAA,KAAQ;AACnB,MAAA,eAAA,CAAgB,MAAM,8BAA8B,CAAA;AAEpD,MAAA,IAAA,CAAK,YAAA,CAAa,8BAA8B,cAAc,CAAA;AAAA,IAChE,CAAA;AAAA,IACA,SAAA,EAAW,OAAO,CAAA,EAAG,KAAA,KAAU;AAC7B,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,gBAAA,CAAiB,KAAA,EAAO;AAAA,UACtB,SAAA,EAAW;AAAA,YACT,IAAA,EAAM,8BAAA;AAAA,YACN,OAAA,EAAS;AAAA;AACX,SACD,CAAA;AACD,QAAA,MAAM,MAAM,GAAI,CAAA;AAAA,MAClB;AAAA,IACF;AAAA;AAEJ,CAAA;AAEO,MAAM,qBAAqB,sBAAA,CAAuB,gBAAA,EAAkB,MAAM,IAAI,uBAAA,CAAwB,MAAM,CAAC;AAEpH,MAAM,wBAAwB,MAAM;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,kBAAA,EAAmB;AAAA,IACrB;AAAA,GACF;AACF,CAAA,CAAA;AAEO,MAAM,mBAAA,GAAsB,kBAAkB,oBAAoB;;;;"}
1
+ {"version":3,"file":"firebase.js","sources":["../../../../../src/integrations/tracing/firebase/firebase.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { FirebaseInstrumentation } from './otel';\n\nconst INTEGRATION_NAME = 'Firebase';\n\nexport const instrumentFirebase = generateInstrumentOnce(INTEGRATION_NAME, () => new FirebaseInstrumentation());\n\nconst _firebaseIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentFirebase();\n },\n };\n}) satisfies IntegrationFn;\n\nexport const firebaseIntegration = defineIntegration(_firebaseIntegration);\n"],"names":[],"mappings":";;;;AAKA,MAAM,gBAAA,GAAmB,UAAA;AAElB,MAAM,qBAAqB,sBAAA,CAAuB,gBAAA,EAAkB,MAAM,IAAI,yBAAyB;AAE9G,MAAM,wBAAwB,MAAM;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,kBAAA,EAAmB;AAAA,IACrB;AAAA,GACF;AACF,CAAA,CAAA;AAEO,MAAM,mBAAA,GAAsB,kBAAkB,oBAAoB;;;;"}