@depup/elastic-apm-node 4.15.0-depup.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 (154) hide show
  1. package/LICENSE +26 -0
  2. package/NOTICE.md +442 -0
  3. package/README.md +48 -0
  4. package/changes.json +78 -0
  5. package/index.d.ts +398 -0
  6. package/index.js +11 -0
  7. package/lib/InflightEventSet.js +53 -0
  8. package/lib/activation-method.js +119 -0
  9. package/lib/agent.js +941 -0
  10. package/lib/apm-client/apm-client.js +313 -0
  11. package/lib/apm-client/http-apm-client/CHANGELOG.md +271 -0
  12. package/lib/apm-client/http-apm-client/README.md +485 -0
  13. package/lib/apm-client/http-apm-client/central-config.js +41 -0
  14. package/lib/apm-client/http-apm-client/container-info.js +111 -0
  15. package/lib/apm-client/http-apm-client/detect-hostname.js +96 -0
  16. package/lib/apm-client/http-apm-client/index.js +1975 -0
  17. package/lib/apm-client/http-apm-client/logging.js +31 -0
  18. package/lib/apm-client/http-apm-client/ndjson.js +20 -0
  19. package/lib/apm-client/http-apm-client/truncate.js +434 -0
  20. package/lib/apm-client/noop-apm-client.js +73 -0
  21. package/lib/async-hooks-polyfill.js +58 -0
  22. package/lib/cloud-metadata/aws.js +175 -0
  23. package/lib/cloud-metadata/azure.js +123 -0
  24. package/lib/cloud-metadata/callback-coordination.js +159 -0
  25. package/lib/cloud-metadata/gcp.js +133 -0
  26. package/lib/cloud-metadata/index.js +175 -0
  27. package/lib/config/config.js +458 -0
  28. package/lib/config/normalizers.js +701 -0
  29. package/lib/config/schema.js +1007 -0
  30. package/lib/constants.js +35 -0
  31. package/lib/errors.js +303 -0
  32. package/lib/filters/sanitize-field-names.js +69 -0
  33. package/lib/http-request.js +249 -0
  34. package/lib/instrumentation/azure-functions.js +519 -0
  35. package/lib/instrumentation/context.js +56 -0
  36. package/lib/instrumentation/dropped-spans-stats.js +112 -0
  37. package/lib/instrumentation/elasticsearch-shared.js +63 -0
  38. package/lib/instrumentation/express-utils.js +91 -0
  39. package/lib/instrumentation/generic-span.js +322 -0
  40. package/lib/instrumentation/http-shared.js +424 -0
  41. package/lib/instrumentation/ids.js +39 -0
  42. package/lib/instrumentation/index.js +1127 -0
  43. package/lib/instrumentation/modules/@apollo/server.js +30 -0
  44. package/lib/instrumentation/modules/@aws-sdk/client-dynamodb.js +143 -0
  45. package/lib/instrumentation/modules/@aws-sdk/client-s3.js +230 -0
  46. package/lib/instrumentation/modules/@aws-sdk/client-sns.js +197 -0
  47. package/lib/instrumentation/modules/@aws-sdk/client-sqs.js +336 -0
  48. package/lib/instrumentation/modules/@elastic/elasticsearch.js +343 -0
  49. package/lib/instrumentation/modules/@hapi/hapi.js +221 -0
  50. package/lib/instrumentation/modules/@opentelemetry/api.js +86 -0
  51. package/lib/instrumentation/modules/@opentelemetry/sdk-metrics.js +79 -0
  52. package/lib/instrumentation/modules/@redis/client/dist/lib/client/commands-queue.js +178 -0
  53. package/lib/instrumentation/modules/@redis/client/dist/lib/client/index.js +49 -0
  54. package/lib/instrumentation/modules/@smithy/smithy-client.js +198 -0
  55. package/lib/instrumentation/modules/_lambda-handler.js +40 -0
  56. package/lib/instrumentation/modules/apollo-server-core.js +49 -0
  57. package/lib/instrumentation/modules/aws-sdk/dynamodb.js +155 -0
  58. package/lib/instrumentation/modules/aws-sdk/s3.js +184 -0
  59. package/lib/instrumentation/modules/aws-sdk/sns.js +232 -0
  60. package/lib/instrumentation/modules/aws-sdk/sqs.js +361 -0
  61. package/lib/instrumentation/modules/aws-sdk.js +76 -0
  62. package/lib/instrumentation/modules/bluebird.js +93 -0
  63. package/lib/instrumentation/modules/cassandra-driver.js +280 -0
  64. package/lib/instrumentation/modules/elasticsearch.js +191 -0
  65. package/lib/instrumentation/modules/express-graphql.js +66 -0
  66. package/lib/instrumentation/modules/express-queue.js +28 -0
  67. package/lib/instrumentation/modules/express.js +162 -0
  68. package/lib/instrumentation/modules/fastify.js +172 -0
  69. package/lib/instrumentation/modules/finalhandler.js +41 -0
  70. package/lib/instrumentation/modules/generic-pool.js +85 -0
  71. package/lib/instrumentation/modules/graphql.js +256 -0
  72. package/lib/instrumentation/modules/handlebars.js +22 -0
  73. package/lib/instrumentation/modules/http.js +112 -0
  74. package/lib/instrumentation/modules/http2.js +320 -0
  75. package/lib/instrumentation/modules/https.js +68 -0
  76. package/lib/instrumentation/modules/ioredis.js +94 -0
  77. package/lib/instrumentation/modules/jade.js +18 -0
  78. package/lib/instrumentation/modules/kafkajs.js +476 -0
  79. package/lib/instrumentation/modules/knex.js +91 -0
  80. package/lib/instrumentation/modules/koa-router.js +74 -0
  81. package/lib/instrumentation/modules/koa.js +15 -0
  82. package/lib/instrumentation/modules/memcached.js +99 -0
  83. package/lib/instrumentation/modules/mimic-response.js +45 -0
  84. package/lib/instrumentation/modules/mongodb/lib/cmap/connection_pool.js +40 -0
  85. package/lib/instrumentation/modules/mongodb-core.js +206 -0
  86. package/lib/instrumentation/modules/mongodb.js +259 -0
  87. package/lib/instrumentation/modules/mysql.js +200 -0
  88. package/lib/instrumentation/modules/mysql2.js +140 -0
  89. package/lib/instrumentation/modules/pg.js +148 -0
  90. package/lib/instrumentation/modules/pug.js +18 -0
  91. package/lib/instrumentation/modules/redis.js +176 -0
  92. package/lib/instrumentation/modules/restify.js +52 -0
  93. package/lib/instrumentation/modules/tedious.js +159 -0
  94. package/lib/instrumentation/modules/undici.js +270 -0
  95. package/lib/instrumentation/modules/ws.js +59 -0
  96. package/lib/instrumentation/noop-transaction.js +81 -0
  97. package/lib/instrumentation/run-context/AbstractRunContextManager.js +215 -0
  98. package/lib/instrumentation/run-context/AsyncHooksRunContextManager.js +106 -0
  99. package/lib/instrumentation/run-context/AsyncLocalStorageRunContextManager.js +73 -0
  100. package/lib/instrumentation/run-context/BasicRunContextManager.js +82 -0
  101. package/lib/instrumentation/run-context/RunContext.js +151 -0
  102. package/lib/instrumentation/run-context/index.js +23 -0
  103. package/lib/instrumentation/shimmer.js +123 -0
  104. package/lib/instrumentation/span-compression.js +239 -0
  105. package/lib/instrumentation/span.js +621 -0
  106. package/lib/instrumentation/template-shared.js +43 -0
  107. package/lib/instrumentation/timer.js +84 -0
  108. package/lib/instrumentation/transaction.js +571 -0
  109. package/lib/lambda.js +992 -0
  110. package/lib/load-source-map.js +100 -0
  111. package/lib/logging.js +212 -0
  112. package/lib/metrics/index.js +92 -0
  113. package/lib/metrics/platforms/generic/index.js +40 -0
  114. package/lib/metrics/platforms/generic/process-cpu.js +22 -0
  115. package/lib/metrics/platforms/generic/process-top.js +157 -0
  116. package/lib/metrics/platforms/generic/stats.js +34 -0
  117. package/lib/metrics/platforms/generic/system-cpu.js +51 -0
  118. package/lib/metrics/platforms/linux/index.js +19 -0
  119. package/lib/metrics/platforms/linux/stats.js +213 -0
  120. package/lib/metrics/queue.js +90 -0
  121. package/lib/metrics/registry.js +52 -0
  122. package/lib/metrics/reporter.js +119 -0
  123. package/lib/metrics/runtime.js +77 -0
  124. package/lib/middleware/connect.js +16 -0
  125. package/lib/opentelemetry-bridge/OTelBridgeNonRecordingSpan.js +150 -0
  126. package/lib/opentelemetry-bridge/OTelBridgeRunContext.js +124 -0
  127. package/lib/opentelemetry-bridge/OTelContextManager.js +82 -0
  128. package/lib/opentelemetry-bridge/OTelSpan.js +344 -0
  129. package/lib/opentelemetry-bridge/OTelTracer.js +201 -0
  130. package/lib/opentelemetry-bridge/OTelTracerProvider.js +25 -0
  131. package/lib/opentelemetry-bridge/README.md +244 -0
  132. package/lib/opentelemetry-bridge/index.js +15 -0
  133. package/lib/opentelemetry-bridge/oblog.js +23 -0
  134. package/lib/opentelemetry-bridge/opentelemetry-core-mini/README.md +3 -0
  135. package/lib/opentelemetry-bridge/opentelemetry-core-mini/internal/validators.js +52 -0
  136. package/lib/opentelemetry-bridge/opentelemetry-core-mini/trace/TraceState.js +109 -0
  137. package/lib/opentelemetry-bridge/otelutils.js +99 -0
  138. package/lib/opentelemetry-bridge/setup.js +76 -0
  139. package/lib/opentelemetry-metrics/ElasticApmMetricExporter.js +285 -0
  140. package/lib/opentelemetry-metrics/index.js +50 -0
  141. package/lib/parsers.js +225 -0
  142. package/lib/propwrap.js +147 -0
  143. package/lib/stacktraces.js +537 -0
  144. package/lib/symbols.js +15 -0
  145. package/lib/tracecontext/index.js +118 -0
  146. package/lib/tracecontext/traceparent.js +185 -0
  147. package/lib/tracecontext/tracestate.js +388 -0
  148. package/lib/wildcard-matcher.js +52 -0
  149. package/loader.mjs +7 -0
  150. package/package.json +299 -0
  151. package/start.d.ts +8 -0
  152. package/start.js +29 -0
  153. package/types/aws-lambda.d.ts +98 -0
  154. package/types/connect.d.ts +23 -0
