@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,63 @@
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
+ // Shared functionality between the instrumentations of:
10
+ // - elasticsearch - the legacy Elasticsearch JS client
11
+ // - @elastic/elasticsearch - the new Elasticsearch JS client
12
+
13
+ // Only capture the ES request body if the request path matches the
14
+ // `elasticsearchCaptureBodyUrls` config.
15
+ function shouldCaptureBody(path, elasticsearchCaptureBodyUrlsRegExp) {
16
+ if (!path) {
17
+ return false;
18
+ }
19
+ for (var i = 0; i < elasticsearchCaptureBodyUrlsRegExp.length; i++) {
20
+ const re = elasticsearchCaptureBodyUrlsRegExp[i];
21
+ if (re.test(path)) {
22
+ return true;
23
+ }
24
+ }
25
+ return false;
26
+ }
27
+
28
+ /**
29
+ * Get an appropriate `span.context.db.statement` for this ES client request, if any.
30
+ * https://github.com/elastic/apm/blob/main/specs/agents/tracing-instrumentation-db.md#elasticsearch_capture_body_urls-configuration
31
+ *
32
+ * @param {string | null} path
33
+ * @param {string | null} body
34
+ * @param {RegExp[]} elasticsearchCaptureBodyUrlsRegExp
35
+ * @return {string | undefined}
36
+ */
37
+ function getElasticsearchDbStatement(
38
+ path,
39
+ body,
40
+ elasticsearchCaptureBodyUrlsRegExp,
41
+ ) {
42
+ if (body && shouldCaptureBody(path, elasticsearchCaptureBodyUrlsRegExp)) {
43
+ if (typeof body === 'string') {
44
+ return body;
45
+ } else if (Buffer.isBuffer(body) || typeof body.pipe === 'function') {
46
+ // Never serialize a Buffer or a Readable. These guards mirror
47
+ // `shouldSerialize()` in the ES client, e.g.:
48
+ // https://github.com/elastic/elastic-transport-js/blob/069172506d1fcd544b23747d8c2d497bab053038/src/Transport.ts#L614-L618
49
+ } else if (Array.isArray(body)) {
50
+ try {
51
+ return body.map(JSON.stringify).join('\n') + '\n'; // ndjson
52
+ } catch (_ignoredErr) {}
53
+ } else if (typeof body === 'object') {
54
+ try {
55
+ return JSON.stringify(body);
56
+ } catch (_ignoredErr) {}
57
+ }
58
+ }
59
+ }
60
+
61
+ module.exports = {
62
+ getElasticsearchDbStatement,
63
+ };
@@ -0,0 +1,91 @@
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 url = require('url');
10
+
11
+ var symbols = require('../symbols');
12
+
13
+ function normalizeSlash(value) {
14
+ return value[0] === '/' ? value : '/' + value;
15
+ }
16
+
17
+ function excludeRoot(value) {
18
+ return value !== '/';
19
+ }
20
+
21
+ function join(parts) {
22
+ if (!parts) return;
23
+ return parts.filter(excludeRoot).map(normalizeSlash).join('') || '/';
24
+ }
25
+
26
+ // This works for both express AND restify
27
+ function routePath(route) {
28
+ if (!route) return;
29
+ return route.path || (route.regexp && route.regexp.source);
30
+ }
31
+
32
+ function getStackPath(req) {
33
+ var stack = req[symbols.expressMountStack];
34
+ return join(stack);
35
+ }
36
+
37
+ // This function is also able to extract the path from a Restify request as
38
+ // it's storing the route name on req.route.path as well
39
+ function getPathFromRequest(req, useBase, usePathAsTransactionName) {
40
+ if (req[symbols.staticFile]) {
41
+ return 'static file';
42
+ }
43
+
44
+ var path = getStackPath(req);
45
+ var route = routePath(req.route);
46
+
47
+ if (route) {
48
+ return path ? join([path, route]) : route;
49
+ } else if (path && (path !== '/' || useBase)) {
50
+ return path;
51
+ }
52
+
53
+ if (usePathAsTransactionName) {
54
+ // `req.url` is the "request-target" from the HTTP request line
55
+ // (https://www.rfc-editor.org/rfc/rfc7230#section-3.1.1). The special-case
56
+ // handling for leading '/' is because this:
57
+ // GET //foo/bar HTTP/1.1
58
+ // Host: example.com
59
+ // should result in:
60
+ // { host: 'example.com', pathname: '//foo/bar' }
61
+ // and *not*:
62
+ // { host: 'foo', pathname: '/bar' }
63
+ //
64
+ // Assuming 'http://' for the `base` URL is fine, because we don't use the
65
+ // protocol.
66
+ let base;
67
+ try {
68
+ // Host header may contain invalid characters therefore the URL
69
+ // parsing will fail and break the app. This try block is to avoid it
70
+ // Ref: https://github.com/elastic/apm-agent-nodejs/issues/3874
71
+ const url = new url.URL('http://' + (req.headers && req.headers.host));
72
+ base = 'http://' + url.hostname;
73
+ } catch (err) {
74
+ base = 'http://undefined';
75
+ }
76
+
77
+ // We may receive invalid chars in the path also but the URL
78
+ // constructor escapes them without throwing.
79
+ const parsed = req.url.startsWith('/')
80
+ ? new url.URL(base + req.url)
81
+ : new url.URL(req.url, base);
82
+
83
+ return parsed && parsed.pathname;
84
+ }
85
+ }
86
+
87
+ module.exports = {
88
+ getPathFromRequest,
89
+ getStackPath,
90
+ routePath,
91
+ };
@@ -0,0 +1,322 @@
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 truncate = require('unicode-byte-truncate');
10
+
11
+ const { INTAKE_STRING_MAX_SIZE } = require('../constants');
12
+ const constants = require('../constants');
13
+ const { SpanCompression } = require('./span-compression');
14
+ const Timer = require('./timer');
15
+ const TraceContext = require('../tracecontext');
16
+ const { TraceParent } = require('../tracecontext/traceparent');
17
+
18
+ module.exports = GenericSpan;
19
+
20
+ /**
21
+ * GenericSpan is an internal base class for Span and Transaction.
22
+ *
23
+ * @param {Agent} agent
24
+ * @param {Object} opts
25
+ * TODO: document supported opts
26
+ */
27
+ function GenericSpan(agent, opts) {
28
+ this._timer = new Timer(opts.timer, opts.startTime);
29
+
30
+ this._context = TraceContext.startOrResume(
31
+ opts.childOf,
32
+ agent._conf,
33
+ opts.tracestate,
34
+ );
35
+ this._hasPropagatedTraceContext = false;
36
+
37
+ this._parentSpan = null;
38
+ if (opts.childOf instanceof GenericSpan) {
39
+ this.setParentSpan(opts.childOf);
40
+ }
41
+ this._compression = new SpanCompression(agent);
42
+ this._compression.setBufferedSpan(null);
43
+
44
+ this._agent = agent;
45
+ this._labels = null;
46
+ this._ids = null; // Populated by sub-types of GenericSpan
47
+ this._otelKind = null;
48
+ this._otelAttributes = null;
49
+
50
+ this._links = [];
51
+ if (opts.links) {
52
+ for (let i = 0; i < opts.links.length; i++) {
53
+ const link = linkFromLinkArg(opts.links[i]);
54
+ if (link) {
55
+ this._links.push(link);
56
+ }
57
+ }
58
+ }
59
+
60
+ this.timestamp = this._timer.start;
61
+ this.ended = false;
62
+ this._duration = null; // Duration in milliseconds. Set on `.end()`.
63
+ this._endTimestamp = null;
64
+
65
+ this.outcome = constants.OUTCOME_UNKNOWN;
66
+
67
+ // Freezing the outcome allows us to prefer a value set from
68
+ // from the API and allows a span to keep its unknown status
69
+ // even if it succesfully ends.
70
+ this._isOutcomeFrozen = false;
71
+ }
72
+
73
+ Object.defineProperty(GenericSpan.prototype, 'id', {
74
+ enumerable: true,
75
+ get() {
76
+ return this._context.traceparent.id;
77
+ },
78
+ });
79
+
80
+ Object.defineProperty(GenericSpan.prototype, 'traceId', {
81
+ enumerable: true,
82
+ get() {
83
+ return this._context.traceparent.traceId;
84
+ },
85
+ });
86
+
87
+ Object.defineProperty(GenericSpan.prototype, 'parentId', {
88
+ enumerable: true,
89
+ get() {
90
+ return this._context.traceparent.parentId;
91
+ },
92
+ });
93
+
94
+ Object.defineProperty(GenericSpan.prototype, 'sampled', {
95
+ enumerable: true,
96
+ get() {
97
+ return this._context.traceparent.recorded;
98
+ },
99
+ });
100
+
101
+ Object.defineProperty(GenericSpan.prototype, 'sampleRate', {
102
+ enumerable: true,
103
+ get() {
104
+ const rate = parseFloat(this._context.tracestate.getValue('s'));
105
+ if (rate >= 0 && rate <= 1) {
106
+ return rate;
107
+ }
108
+ return null;
109
+ },
110
+ });
111
+
112
+ Object.defineProperty(GenericSpan.prototype, 'traceparent', {
113
+ enumerable: true,
114
+ get() {
115
+ return this._context.toString();
116
+ },
117
+ });
118
+
119
+ // The duration of the span, in milliseconds.
120
+ GenericSpan.prototype.duration = function () {
121
+ if (!this.ended) {
122
+ this._agent.logger.debug(
123
+ 'tried to call duration() on un-ended transaction/span %o',
124
+ {
125
+ id: this.id,
126
+ parent: this.parentId,
127
+ trace: this.traceId,
128
+ name: this.name,
129
+ type: this.type,
130
+ },
131
+ );
132
+ return null;
133
+ }
134
+
135
+ return this._duration;
136
+ };
137
+
138
+ // The 'stringify' option is for backward compatibility and will likely be
139
+ // removed in the next major version.
140
+ GenericSpan.prototype.setLabel = function (key, value, stringify = true) {
141
+ const makeLabelValue = () => {
142
+ if (
143
+ !stringify &&
144
+ (typeof value === 'boolean' || typeof value === 'number')
145
+ ) {
146
+ return value;
147
+ }
148
+
149
+ return truncate(String(value), INTAKE_STRING_MAX_SIZE);
150
+ };
151
+
152
+ if (!key) return false;
153
+ if (!this._labels) this._labels = {};
154
+ var skey = key.replace(/[.*"]/g, '_');
155
+ if (key !== skey) {
156
+ this._agent.logger.warn('Illegal characters used in tag key: %s', key);
157
+ }
158
+ this._labels[skey] = makeLabelValue();
159
+ return true;
160
+ };
161
+
162
+ GenericSpan.prototype.addLabels = function (labels, stringify) {
163
+ if (!labels) return false;
164
+ var keys = Object.keys(labels);
165
+ for (const key of keys) {
166
+ if (!this.setLabel(key, labels[key], stringify)) {
167
+ return false;
168
+ }
169
+ }
170
+ return true;
171
+ };
172
+
173
+ // Add span links.
174
+ //
175
+ // @param {Array} links - An array of objects with a `context` property that is
176
+ // a Transaction, Span, or TraceParent instance; an OTel SpanContext object;
177
+ // or a W3C trace-context 'traceparent' string.
178
+ GenericSpan.prototype.addLinks = function (links) {
179
+ if (links) {
180
+ for (let i = 0; i < links.length; i++) {
181
+ this.addLink(links[i]);
182
+ }
183
+ }
184
+ };
185
+
186
+ // Add a span link.
187
+ //
188
+ // @param {Link} link - An object with a `context` property that is
189
+ // a Transaction, Span, or TraceParent instance; an OTel SpanContext object;
190
+ // or a W3C trace-context 'traceparent' string.
191
+ GenericSpan.prototype.addLink = function (linkArg) {
192
+ const link = linkFromLinkArg(linkArg);
193
+ if (link) {
194
+ this._links.push(link);
195
+ }
196
+ };
197
+
198
+ GenericSpan.prototype._freezeOutcome = function () {
199
+ this._isOutcomeFrozen = true;
200
+ };
201
+
202
+ GenericSpan.prototype._isValidOutcome = function (outcome) {
203
+ return (
204
+ outcome === constants.OUTCOME_FAILURE ||
205
+ outcome === constants.OUTCOME_SUCCESS ||
206
+ outcome === constants.OUTCOME_UNKNOWN
207
+ );
208
+ };
209
+
210
+ GenericSpan.prototype.propagateTraceContextHeaders = function (
211
+ carrier,
212
+ setter,
213
+ ) {
214
+ this._hasPropagatedTraceContext = true;
215
+ return this._context.propagateTraceContextHeaders(carrier, setter);
216
+ };
217
+ GenericSpan.prototype.setParentSpan = function (span) {
218
+ this._parentSpan = span;
219
+ };
220
+
221
+ GenericSpan.prototype.getParentSpan = function (span) {
222
+ return this._parentSpan;
223
+ };
224
+
225
+ GenericSpan.prototype.getBufferedSpan = function () {
226
+ return this._compression.getBufferedSpan();
227
+ };
228
+
229
+ GenericSpan.prototype.setBufferedSpan = function (span) {
230
+ return this._compression.setBufferedSpan(span);
231
+ };
232
+
233
+ GenericSpan.prototype.isCompositeSameKind = function () {
234
+ return this._compression.isCompositeSameKind();
235
+ };
236
+
237
+ GenericSpan.prototype.isComposite = function () {
238
+ return this._compression.isComposite();
239
+ };
240
+
241
+ GenericSpan.prototype.getCompositeSum = function () {
242
+ return this._compression.composite.sum;
243
+ };
244
+
245
+ // https://github.com/elastic/apm/blob/main/specs/agents/tracing-api-otel.md#span-kind
246
+ // @param {String} kind
247
+ GenericSpan.prototype._setOTelKind = function (kind) {
248
+ this._otelKind = kind;
249
+ };
250
+
251
+ // This returns the internal OTel attributes object so it can be mutated.
252
+ GenericSpan.prototype._getOTelAttributes = function () {
253
+ if (!this._otelAttributes) {
254
+ this._otelAttributes = {};
255
+ }
256
+ return this._otelAttributes;
257
+ };
258
+
259
+ // Serialize OTel-related fields into the given payload, if any.
260
+ GenericSpan.prototype._serializeOTel = function (payload) {
261
+ if (this._otelKind) {
262
+ payload.otel = {
263
+ span_kind: this._otelKind,
264
+ };
265
+ }
266
+
267
+ if (this._otelAttributes) {
268
+ // Though the spec allows it ("MAY"), we are opting *not* to report OTel
269
+ // span attributes as labels for older (<7.16) versions of APM server.
270
+ // This is to avoid the added complexity of guarding allowed attribute
271
+ // value types to those supported by the APM server intake API.
272
+ if (!payload.otel) {
273
+ payload.otel = {};
274
+ }
275
+
276
+ payload.otel.attributes = this._otelAttributes;
277
+ }
278
+ };
279
+
280
+ // Translate a `opts.links` entry (see the `Link` type in "index.d.ts") to a
281
+ // span link as it will be serialized and sent to APM server. If the linkArg is
282
+ // invalid, this will return null.
283
+ //
284
+ // @param {Object} linkArg - An object with a `context` property that is
285
+ // a Transaction, Span, or TraceParent instance; an OTel SpanContext object;
286
+ // or a W3C trace-context 'traceparent' string.
287
+ function linkFromLinkArg(linkArg) {
288
+ if (!linkArg || !linkArg.context) {
289
+ return null;
290
+ }
291
+
292
+ const ctx = linkArg.context;
293
+ let traceId;
294
+ let spanId;
295
+
296
+ if (ctx.traceId && ctx.spanId) {
297
+ // Duck-typing for an OTel SpanContext. APM intake v2 only supports the
298
+ // trace id and span id fields for span links, so we only need care about
299
+ // those attributes.
300
+ traceId = ctx.traceId;
301
+ spanId = ctx.spanId;
302
+ } else if (ctx._context instanceof TraceContext) {
303
+ // Transaction or Span
304
+ traceId = ctx._context.traceparent.traceId;
305
+ spanId = ctx._context.traceparent.id;
306
+ } else if (ctx instanceof TraceParent) {
307
+ traceId = ctx.traceId;
308
+ spanId = ctx.id;
309
+ } else if (typeof ctx === 'string') {
310
+ // Note: Unfortunately TraceParent.fromString doesn't validate the string.
311
+ const traceparent = TraceParent.fromString(ctx);
312
+ traceId = traceparent.traceId;
313
+ spanId = traceparent.id;
314
+ } else {
315
+ return null;
316
+ }
317
+
318
+ return {
319
+ trace_id: traceId,
320
+ span_id: spanId,
321
+ };
322
+ }