@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.
- package/LICENSE +26 -0
- package/NOTICE.md +442 -0
- package/README.md +48 -0
- package/changes.json +78 -0
- package/index.d.ts +398 -0
- package/index.js +11 -0
- package/lib/InflightEventSet.js +53 -0
- package/lib/activation-method.js +119 -0
- package/lib/agent.js +941 -0
- package/lib/apm-client/apm-client.js +313 -0
- package/lib/apm-client/http-apm-client/CHANGELOG.md +271 -0
- package/lib/apm-client/http-apm-client/README.md +485 -0
- package/lib/apm-client/http-apm-client/central-config.js +41 -0
- package/lib/apm-client/http-apm-client/container-info.js +111 -0
- package/lib/apm-client/http-apm-client/detect-hostname.js +96 -0
- package/lib/apm-client/http-apm-client/index.js +1975 -0
- package/lib/apm-client/http-apm-client/logging.js +31 -0
- package/lib/apm-client/http-apm-client/ndjson.js +20 -0
- package/lib/apm-client/http-apm-client/truncate.js +434 -0
- package/lib/apm-client/noop-apm-client.js +73 -0
- package/lib/async-hooks-polyfill.js +58 -0
- package/lib/cloud-metadata/aws.js +175 -0
- package/lib/cloud-metadata/azure.js +123 -0
- package/lib/cloud-metadata/callback-coordination.js +159 -0
- package/lib/cloud-metadata/gcp.js +133 -0
- package/lib/cloud-metadata/index.js +175 -0
- package/lib/config/config.js +458 -0
- package/lib/config/normalizers.js +701 -0
- package/lib/config/schema.js +1007 -0
- package/lib/constants.js +35 -0
- package/lib/errors.js +303 -0
- package/lib/filters/sanitize-field-names.js +69 -0
- package/lib/http-request.js +249 -0
- package/lib/instrumentation/azure-functions.js +519 -0
- package/lib/instrumentation/context.js +56 -0
- package/lib/instrumentation/dropped-spans-stats.js +112 -0
- package/lib/instrumentation/elasticsearch-shared.js +63 -0
- package/lib/instrumentation/express-utils.js +91 -0
- package/lib/instrumentation/generic-span.js +322 -0
- package/lib/instrumentation/http-shared.js +424 -0
- package/lib/instrumentation/ids.js +39 -0
- package/lib/instrumentation/index.js +1127 -0
- package/lib/instrumentation/modules/@apollo/server.js +30 -0
- package/lib/instrumentation/modules/@aws-sdk/client-dynamodb.js +143 -0
- package/lib/instrumentation/modules/@aws-sdk/client-s3.js +230 -0
- package/lib/instrumentation/modules/@aws-sdk/client-sns.js +197 -0
- package/lib/instrumentation/modules/@aws-sdk/client-sqs.js +336 -0
- package/lib/instrumentation/modules/@elastic/elasticsearch.js +343 -0
- package/lib/instrumentation/modules/@hapi/hapi.js +221 -0
- package/lib/instrumentation/modules/@opentelemetry/api.js +86 -0
- package/lib/instrumentation/modules/@opentelemetry/sdk-metrics.js +79 -0
- package/lib/instrumentation/modules/@redis/client/dist/lib/client/commands-queue.js +178 -0
- package/lib/instrumentation/modules/@redis/client/dist/lib/client/index.js +49 -0
- package/lib/instrumentation/modules/@smithy/smithy-client.js +198 -0
- package/lib/instrumentation/modules/_lambda-handler.js +40 -0
- package/lib/instrumentation/modules/apollo-server-core.js +49 -0
- package/lib/instrumentation/modules/aws-sdk/dynamodb.js +155 -0
- package/lib/instrumentation/modules/aws-sdk/s3.js +184 -0
- package/lib/instrumentation/modules/aws-sdk/sns.js +232 -0
- package/lib/instrumentation/modules/aws-sdk/sqs.js +361 -0
- package/lib/instrumentation/modules/aws-sdk.js +76 -0
- package/lib/instrumentation/modules/bluebird.js +93 -0
- package/lib/instrumentation/modules/cassandra-driver.js +280 -0
- package/lib/instrumentation/modules/elasticsearch.js +191 -0
- package/lib/instrumentation/modules/express-graphql.js +66 -0
- package/lib/instrumentation/modules/express-queue.js +28 -0
- package/lib/instrumentation/modules/express.js +162 -0
- package/lib/instrumentation/modules/fastify.js +172 -0
- package/lib/instrumentation/modules/finalhandler.js +41 -0
- package/lib/instrumentation/modules/generic-pool.js +85 -0
- package/lib/instrumentation/modules/graphql.js +256 -0
- package/lib/instrumentation/modules/handlebars.js +22 -0
- package/lib/instrumentation/modules/http.js +112 -0
- package/lib/instrumentation/modules/http2.js +320 -0
- package/lib/instrumentation/modules/https.js +68 -0
- package/lib/instrumentation/modules/ioredis.js +94 -0
- package/lib/instrumentation/modules/jade.js +18 -0
- package/lib/instrumentation/modules/kafkajs.js +476 -0
- package/lib/instrumentation/modules/knex.js +91 -0
- package/lib/instrumentation/modules/koa-router.js +74 -0
- package/lib/instrumentation/modules/koa.js +15 -0
- package/lib/instrumentation/modules/memcached.js +99 -0
- package/lib/instrumentation/modules/mimic-response.js +45 -0
- package/lib/instrumentation/modules/mongodb/lib/cmap/connection_pool.js +40 -0
- package/lib/instrumentation/modules/mongodb-core.js +206 -0
- package/lib/instrumentation/modules/mongodb.js +259 -0
- package/lib/instrumentation/modules/mysql.js +200 -0
- package/lib/instrumentation/modules/mysql2.js +140 -0
- package/lib/instrumentation/modules/pg.js +148 -0
- package/lib/instrumentation/modules/pug.js +18 -0
- package/lib/instrumentation/modules/redis.js +176 -0
- package/lib/instrumentation/modules/restify.js +52 -0
- package/lib/instrumentation/modules/tedious.js +159 -0
- package/lib/instrumentation/modules/undici.js +270 -0
- package/lib/instrumentation/modules/ws.js +59 -0
- package/lib/instrumentation/noop-transaction.js +81 -0
- package/lib/instrumentation/run-context/AbstractRunContextManager.js +215 -0
- package/lib/instrumentation/run-context/AsyncHooksRunContextManager.js +106 -0
- package/lib/instrumentation/run-context/AsyncLocalStorageRunContextManager.js +73 -0
- package/lib/instrumentation/run-context/BasicRunContextManager.js +82 -0
- package/lib/instrumentation/run-context/RunContext.js +151 -0
- package/lib/instrumentation/run-context/index.js +23 -0
- package/lib/instrumentation/shimmer.js +123 -0
- package/lib/instrumentation/span-compression.js +239 -0
- package/lib/instrumentation/span.js +621 -0
- package/lib/instrumentation/template-shared.js +43 -0
- package/lib/instrumentation/timer.js +84 -0
- package/lib/instrumentation/transaction.js +571 -0
- package/lib/lambda.js +992 -0
- package/lib/load-source-map.js +100 -0
- package/lib/logging.js +212 -0
- package/lib/metrics/index.js +92 -0
- package/lib/metrics/platforms/generic/index.js +40 -0
- package/lib/metrics/platforms/generic/process-cpu.js +22 -0
- package/lib/metrics/platforms/generic/process-top.js +157 -0
- package/lib/metrics/platforms/generic/stats.js +34 -0
- package/lib/metrics/platforms/generic/system-cpu.js +51 -0
- package/lib/metrics/platforms/linux/index.js +19 -0
- package/lib/metrics/platforms/linux/stats.js +213 -0
- package/lib/metrics/queue.js +90 -0
- package/lib/metrics/registry.js +52 -0
- package/lib/metrics/reporter.js +119 -0
- package/lib/metrics/runtime.js +77 -0
- package/lib/middleware/connect.js +16 -0
- package/lib/opentelemetry-bridge/OTelBridgeNonRecordingSpan.js +150 -0
- package/lib/opentelemetry-bridge/OTelBridgeRunContext.js +124 -0
- package/lib/opentelemetry-bridge/OTelContextManager.js +82 -0
- package/lib/opentelemetry-bridge/OTelSpan.js +344 -0
- package/lib/opentelemetry-bridge/OTelTracer.js +201 -0
- package/lib/opentelemetry-bridge/OTelTracerProvider.js +25 -0
- package/lib/opentelemetry-bridge/README.md +244 -0
- package/lib/opentelemetry-bridge/index.js +15 -0
- package/lib/opentelemetry-bridge/oblog.js +23 -0
- package/lib/opentelemetry-bridge/opentelemetry-core-mini/README.md +3 -0
- package/lib/opentelemetry-bridge/opentelemetry-core-mini/internal/validators.js +52 -0
- package/lib/opentelemetry-bridge/opentelemetry-core-mini/trace/TraceState.js +109 -0
- package/lib/opentelemetry-bridge/otelutils.js +99 -0
- package/lib/opentelemetry-bridge/setup.js +76 -0
- package/lib/opentelemetry-metrics/ElasticApmMetricExporter.js +285 -0
- package/lib/opentelemetry-metrics/index.js +50 -0
- package/lib/parsers.js +225 -0
- package/lib/propwrap.js +147 -0
- package/lib/stacktraces.js +537 -0
- package/lib/symbols.js +15 -0
- package/lib/tracecontext/index.js +118 -0
- package/lib/tracecontext/traceparent.js +185 -0
- package/lib/tracecontext/tracestate.js +388 -0
- package/lib/wildcard-matcher.js +52 -0
- package/loader.mjs +7 -0
- package/package.json +299 -0
- package/start.d.ts +8 -0
- package/start.js +29 -0
- package/types/aws-lambda.d.ts +98 -0
- package/types/connect.d.ts +23 -0
|
@@ -0,0 +1,621 @@
|
|
|
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 { executionAsyncId } = require('async_hooks');
|
|
10
|
+
const { URL } = require('url');
|
|
11
|
+
var util = require('util');
|
|
12
|
+
|
|
13
|
+
var Value = require('async-value-promise');
|
|
14
|
+
|
|
15
|
+
const constants = require('../constants');
|
|
16
|
+
var GenericSpan = require('./generic-span');
|
|
17
|
+
var { SpanIds } = require('./ids');
|
|
18
|
+
const { gatherStackTrace } = require('../stacktraces');
|
|
19
|
+
|
|
20
|
+
const TEST = process.env.ELASTIC_APM_TEST;
|
|
21
|
+
|
|
22
|
+
module.exports = Span;
|
|
23
|
+
|
|
24
|
+
util.inherits(Span, GenericSpan);
|
|
25
|
+
|
|
26
|
+
// new Span(transaction)
|
|
27
|
+
// new Span(transaction, name?, opts?)
|
|
28
|
+
// new Span(transaction, name?, type?, opts?)
|
|
29
|
+
// new Span(transaction, name?, type?, subtype?, opts?)
|
|
30
|
+
// new Span(transaction, name?, type?, subtype?, action?, opts?)
|
|
31
|
+
function Span(transaction, ...args) {
|
|
32
|
+
const opts =
|
|
33
|
+
typeof args[args.length - 1] === 'object' ? args.pop() || {} : {};
|
|
34
|
+
const [name, ...tsaArgs] = args; // "tsa" === Type, Subtype, Action
|
|
35
|
+
|
|
36
|
+
if (opts.timer) {
|
|
37
|
+
// Before 4.x this option could be passed in. It was never publicly documented.
|
|
38
|
+
delete opts.timer;
|
|
39
|
+
}
|
|
40
|
+
if (!opts.childOf) {
|
|
41
|
+
const defaultChildOf =
|
|
42
|
+
transaction._agent._instrumentation.currSpan() || transaction;
|
|
43
|
+
opts.childOf = defaultChildOf;
|
|
44
|
+
opts.timer = defaultChildOf._timer;
|
|
45
|
+
} else if (opts.childOf._timer) {
|
|
46
|
+
opts.timer = opts.childOf._timer;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this._exitSpan = !!opts.exitSpan;
|
|
50
|
+
this.discardable = this._exitSpan;
|
|
51
|
+
|
|
52
|
+
delete opts.exitSpan;
|
|
53
|
+
|
|
54
|
+
this.type = null;
|
|
55
|
+
this.subtype = null;
|
|
56
|
+
this.action = null;
|
|
57
|
+
this.setType(...tsaArgs);
|
|
58
|
+
|
|
59
|
+
GenericSpan.call(this, transaction._agent, opts);
|
|
60
|
+
|
|
61
|
+
this._db = null;
|
|
62
|
+
this._http = null;
|
|
63
|
+
this._destination = null;
|
|
64
|
+
this._serviceTarget = null;
|
|
65
|
+
this._excludeServiceTarget = false;
|
|
66
|
+
this._message = null;
|
|
67
|
+
this._stackObj = null;
|
|
68
|
+
this._capturedStackTrace = null;
|
|
69
|
+
this.sync = true;
|
|
70
|
+
this._startXid = executionAsyncId();
|
|
71
|
+
|
|
72
|
+
this.transaction = transaction;
|
|
73
|
+
this.name = name || 'unnamed';
|
|
74
|
+
|
|
75
|
+
if (this._agent._conf.spanStackTraceMinDuration >= 0) {
|
|
76
|
+
this._recordStackTrace();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this._agent.logger.debug('start span %o', {
|
|
80
|
+
span: this.id,
|
|
81
|
+
parent: this.parentId,
|
|
82
|
+
trace: this.traceId,
|
|
83
|
+
name: this.name,
|
|
84
|
+
type: this.type,
|
|
85
|
+
subtype: this.subtype,
|
|
86
|
+
action: this.action,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
Object.defineProperty(Span.prototype, 'ids', {
|
|
91
|
+
get() {
|
|
92
|
+
return this._ids === null ? (this._ids = new SpanIds(this)) : this._ids;
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
Span.prototype.setType = function (type = null, subtype = null, action = null) {
|
|
97
|
+
this.type = type || constants.DEFAULT_SPAN_TYPE;
|
|
98
|
+
this.subtype = subtype;
|
|
99
|
+
this.action = action;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/*
|
|
103
|
+
* A string representation of the span to help with internal debugging. This
|
|
104
|
+
* is not a promised interface.
|
|
105
|
+
*/
|
|
106
|
+
Span.prototype.toString = function () {
|
|
107
|
+
return `Span(${this.id}, '${this.name}'${this.ended ? ', ended' : ''})`;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
Span.prototype.customStackTrace = function (stackObj) {
|
|
111
|
+
this._agent.logger.debug('applying custom stack trace to span %o', {
|
|
112
|
+
span: this.id,
|
|
113
|
+
parent: this.parentId,
|
|
114
|
+
trace: this.traceId,
|
|
115
|
+
});
|
|
116
|
+
this._recordStackTrace(stackObj);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
Span.prototype.end = function (endTime) {
|
|
120
|
+
if (this.ended) {
|
|
121
|
+
this._agent.logger.debug(
|
|
122
|
+
'tried to call span.end() on already ended span %o',
|
|
123
|
+
{
|
|
124
|
+
span: this.id,
|
|
125
|
+
parent: this.parentId,
|
|
126
|
+
trace: this.traceId,
|
|
127
|
+
name: this.name,
|
|
128
|
+
type: this.type,
|
|
129
|
+
subtype: this.subtype,
|
|
130
|
+
action: this.action,
|
|
131
|
+
},
|
|
132
|
+
);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
this._timer.end(endTime);
|
|
137
|
+
this._endTimestamp = this._timer.endTimestamp;
|
|
138
|
+
this._duration = this._timer.duration;
|
|
139
|
+
if (executionAsyncId() !== this._startXid) {
|
|
140
|
+
this.sync = false;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this._setOutcomeFromSpanEnd();
|
|
144
|
+
|
|
145
|
+
this._inferServiceTargetAndDestinationService();
|
|
146
|
+
|
|
147
|
+
this.ended = true;
|
|
148
|
+
this._agent.logger.debug('ended span %o', {
|
|
149
|
+
span: this.id,
|
|
150
|
+
parent: this.parentId,
|
|
151
|
+
trace: this.traceId,
|
|
152
|
+
name: this.name,
|
|
153
|
+
type: this.type,
|
|
154
|
+
subtype: this.subtype,
|
|
155
|
+
action: this.action,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
if (
|
|
159
|
+
this._capturedStackTrace !== null &&
|
|
160
|
+
this._agent._conf.spanStackTraceMinDuration >= 0 &&
|
|
161
|
+
this._duration / 1000 >= this._agent._conf.spanStackTraceMinDuration
|
|
162
|
+
) {
|
|
163
|
+
// NOTE: This uses a promise-like thing and not a *real* promise
|
|
164
|
+
// because passing error stacks into a promise context makes it
|
|
165
|
+
// uncollectable by the garbage collector.
|
|
166
|
+
this._stackObj = new Value();
|
|
167
|
+
var self = this;
|
|
168
|
+
gatherStackTrace(
|
|
169
|
+
this._agent.logger,
|
|
170
|
+
this._capturedStackTrace,
|
|
171
|
+
this._agent._conf.sourceLinesSpanAppFrames,
|
|
172
|
+
this._agent._conf.sourceLinesSpanLibraryFrames,
|
|
173
|
+
TEST ? null : filterCallSite,
|
|
174
|
+
function (_err, stacktrace) {
|
|
175
|
+
// _err from gatherStackTrace is always null.
|
|
176
|
+
self._stackObj.resolve(stacktrace);
|
|
177
|
+
},
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
this._agent._instrumentation.addEndedSpan(this);
|
|
182
|
+
this.transaction._captureBreakdown(this);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
Span.prototype._inferServiceTargetAndDestinationService = function () {
|
|
186
|
+
// `context.service.target.*` must be set for exit spans. There is a public
|
|
187
|
+
// `span.setServiceTarget(...)` for users to manually set this, but typically
|
|
188
|
+
// it is inferred from other span fields here.
|
|
189
|
+
// https://github.com/elastic/apm/blob/main/specs/agents/tracing-spans-service-target.md#field-values
|
|
190
|
+
if (this._excludeServiceTarget || !this._exitSpan) {
|
|
191
|
+
this._serviceTarget = null;
|
|
192
|
+
} else {
|
|
193
|
+
if (!this._serviceTarget) {
|
|
194
|
+
this._serviceTarget = {};
|
|
195
|
+
}
|
|
196
|
+
if (!('type' in this._serviceTarget)) {
|
|
197
|
+
this._serviceTarget.type =
|
|
198
|
+
this.subtype || this.type || constants.DEFAULT_SPAN_TYPE;
|
|
199
|
+
}
|
|
200
|
+
if (!('name' in this._serviceTarget)) {
|
|
201
|
+
if (this._db) {
|
|
202
|
+
if (this._db.instance) {
|
|
203
|
+
this._serviceTarget.name = this._db.instance;
|
|
204
|
+
}
|
|
205
|
+
} else if (this._message) {
|
|
206
|
+
if (this._message.queue && this._message.queue.name) {
|
|
207
|
+
this._serviceTarget.name = this._message.queue.name;
|
|
208
|
+
}
|
|
209
|
+
} else if (this._http && this._http.url) {
|
|
210
|
+
try {
|
|
211
|
+
const defaultPorts = { 'https:': '443', 'http:': '80' };
|
|
212
|
+
const url = new URL(this._http.url);
|
|
213
|
+
if (!url.port && defaultPorts[url.protocol]) {
|
|
214
|
+
this._serviceTarget.name = `${url.host}:${
|
|
215
|
+
defaultPorts[url.protocol]
|
|
216
|
+
}`;
|
|
217
|
+
} else {
|
|
218
|
+
this._serviceTarget.name = url.host;
|
|
219
|
+
}
|
|
220
|
+
} catch (invalidUrlErr) {
|
|
221
|
+
this._agent.logger.debug(
|
|
222
|
+
'cannot set "service.target.name": %s (ignoring)',
|
|
223
|
+
invalidUrlErr,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// `destination.service.*` is deprecated, but still required for older
|
|
230
|
+
// APM servers.
|
|
231
|
+
if (!this._destination) {
|
|
232
|
+
this._destination = {};
|
|
233
|
+
}
|
|
234
|
+
if (!this._destination.service) {
|
|
235
|
+
this._destination.service = {};
|
|
236
|
+
}
|
|
237
|
+
// - `destination.service.{type,name}` could be skipped if the upstream APM server is known to be >=7.14.
|
|
238
|
+
this._destination.service.type = '';
|
|
239
|
+
this._destination.service.name = '';
|
|
240
|
+
// - Infer the now deprecated `context.destination.service.resource` value.
|
|
241
|
+
// https://github.com/elastic/apm/blob/main/specs/agents/tracing-spans-destination.md#destination-resource
|
|
242
|
+
if (!this._destination.service.resource) {
|
|
243
|
+
if (!this._serviceTarget.name) {
|
|
244
|
+
// If we only have `.type`, then use that.
|
|
245
|
+
this._destination.service.resource = this._serviceTarget.type;
|
|
246
|
+
} else if (!this._serviceTarget.type) {
|
|
247
|
+
// If we only have `.name`, then use that.
|
|
248
|
+
this._destination.service.resource = this._serviceTarget.name;
|
|
249
|
+
} else if (this.type === 'external') {
|
|
250
|
+
// Typically the "resource" value would now be "$type/$name", e.g.
|
|
251
|
+
// "mysql/customers". However, we want a special case for some spans (to
|
|
252
|
+
// have the same value as historically?) where we do NOT use the
|
|
253
|
+
// "$type/" prefix. One example is HTTP spans. Another is gRPC spans
|
|
254
|
+
// and, I infer from otel_bridge.feature, any OTel "rpc.system"-usage
|
|
255
|
+
// spans as well
|
|
256
|
+
// (https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/rpc/).
|
|
257
|
+
// Options to infer this from other span data:
|
|
258
|
+
// - Use the presence of "http" context, but without "db" and "message"
|
|
259
|
+
// context. This is a little brittle, and requires more complete OTel
|
|
260
|
+
// bridge compatibility mapping of OTel attributes than is currently
|
|
261
|
+
// being done.
|
|
262
|
+
// } else if (!this._db && !this._message && this._http && this._http.url) {
|
|
263
|
+
// - Use `span.subtype`: "http", "grpc", ... add others if/when they are
|
|
264
|
+
// used.
|
|
265
|
+
// - Use `span.type === "external"`. This, at least currently corresponds.
|
|
266
|
+
// Let's use this one.
|
|
267
|
+
this._destination.service.resource = this._serviceTarget.name;
|
|
268
|
+
} else {
|
|
269
|
+
this._destination.service.resource = `${this._serviceTarget.type}/${this._serviceTarget.name}`;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
Span.prototype.setDbContext = function (context) {
|
|
276
|
+
if (!context) return;
|
|
277
|
+
this._db = Object.assign(this._db || {}, context);
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
Span.prototype.setHttpContext = function (context) {
|
|
281
|
+
if (!context) return;
|
|
282
|
+
this._http = Object.assign(this._http || {}, context);
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* This is deprecated and will be dropped in a future version. This was always
|
|
287
|
+
* an internal method, but possibly used by enterprising users of manual
|
|
288
|
+
* instrumentation.
|
|
289
|
+
*
|
|
290
|
+
* @deprecated Users should use the public `setServiceTarget()`.
|
|
291
|
+
* Internal APM agent code should use `_setDestinationContext()`.
|
|
292
|
+
*/
|
|
293
|
+
Span.prototype.setDestinationContext = function (destCtx) {
|
|
294
|
+
process.emitWarning(
|
|
295
|
+
'<span>.setDestinationContext() was never a public API and will be removed, use <span>.setServiceTarget().',
|
|
296
|
+
'DeprecationWarning',
|
|
297
|
+
'ELASTIC_APM_SET_DESTINATION_CONTEXT',
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
if (destCtx.service && destCtx.service.resource) {
|
|
301
|
+
this.setServiceTarget('', destCtx.service.resource);
|
|
302
|
+
}
|
|
303
|
+
const destCtxWithoutService = Object.assign({}, destCtx);
|
|
304
|
+
delete destCtxWithoutService.service;
|
|
305
|
+
this._setDestinationContext(destCtxWithoutService);
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* The internal method for setting "destination" context.
|
|
310
|
+
*
|
|
311
|
+
* "destination.service.resource" should only ever be included for special
|
|
312
|
+
* cases. It is typically inferred from other fields via a general algorithm.
|
|
313
|
+
*/
|
|
314
|
+
Span.prototype._setDestinationContext = function (destCtx) {
|
|
315
|
+
this._destination = Object.assign(this._destination || {}, destCtx);
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Manually set the `service.target.type` and `service.target.name` fields that
|
|
320
|
+
* are used for service maps and the identification of downstream services. The
|
|
321
|
+
* values are only used for "exit" spans -- spans representing outgoing
|
|
322
|
+
* communication, marked with `exitSpan: true` at span creation.
|
|
323
|
+
*
|
|
324
|
+
* If false-y values (e.g. `null`) are given for both `type` and `name`, then
|
|
325
|
+
* `service.target` will explicitly be excluded from this span. This may impact
|
|
326
|
+
* Service Maps and other Kibana APM app reporting for this service.
|
|
327
|
+
*
|
|
328
|
+
* If this method is not called, values are inferred from other span fields per
|
|
329
|
+
* https://github.com/elastic/apm/blob/main/specs/agents/tracing-spans-service-target.md#field-values
|
|
330
|
+
*
|
|
331
|
+
* `service.target.*` fields are ignored for APM Server before v8.3.
|
|
332
|
+
*
|
|
333
|
+
* @param {string | null} type - service target type, usually same value as
|
|
334
|
+
* `span.subtype`
|
|
335
|
+
* @param {string | null} name - service target name: value depends on type,
|
|
336
|
+
* for databases it's usually the database name
|
|
337
|
+
*/
|
|
338
|
+
Span.prototype.setServiceTarget = function (type, name) {
|
|
339
|
+
if (!type && !name) {
|
|
340
|
+
this._excludeServiceTarget = true;
|
|
341
|
+
this._serviceTarget = null;
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (typeof type === 'string') {
|
|
346
|
+
this._excludeServiceTarget = false;
|
|
347
|
+
if (this._serviceTarget === null) {
|
|
348
|
+
this._serviceTarget = { type };
|
|
349
|
+
} else {
|
|
350
|
+
this._serviceTarget.type = type;
|
|
351
|
+
}
|
|
352
|
+
} else if (type != null) {
|
|
353
|
+
this._agent.logger.warn(
|
|
354
|
+
'"type" argument to Span#setServiceTarget must be of type "string", got type "%s": ignoring',
|
|
355
|
+
typeof type,
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
if (typeof name === 'string') {
|
|
359
|
+
this._excludeServiceTarget = false;
|
|
360
|
+
if (this._serviceTarget === null) {
|
|
361
|
+
this._serviceTarget = { name };
|
|
362
|
+
} else {
|
|
363
|
+
this._serviceTarget.name = name;
|
|
364
|
+
}
|
|
365
|
+
} else if (name != null) {
|
|
366
|
+
this._agent.logger.warn(
|
|
367
|
+
'"name" argument to Span#setServiceTarget must be of type "string", got type "%s": ignoring',
|
|
368
|
+
typeof name,
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
Span.prototype.setMessageContext = function (context) {
|
|
374
|
+
this._message = Object.assign(this._message || {}, context);
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
Span.prototype.setOutcome = function (outcome) {
|
|
378
|
+
if (!this._isValidOutcome(outcome)) {
|
|
379
|
+
this._agent.logger.trace(
|
|
380
|
+
'Unknown outcome [%s] seen in Span.setOutcome, ignoring',
|
|
381
|
+
outcome,
|
|
382
|
+
);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (this.ended) {
|
|
387
|
+
this._agent.logger.debug(
|
|
388
|
+
'tried to call Span.setOutcome() on already ended span %o',
|
|
389
|
+
{
|
|
390
|
+
span: this.id,
|
|
391
|
+
parent: this.parentId,
|
|
392
|
+
trace: this.traceId,
|
|
393
|
+
name: this.name,
|
|
394
|
+
type: this.type,
|
|
395
|
+
subtype: this.subtype,
|
|
396
|
+
action: this.action,
|
|
397
|
+
},
|
|
398
|
+
);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
this._freezeOutcome();
|
|
402
|
+
this._setOutcome(outcome);
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
Span.prototype._setOutcomeFromErrorCapture = function (outcome) {
|
|
406
|
+
if (this._isOutcomeFrozen) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
this._setOutcome(outcome);
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
Span.prototype._setOutcomeFromHttpStatusCode = function (statusCode) {
|
|
413
|
+
if (this._isOutcomeFrozen) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* The statusCode could be undefined for example if,
|
|
418
|
+
* the request is aborted before socket, in that case
|
|
419
|
+
* we keep the default 'unknown' value.
|
|
420
|
+
*/
|
|
421
|
+
if (typeof statusCode !== 'undefined') {
|
|
422
|
+
if (statusCode >= 400) {
|
|
423
|
+
this._setOutcome(constants.OUTCOME_FAILURE);
|
|
424
|
+
} else {
|
|
425
|
+
this._setOutcome(constants.OUTCOME_SUCCESS);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
this._freezeOutcome();
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
Span.prototype._setOutcomeFromSpanEnd = function () {
|
|
433
|
+
if (this.outcome === constants.OUTCOME_UNKNOWN && !this._isOutcomeFrozen) {
|
|
434
|
+
this._setOutcome(constants.OUTCOME_SUCCESS);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Central setting for outcome
|
|
440
|
+
*
|
|
441
|
+
* Enables "when outcome does X, Y should also happen" behaviors
|
|
442
|
+
*/
|
|
443
|
+
Span.prototype._setOutcome = function (outcome) {
|
|
444
|
+
this.outcome = outcome;
|
|
445
|
+
if (outcome !== constants.OUTCOME_SUCCESS) {
|
|
446
|
+
this.discardable = false;
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
Span.prototype._recordStackTrace = function (obj) {
|
|
451
|
+
if (!obj) {
|
|
452
|
+
obj = {};
|
|
453
|
+
Error.captureStackTrace(obj, Span);
|
|
454
|
+
}
|
|
455
|
+
this._capturedStackTrace = obj;
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
Span.prototype._encode = function (cb) {
|
|
459
|
+
var self = this;
|
|
460
|
+
|
|
461
|
+
if (!this.ended) {
|
|
462
|
+
return cb(new Error('cannot encode un-ended span'));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const payload = {
|
|
466
|
+
id: self.id,
|
|
467
|
+
transaction_id: self.transaction.id,
|
|
468
|
+
parent_id: self.parentId,
|
|
469
|
+
trace_id: self.traceId,
|
|
470
|
+
name: self.name,
|
|
471
|
+
type: self.type || constants.DEFAULT_SPAN_TYPE,
|
|
472
|
+
subtype: self.subtype,
|
|
473
|
+
action: self.action,
|
|
474
|
+
timestamp: self.timestamp,
|
|
475
|
+
duration: self._duration,
|
|
476
|
+
context: undefined,
|
|
477
|
+
stacktrace: undefined,
|
|
478
|
+
sync: self.sync,
|
|
479
|
+
outcome: self.outcome,
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
// if a valid sample rate is set (truthy or zero), set the property
|
|
483
|
+
const sampleRate = self.sampleRate;
|
|
484
|
+
if (sampleRate !== null) {
|
|
485
|
+
payload.sample_rate = sampleRate;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
let haveContext = false;
|
|
489
|
+
const context = {};
|
|
490
|
+
if (self._serviceTarget) {
|
|
491
|
+
context.service = { target: self._serviceTarget };
|
|
492
|
+
haveContext = true;
|
|
493
|
+
}
|
|
494
|
+
if (self._destination) {
|
|
495
|
+
context.destination = self._destination;
|
|
496
|
+
haveContext = true;
|
|
497
|
+
}
|
|
498
|
+
if (self._db) {
|
|
499
|
+
context.db = self._db;
|
|
500
|
+
haveContext = true;
|
|
501
|
+
}
|
|
502
|
+
if (self._message) {
|
|
503
|
+
context.message = self._message;
|
|
504
|
+
haveContext = true;
|
|
505
|
+
}
|
|
506
|
+
if (self._http) {
|
|
507
|
+
context.http = self._http;
|
|
508
|
+
haveContext = true;
|
|
509
|
+
}
|
|
510
|
+
if (self._labels) {
|
|
511
|
+
context.tags = self._labels;
|
|
512
|
+
haveContext = true;
|
|
513
|
+
}
|
|
514
|
+
if (haveContext) {
|
|
515
|
+
payload.context = context;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
if (self.isComposite()) {
|
|
519
|
+
payload.composite = self._compression.encode();
|
|
520
|
+
payload.timestamp = self._compression.timestamp;
|
|
521
|
+
payload.duration = self._compression.duration;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
this._serializeOTel(payload);
|
|
525
|
+
|
|
526
|
+
if (this._links.length > 0) {
|
|
527
|
+
payload.links = this._links;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (this._stackObj) {
|
|
531
|
+
this._stackObj.then(
|
|
532
|
+
(value) => done(null, value),
|
|
533
|
+
(error) => done(error),
|
|
534
|
+
);
|
|
535
|
+
} else {
|
|
536
|
+
process.nextTick(done);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
function done(err, frames) {
|
|
540
|
+
if (err) {
|
|
541
|
+
self._agent.logger.debug('could not capture stack trace for span %o', {
|
|
542
|
+
span: self.id,
|
|
543
|
+
parent: self.parentId,
|
|
544
|
+
trace: self.traceId,
|
|
545
|
+
name: self.name,
|
|
546
|
+
type: self.type,
|
|
547
|
+
subtype: self.subtype,
|
|
548
|
+
action: self.action,
|
|
549
|
+
err: err.message,
|
|
550
|
+
});
|
|
551
|
+
} else if (frames) {
|
|
552
|
+
payload.stacktrace = frames;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Reduce this span's memory usage by dropping references once they're
|
|
556
|
+
// no longer needed. We also keep fields required to support
|
|
557
|
+
// `interface Span`.
|
|
558
|
+
// Span fields:
|
|
559
|
+
self._db = null;
|
|
560
|
+
self._http = null;
|
|
561
|
+
self._message = null;
|
|
562
|
+
self._capturedStackTrace = null;
|
|
563
|
+
// GenericSpan fields:
|
|
564
|
+
// - Cannot drop `this._context` because it is used for traceparent and ids.
|
|
565
|
+
self._timer = null;
|
|
566
|
+
self._labels = null;
|
|
567
|
+
|
|
568
|
+
cb(null, payload);
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
Span.prototype.isCompressionEligible = function () {
|
|
573
|
+
if (!this.getParentSpan()) {
|
|
574
|
+
return false;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
if (
|
|
578
|
+
this.outcome !== constants.OUTCOME_UNKNOWN &&
|
|
579
|
+
this.outcome !== constants.OUTCOME_SUCCESS
|
|
580
|
+
) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (!this._exitSpan) {
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
if (this._hasPropagatedTraceContext) {
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return true;
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
Span.prototype.tryToCompress = function (spanToCompress) {
|
|
596
|
+
return this._compression.tryToCompress(this, spanToCompress);
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
Span.prototype.isRecorded = function () {
|
|
600
|
+
return this._context.isRecorded();
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
Span.prototype.setRecorded = function (value) {
|
|
604
|
+
return this._context.setRecorded(value);
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
Span.prototype.propagateTraceContextHeaders = function (carrier, setter) {
|
|
608
|
+
this.discardable = false;
|
|
609
|
+
return GenericSpan.prototype.propagateTraceContextHeaders.call(
|
|
610
|
+
this,
|
|
611
|
+
carrier,
|
|
612
|
+
setter,
|
|
613
|
+
);
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
function filterCallSite(callsite) {
|
|
617
|
+
var filename = callsite.getFileName();
|
|
618
|
+
return filename
|
|
619
|
+
? filename.indexOf('/node_modules/elastic-apm-node/') === -1
|
|
620
|
+
: true;
|
|
621
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
exports.wrapCompile = function (agent, moduleName) {
|
|
10
|
+
function wrapTemplate(original) {
|
|
11
|
+
return function wrappedTemplate(data) {
|
|
12
|
+
var span = agent.startSpan(moduleName, 'template', moduleName, 'render');
|
|
13
|
+
var id = span && span.transaction.id;
|
|
14
|
+
|
|
15
|
+
agent.logger.debug('intercepted call to %s render %o', moduleName, {
|
|
16
|
+
id,
|
|
17
|
+
data,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
var ret = original.apply(this, arguments);
|
|
21
|
+
if (span) span.end();
|
|
22
|
+
|
|
23
|
+
return ret;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return function wrappedCompile(original) {
|
|
28
|
+
return function wrappedCompile(input) {
|
|
29
|
+
var span = agent.startSpan(moduleName, 'template', moduleName, 'compile');
|
|
30
|
+
var id = span && span.transaction.id;
|
|
31
|
+
|
|
32
|
+
agent.logger.debug('intercepted call to %s compile %o', moduleName, {
|
|
33
|
+
id,
|
|
34
|
+
input,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
var ret = original.apply(this, arguments);
|
|
38
|
+
if (span) span.end();
|
|
39
|
+
|
|
40
|
+
return typeof ret === 'function' ? wrapTemplate(ret) : ret;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
};
|