@@ -0,0 +1,424 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and other contributors where applicable.
3
+ * Licensed under the BSD 2-Clause License; you may not use this file except in
4
+ * compliance with the BSD 2-Clause License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ var { URL, urlToHttpOptions } = require('url');
10
+
11
+ var endOfStream = require('end-of-stream');
12
+ const semver = require('semver');
13
+
14
+ var { getHTTPDestination } = require('./context');
15
+
16
+ const transactionForResponse = new WeakMap();
17
+ exports.transactionForResponse = transactionForResponse;
18
+
19
+ const nodeHttpRequestSupportsSeparateUrlArg = semver.gte(
20
+ process.version,
21
+ '10.9.0',
22
+ );
23
+
24
+ /**
25
+ * safeUrlToHttpOptions is a version of `urlToHttpOptions` -- available in
26
+ * later Node.js versions (https://nodejs.org/api/all.html#all_url_urlurltohttpoptionsurl)
27
+ * -- where the returned object is made "safe" to use as the `options` argument
28
+ * to `http.request()` and `https.request()`.
29
+ *
30
+ * By "safe" here we mean that it will not accidentally be considered a `url`
31
+ * argument. This matters in the instrumentation below because the following are
32
+ * handled differently:
33
+ * http.request(<options>, 'this is a bogus callback')
34
+ * http.request(<url>, 'this is a bogus callback')
35
+ */
36
+ let safeUrlToHttpOptions;
37
+ if (!urlToHttpOptions) {
38
+ // Adapted from https://github.com/nodejs/node/blob/v18.13.0/lib/internal/url.js#L1408-L1431
39
+ // Added in: v15.7.0, v14.18.0.
40
+ safeUrlToHttpOptions = function (url) {
41
+ const options = {
42
+ protocol: url.protocol,
43
+ hostname:
44
+ typeof url.hostname === 'string' &&
45
+ String.prototype.startsWith(url.hostname, '[')
46
+ ? String.prototype.slice(url.hostname, 1, -1)
47
+ : url.hostname,
48
+ hash: url.hash,
49
+ search: url.search,
50
+ pathname: url.pathname,
51
+ path: `${url.pathname || ''}${url.search || ''}`,
52
+ href: url.href,
53
+ };
54
+ if (url.port !== '') {
55
+ options.port = Number(url.port);
56
+ }
57
+ if (url.username || url.password) {
58
+ options.auth = `${decodeURIComponent(url.username)}:${decodeURIComponent(
59
+ url.password,
60
+ )}`;
61
+ }
62
+ return options;
63
+ };
64
+ } else if (
65
+ semver.satisfies(process.version, '>=19.9.0 <20') ||
66
+ semver.satisfies(process.version, '>=18.17.0 <19')
67
+ ) {
68
+ // Starting in node v19.9.0 (as of https://github.com/nodejs/node/pull/46989)
69
+ // `urlToHttpOptions(url)` returns an object which is considered a `url`
70
+ // argument by `http.request()` -- because of the internal `isURL(url)` test.
71
+ // Starting with node v18.17.0, the same is true with the internal switch
72
+ // to the "Ada" lib for URL parsing.
73
+ safeUrlToHttpOptions = function (url) {
74
+ const options = urlToHttpOptions(url);
75
+ // Specifically we are dropping the `Symbol(context)` field.
76
+ Object.getOwnPropertySymbols(options).forEach((sym) => {
77
+ delete options[sym];
78
+ });
79
+ return options;
80
+ };
81
+ } else if (
82
+ semver.satisfies(process.version, '>=20', { includePrerelease: true })
83
+ ) {
84
+ // This only works for versions of node v20 after
85
+ // https://github.com/nodejs/node/pull/47339 which changed the internal
86
+ // `isURL()` to duck-type test for the `href` field. `href` isn't an option
87
+ // to `http.request()` so there is no harm in dropping it.
88
+ safeUrlToHttpOptions = function (url) {
89
+ const options = urlToHttpOptions(url);
90
+ delete options.href;
91
+ return options;
92
+ };
93
+ } else {
94
+ safeUrlToHttpOptions = urlToHttpOptions;
95
+ }
96
+
97
+ exports.instrumentRequest = function (agent, moduleName) {
98
+ var ins = agent._instrumentation;
99
+ return function (orig) {
100
+ return function (event, req, res) {
101
+ if (event === 'request') {
102
+ agent.logger.debug(
103
+ 'intercepted request event call to %s.Server.prototype.emit for %s',
104
+ moduleName,
105
+ req.url,
106
+ );
107
+
108
+ if (shouldIgnoreRequest(agent, req)) {
109
+ agent.logger.debug('ignoring request to %s', req.url);
110
+ // Don't leak previous transaction.
111
+ agent._instrumentation.supersedeWithEmptyRunContext();
112
+ } else {
113
+ // Decide whether to use trace-context headers, if any, for a
114
+ // distributed trace.
115
+ const traceparent =
116
+ req.headers.traceparent || req.headers['elastic-apm-traceparent'];
117
+ const tracestate = req.headers.tracestate;
118
+ const trans = agent.startTransaction(null, null, {
119
+ childOf: traceparent,
120
+ tracestate,
121
+ });
122
+ trans.type = 'request';
123
+ trans.req = req;
124
+ trans.res = res;
125
+
126
+ transactionForResponse.set(res, trans);
127
+
128
+ ins.bindEmitter(req);
129
+ ins.bindEmitter(res);
130
+
131
+ endOfStream(res, function (err) {
132
+ if (trans.ended) return;
133
+ if (!err) return trans.end();
134
+
135
+ if (agent._conf.errorOnAbortedRequests) {
136
+ var duration = trans._timer.elapsed();
137
+ if (duration > agent._conf.abortedErrorThreshold * 1000) {
138
+ agent.captureError(
139
+ 'Socket closed with active HTTP request (>' +
140
+ agent._conf.abortedErrorThreshold +
141
+ ' sec)',
142
+ {
143
+ request: req,
144
+ extra: { abortTime: duration },
145
+ },
146
+ );
147
+ }
148
+ }
149
+
150
+ // Handle case where res.end is called after an error occurred on the
151
+ // stream (e.g. if the underlying socket was prematurely closed)
152
+ const end = res.end;
153
+ res.end = function () {
154
+ const result = end.apply(this, arguments);
155
+ trans.end();
156
+ return result;
157
+ };
158
+ });
159
+ }
160
+ }
161
+
162
+ return orig.apply(this, arguments);
163
+ };
164
+ };
165
+ };
166
+
167
+ function shouldIgnoreRequest(agent, req) {
168
+ var i;
169
+
170
+ for (i = 0; i < agent._conf.ignoreUrlStr.length; i++) {
171
+ if (agent._conf.ignoreUrlStr[i] === req.url) return true;
172
+ }
173
+ for (i = 0; i < agent._conf.ignoreUrlRegExp.length; i++) {
174
+ if (agent._conf.ignoreUrlRegExp[i].test(req.url)) return true;
175
+ }
176
+ for (i = 0; i < agent._conf.transactionIgnoreUrlRegExp.length; i++) {
177
+ if (agent._conf.transactionIgnoreUrlRegExp[i].test(req.url)) return true;
178
+ }
179
+
180
+ var ua = req.headers['user-agent'];
181
+ if (!ua) return false;
182
+
183
+ for (i = 0; i < agent._conf.ignoreUserAgentStr.length; i++) {
184
+ if (ua.indexOf(agent._conf.ignoreUserAgentStr[i]) === 0) return true;
185
+ }
186
+ for (i = 0; i < agent._conf.ignoreUserAgentRegExp.length; i++) {
187
+ if (agent._conf.ignoreUserAgentRegExp[i].test(ua)) return true;
188
+ }
189
+
190
+ return false;
191
+ }
192
+
193
+ /**
194
+ * Safely get the Host header used in the given client request without incurring
195
+ * the core Node.js DEP0066 warning for using `req._headers`.
196
+ *
197
+ * @param {http.ClientRequest} req
198
+ * @returns {string}
199
+ */
200
+ function getSafeHost(req) {
201
+ return req.getHeader ? req.getHeader('Host') : req._headers.host;
202
+ }
203
+
204
+ exports.traceOutgoingRequest = function (agent, moduleName, method) {
205
+ var ins = agent._instrumentation;
206
+
207
+ return function wrapHttpRequest(orig) {
208
+ return function wrappedHttpRequest(input, options, cb) {
209
+ const parentRunContext = ins.currRunContext();
210
+ var span = ins.createSpan(null, 'external', 'http', { exitSpan: true });
211
+ var id = span && span.transaction.id;
212
+ agent.logger.debug('intercepted call to %s.%s %o', moduleName, method, {
213
+ id,
214
+ });
215
+
216
+ // Reproduce the argument handling from node/lib/_http_client.js#ClientRequest().
217
+ //
218
+ // The `new URL(...)` calls in this block *could* throw INVALID_URL, but
219
+ // that would happen anyway when calling `orig(...)`. The only slight
220
+ // downside is that the Error stack won't originate inside "_http_client.js".
221
+ if (!nodeHttpRequestSupportsSeparateUrlArg) {
222
+ // Signature from node <10.9.0:
223
+ // http.request(options[, callback])
224
+ // options <Object> | <string> | <URL>
225
+ cb = options;
226
+ options = input;
227
+ if (typeof options === 'string') {
228
+ options = safeUrlToHttpOptions(new URL(options));
229
+ } else if (options instanceof URL) {
230
+ options = safeUrlToHttpOptions(options);
231
+ } else {
232
+ options = Object.assign({}, options);
233
+ }
234
+ } else {
235
+ // Signature from node >=10.9.0:
236
+ // http.request(options[, callback])
237
+ // http.request(url[, options][, callback])
238
+ // url <string> | <URL>
239
+ // options <Object>
240
+ if (typeof input === 'string') {
241
+ input = safeUrlToHttpOptions(new URL(input));
242
+ } else if (input instanceof URL) {
243
+ input = safeUrlToHttpOptions(input);
244
+ } else {
245
+ cb = options;
246
+ options = input;
247
+ input = null;
248
+ }
249
+
250
+ if (typeof options === 'function') {
251
+ cb = options;
252
+ options = input || {};
253
+ } else {
254
+ options = Object.assign(input || {}, options);
255
+ }
256
+ }
257
+
258
+ const newArgs = [options];
259
+ if (cb !== undefined) {
260
+ if (typeof cb === 'function') {
261
+ newArgs.push(ins.bindFunctionToRunContext(parentRunContext, cb));
262
+ } else {
263
+ newArgs.push(cb);
264
+ }
265
+ }
266
+
267
+ // W3C trace-context propagation.
268
+ // There are a number of reasons why `span` might be null: child of an
269
+ // exit span, `transactionMaxSpans` was hit, unsampled transaction, etc.
270
+ // If so, then fallback to the current run context's span or transaction,
271
+ // if any.
272
+ const parent =
273
+ span ||
274
+ parentRunContext.currSpan() ||
275
+ parentRunContext.currTransaction();
276
+ if (parent) {
277
+ const headers = Object.assign({}, options.headers);
278
+ parent.propagateTraceContextHeaders(
279
+ headers,
280
+ function (carrier, name, value) {
281
+ carrier[name] = value;
282
+ },
283
+ );
284
+ options.headers = headers;
285
+ }
286
+
287
+ if (!span) {
288
+ return orig.apply(this, newArgs);
289
+ }
290
+
291
+ const spanRunContext = parentRunContext.enterSpan(span);
292
+ var req = ins.withRunContext(spanRunContext, orig, this, ...newArgs);
293
+
294
+ var protocol = req.agent && req.agent.protocol;
295
+ agent.logger.debug('request details: %o', {
296
+ protocol,
297
+ host: getSafeHost(req),
298
+ id,
299
+ });
300
+
301
+ ins.bindEmitter(req);
302
+
303
+ span.action = req.method;
304
+ span.name = req.method + ' ' + getSafeHost(req);
305
+
306
+ // TODO: Research if it's possible to add this to the prototype instead.
307
+ // Or if it's somehow preferable to listen for when a `response` listener
308
+ // is added instead of when `response` is emitted.
309
+ const emit = req.emit;
310
+ req.emit = function wrappedEmit(type, res) {
311
+ if (type === 'response') onResponse(res);
312
+ if (type === 'abort') onAbort(type);
313
+ return emit.apply(req, arguments);
314
+ };
315
+
316
+ const url = getUrlFromRequestAndOptions(req, options, moduleName + ':');
317
+ if (!url) {
318
+ agent.logger.warn('unable to identify http.ClientRequest url %o', {
319
+ id,
320
+ });
321
+ }
322
+ let statusCode;
323
+ return req;
324
+
325
+ // In case the request is ended prematurely
326
+ function onAbort(type) {
327
+ if (span.ended) return;
328
+ agent.logger.debug('intercepted http.ClientRequest abort event %o', {
329
+ id,
330
+ });
331
+
332
+ onEnd();
333
+ }
334
+
335
+ function onEnd() {
336
+ span.setHttpContext({
337
+ method: req.method,
338
+ status_code: statusCode,
339
+ url,
340
+ });
341
+
342
+ // Add destination info only when socket conn is established
343
+ if (url) {
344
+ // The `getHTTPDestination` function might throw in case an
345
+ // invalid URL is given to the `URL()` function. Until we can
346
+ // be 100% sure this doesn't happen, we better catch it here.
347
+ // For details, see:
348
+ // https://github.com/elastic/apm-agent-nodejs/issues/1769
349
+ try {
350
+ span._setDestinationContext(getHTTPDestination(url));
351
+ } catch (e) {
352
+ agent.logger.error(
353
+ 'Could not set destination context: %s',
354
+ e.message,
355
+ );
356
+ }
357
+ }
358
+
359
+ span._setOutcomeFromHttpStatusCode(statusCode);
360
+ span.end();
361
+ }
362
+
363
+ function onResponse(res) {
364
+ agent.logger.debug('intercepted http.ClientRequest response event %o', {
365
+ id,
366
+ });
367
+ ins.bindEmitterToRunContext(parentRunContext, res);
368
+ statusCode = res.statusCode;
369
+ res.prependListener('end', function () {
370
+ agent.logger.debug('intercepted http.IncomingMessage end event %o', {
371
+ id,
372
+ });
373
+ onEnd();
374
+ });
375
+ }
376
+ };
377
+ };
378
+ };
379
+
380
+ // Creates a sanitized URL suitable for the span's HTTP context
381
+ //
382
+ // This function reconstructs a URL using the request object's properties
383
+ // where it can (node versions v14.5.0, v12.19.0 and later), and falling
384
+ // back to the options where it can not. This function also strips any
385
+ // authentication information provided with the hostname. In other words
386
+ //
387
+ // http://username:password@example.com/foo
388
+ //
389
+ // becomes http://example.com/foo
390
+ //
391
+ // NOTE: The options argument may not be the same options that are passed
392
+ // to http.request if the caller uses the the http.request(url,options,...)
393
+ // method signature. The agent normalizes the url and options into a single
394
+ // options object. This function expects those pre-normalized options.
395
+ //
396
+ // @param {ClientRequest} req
397
+ // @param {object} options
398
+ // @param {string} fallbackProtocol
399
+ // @return string|undefined
400
+ function getUrlFromRequestAndOptions(req, options, fallbackProtocol) {
401
+ if (!req) {
402
+ return undefined;
403
+ }
404
+ options = options || {};
405
+ req = req || {};
406
+ req.agent = req.agent || {};
407
+
408
+ if (isProxiedRequest(req)) {
409
+ return req.path;
410
+ }
411
+
412
+ const port = options.port ? `:${options.port}` : '';
413
+ // req.host and req.protocol are node versions v14.5.0/v12.19.0 and later
414
+ const host = req.host || options.hostname || options.host || 'localhost';
415
+ const protocol = req.protocol || req.agent.protocol || fallbackProtocol;
416
+
417
+ return `${protocol}//${host}${port}${req.path}`;
418
+ }
419
+
420
+ function isProxiedRequest(req) {
421
+ return req.path.indexOf('https:') === 0 || req.path.indexOf('http:') === 0;
422
+ }
423
+
424
+ exports.getUrlFromRequestAndOptions = getUrlFromRequestAndOptions;
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and other contributors where applicable.
3
+ * Licensed under the BSD 2-Clause License; you may not use this file except in
4
+ * compliance with the BSD 2-Clause License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { stringify } = require('querystring');
10
+
11
+ class Ids {
12
+ toString() {
13
+ return stringify(this, ' ', '=');
14
+ }
15
+ }
16
+
17
+ class SpanIds extends Ids {
18
+ constructor(span) {
19
+ super();
20
+ this['trace.id'] = span.traceId;
21
+ this['span.id'] = span.id;
22
+ Object.freeze(this);
23
+ }
24
+ }
25
+
26
+ class TransactionIds extends Ids {
27
+ constructor(transaction) {
28
+ super();
29
+ this['trace.id'] = transaction.traceId;
30
+ this['transaction.id'] = transaction.id;
31
+ Object.freeze(this);
32
+ }
33
+ }
34
+
35
+ module.exports = {
36
+ Ids,
37
+ SpanIds,
38
+ TransactionIds,
39
+ };