@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,106 @@
|
|
|
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 asyncHooks = require('async_hooks');
|
|
10
|
+
|
|
11
|
+
const { BasicRunContextManager } = require('./BasicRunContextManager');
|
|
12
|
+
|
|
13
|
+
// A run context manager that uses an async hook to automatically track
|
|
14
|
+
// run context across async tasks.
|
|
15
|
+
//
|
|
16
|
+
// (Adapted from https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-context-async-hooks/src/AsyncHooksContextManager.ts)
|
|
17
|
+
class AsyncHooksRunContextManager extends BasicRunContextManager {
|
|
18
|
+
constructor(log, runContextClass) {
|
|
19
|
+
super(log, runContextClass);
|
|
20
|
+
this._runContextFromAsyncId = new Map();
|
|
21
|
+
this._asyncHook = asyncHooks.createHook({
|
|
22
|
+
init: this._init.bind(this),
|
|
23
|
+
before: this._before.bind(this),
|
|
24
|
+
after: this._after.bind(this),
|
|
25
|
+
destroy: this._destroy.bind(this),
|
|
26
|
+
promiseResolve: this._destroy.bind(this),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
enable() {
|
|
31
|
+
super.enable();
|
|
32
|
+
this._asyncHook.enable();
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
disable() {
|
|
37
|
+
super.disable();
|
|
38
|
+
this._asyncHook.disable();
|
|
39
|
+
this._runContextFromAsyncId.clear();
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Reset state for re-use of this context manager by tests in the same process.
|
|
44
|
+
testReset() {
|
|
45
|
+
// Absent a core node async_hooks bug, the easy way to implement this method
|
|
46
|
+
// would be: `this.disable(); this.enable()`.
|
|
47
|
+
// However there is a bug in Node.js v12.0.0 - v12.2.0 (inclusive) where
|
|
48
|
+
// disabling the async hook could result in it never getting re-enabled.
|
|
49
|
+
// https://github.com/nodejs/node/issues/27585
|
|
50
|
+
// https://github.com/nodejs/node/pull/27590 (included in node v12.3.0)
|
|
51
|
+
this._runContextFromAsyncId.clear();
|
|
52
|
+
this._stack = [];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Init hook will be called when userland create a async context, setting the
|
|
57
|
+
* context as the current one if it exist.
|
|
58
|
+
* @param asyncId id of the async context
|
|
59
|
+
* @param type the resource type
|
|
60
|
+
*/
|
|
61
|
+
_init(asyncId, type, triggerAsyncId) {
|
|
62
|
+
// ignore TIMERWRAP as they combine timers with same timeout which can lead to
|
|
63
|
+
// false context propagation. TIMERWRAP has been removed in node 11
|
|
64
|
+
// every timer has it's own `Timeout` resource anyway which is used to propagete
|
|
65
|
+
// context.
|
|
66
|
+
if (type === 'TIMERWRAP') {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const context = this._stack[this._stack.length - 1];
|
|
71
|
+
if (context !== undefined) {
|
|
72
|
+
this._runContextFromAsyncId.set(asyncId, context);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Destroy hook will be called when a given context is no longer used so we can
|
|
78
|
+
* remove its attached context.
|
|
79
|
+
* @param asyncId id of the async context
|
|
80
|
+
*/
|
|
81
|
+
_destroy(asyncId) {
|
|
82
|
+
this._runContextFromAsyncId.delete(asyncId);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Before hook is called just before executing a async context.
|
|
87
|
+
* @param asyncId id of the async context
|
|
88
|
+
*/
|
|
89
|
+
_before(asyncId) {
|
|
90
|
+
const context = this._runContextFromAsyncId.get(asyncId);
|
|
91
|
+
if (context !== undefined) {
|
|
92
|
+
this._enterRunContext(context);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* After hook is called just after completing the execution of a async context.
|
|
98
|
+
*/
|
|
99
|
+
_after() {
|
|
100
|
+
this._exitRunContext();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = {
|
|
105
|
+
AsyncHooksRunContextManager,
|
|
106
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
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 { AsyncLocalStorage } = require('async_hooks');
|
|
10
|
+
|
|
11
|
+
const { AbstractRunContextManager } = require('./AbstractRunContextManager');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A RunContextManager that uses core node `AsyncLocalStorage` as the mechanism
|
|
15
|
+
* for run-context tracking.
|
|
16
|
+
*
|
|
17
|
+
* (Adapted from https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-context-async-hooks/src/AsyncLocalStorageContextManager.ts)
|
|
18
|
+
*/
|
|
19
|
+
class AsyncLocalStorageRunContextManager extends AbstractRunContextManager {
|
|
20
|
+
constructor(log, runContextClass) {
|
|
21
|
+
super(log, runContextClass);
|
|
22
|
+
this._asyncLocalStorage = new AsyncLocalStorage();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// A string representation useful for debug logging. For example,
|
|
26
|
+
// AsyncLocalStorageRunContextManager( RC(Trans(685ead, manual), [Span(9dd31c, GET httpstat.us, ended)]) )
|
|
27
|
+
toString() {
|
|
28
|
+
return `${this.constructor.name}( ${this.active().toString()} )`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
enable() {
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
disable() {
|
|
36
|
+
this._asyncLocalStorage.disable();
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Reset state for re-use of this context manager by tests in the same process.
|
|
41
|
+
testReset() {
|
|
42
|
+
this.disable();
|
|
43
|
+
this.enable();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
active() {
|
|
47
|
+
const store = this._asyncLocalStorage.getStore();
|
|
48
|
+
if (store == null) {
|
|
49
|
+
return this.root();
|
|
50
|
+
} else {
|
|
51
|
+
return store;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
with(runContext, fn, thisArg, ...args) {
|
|
56
|
+
const cb = thisArg == null ? fn : fn.bind(thisArg);
|
|
57
|
+
return this._asyncLocalStorage.run(runContext, cb, ...args);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// This public method is needed to support the semantics of
|
|
61
|
+
// apm.startTransaction() and apm.startSpan() that impact the current run
|
|
62
|
+
// context.
|
|
63
|
+
//
|
|
64
|
+
// Otherwise, all run context changes are via `.with()` -- scoped to a
|
|
65
|
+
// function call -- or via the "before" async hook -- scoped to an async task.
|
|
66
|
+
supersedeRunContext(runContext) {
|
|
67
|
+
this._asyncLocalStorage.enterWith(runContext);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
AsyncLocalStorageRunContextManager,
|
|
73
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
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 { AbstractRunContextManager } = require('./AbstractRunContextManager');
|
|
10
|
+
|
|
11
|
+
// A basic manager for run context. It handles a stack of run contexts, but does
|
|
12
|
+
// no automatic tracking (via async_hooks or otherwise). Use one of the
|
|
13
|
+
// subclasses.
|
|
14
|
+
//
|
|
15
|
+
// (Adapted from https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-context-async-hooks/src/AsyncHooksContextManager.ts)
|
|
16
|
+
class BasicRunContextManager extends AbstractRunContextManager {
|
|
17
|
+
constructor(log, runContextClass) {
|
|
18
|
+
super(log, runContextClass);
|
|
19
|
+
this._stack = []; // Top of stack is the current run context.
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// A string representation useful for debug logging. For example,
|
|
23
|
+
// BasicRunContextManager(
|
|
24
|
+
// RC(Trans(685ead, manual), [Span(9dd31c, GET httpstat.us, ended)]),
|
|
25
|
+
// RC(Trans(685ead, manual)) )
|
|
26
|
+
toString() {
|
|
27
|
+
return `${this.constructor.name}( ${this._stack
|
|
28
|
+
.map((rc) => rc.toString())
|
|
29
|
+
.join(', ')} )`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
enable() {
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
disable() {
|
|
37
|
+
this._stack = [];
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Reset state for re-use of this context manager by tests in the same process.
|
|
42
|
+
testReset() {
|
|
43
|
+
this.disable();
|
|
44
|
+
this.enable();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
active() {
|
|
48
|
+
return this._stack[this._stack.length - 1] || this.root();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
with(runContext, fn, thisArg, ...args) {
|
|
52
|
+
this._enterRunContext(runContext);
|
|
53
|
+
try {
|
|
54
|
+
return fn.call(thisArg, ...args);
|
|
55
|
+
} finally {
|
|
56
|
+
this._exitRunContext();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// This public method is needed to support the semantics of
|
|
61
|
+
// apm.startTransaction() and apm.startSpan() that impact the current run
|
|
62
|
+
// context.
|
|
63
|
+
//
|
|
64
|
+
// Otherwise, all run context changes are via `.with()` -- scoped to a
|
|
65
|
+
// function call -- or via the "before" async hook -- scoped to an async task.
|
|
66
|
+
supersedeRunContext(runContext) {
|
|
67
|
+
this._exitRunContext();
|
|
68
|
+
this._enterRunContext(runContext);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
_enterRunContext(runContext) {
|
|
72
|
+
this._stack.push(runContext);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_exitRunContext() {
|
|
76
|
+
this._stack.pop();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
BasicRunContextManager,
|
|
82
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
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
|
+
// A RunContext is the immutable structure that holds which transaction and span
|
|
10
|
+
// are currently active, if any, for the running JavaScript code.
|
|
11
|
+
//
|
|
12
|
+
// Module instrumentation code interacts with run contexts via a number of
|
|
13
|
+
// methods on the `Instrumentation` instance at `agent._instrumentation`.
|
|
14
|
+
//
|
|
15
|
+
// User code using the agent's API (the Agent API, Transaction API, and Span API)
|
|
16
|
+
// are not exposes to RunContext instances. However users of the OpenTelemetry
|
|
17
|
+
// API, provided by the OpenTelemetry Bridge, *are* exposed to OpenTelemetry
|
|
18
|
+
// `Context` instances -- which RunContext implements.
|
|
19
|
+
//
|
|
20
|
+
// A RunContext holds:
|
|
21
|
+
// - a current Transaction, which can be null; and
|
|
22
|
+
// - a *stack* of Spans, where the top-of-stack span is the "current" one.
|
|
23
|
+
// A stack is necessary to support the semantics of multiple started and ended
|
|
24
|
+
// spans in the same async task. E.g.:
|
|
25
|
+
// apm.startTransaction('t')
|
|
26
|
+
// var s1 = apm.startSpan('s1')
|
|
27
|
+
// var s2 = apm.startSpan('s2')
|
|
28
|
+
// s2.end()
|
|
29
|
+
// assert(apm.currentSpan === s1, 's1 is now the current span')
|
|
30
|
+
// - a mapping of "values". This is an arbitrary key-value mapping, but exists
|
|
31
|
+
// primarily to implement OpenTelemetry `interface Context`
|
|
32
|
+
// https://github.com/open-telemetry/opentelemetry-js-api/blob/v1.1.0/src/context/types.ts#L17-L41
|
|
33
|
+
//
|
|
34
|
+
// A RunContext is immutable. This means that `runContext.enterSpan(span)` and
|
|
35
|
+
// other similar methods return a new/separate RunContext instance. This is
|
|
36
|
+
// done so that a run-context change in the current code does not change
|
|
37
|
+
// anything for other code bound to the original RunContext (e.g. via
|
|
38
|
+
// `ins.bindFunction` or `ins.bindEmitter`).
|
|
39
|
+
//
|
|
40
|
+
// Warning: Agent code should never use the `RunContext` class directly
|
|
41
|
+
// because a subclass can be provided for the `Instrumentation` to use.
|
|
42
|
+
// Instead new instances should be built from an existing one, typically the
|
|
43
|
+
// active one (`_runCtxMgr.active()`) or the root one (`_runCtxMgr.root()`).
|
|
44
|
+
class RunContext {
|
|
45
|
+
constructor(trans, spans, parentValues) {
|
|
46
|
+
this._trans = trans || null;
|
|
47
|
+
this._spans = spans || [];
|
|
48
|
+
this._values = parentValues ? new Map(parentValues) : new Map();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
currTransaction() {
|
|
52
|
+
return this._trans;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Returns the currently active span, if any, otherwise null.
|
|
56
|
+
currSpan() {
|
|
57
|
+
if (this._spans.length > 0) {
|
|
58
|
+
return this._spans[this._spans.length - 1];
|
|
59
|
+
} else {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Return a new RunContext for a newly active/current Transaction.
|
|
65
|
+
enterTrans(trans) {
|
|
66
|
+
return new this.constructor(trans, null, this._values);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Return a new RunContext with the given span added to the top of the spans
|
|
70
|
+
// stack.
|
|
71
|
+
enterSpan(span) {
|
|
72
|
+
const newSpans = this._spans.slice();
|
|
73
|
+
newSpans.push(span);
|
|
74
|
+
return new this.constructor(this._trans, newSpans, this._values);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Return a new RunContext with the given transaction (and hence all of its
|
|
78
|
+
// spans) removed.
|
|
79
|
+
leaveTrans() {
|
|
80
|
+
return new this.constructor(null, null, this._values);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Return a new RunContext with the given span removed, or null if there is
|
|
84
|
+
// no change (the given span isn't part of the run context).
|
|
85
|
+
//
|
|
86
|
+
// Typically this span is the top of stack (i.e. it is the current span).
|
|
87
|
+
// However, it is possible to have out-of-order span.end() or even end a span
|
|
88
|
+
// that isn't part of the current run context stack at all. (See
|
|
89
|
+
// test/instrumentation/run-context/fixtures/end-non-current-spans.js for
|
|
90
|
+
// examples.)
|
|
91
|
+
leaveSpan(span) {
|
|
92
|
+
let newRc = null;
|
|
93
|
+
let newSpans;
|
|
94
|
+
const lastSpan = this._spans[this._spans.length - 1];
|
|
95
|
+
if (lastSpan && lastSpan.id === span.id) {
|
|
96
|
+
// Fast path for common case: `span` is top of stack.
|
|
97
|
+
newSpans = this._spans.slice(0, this._spans.length - 1);
|
|
98
|
+
newRc = new this.constructor(this._trans, newSpans, this._values);
|
|
99
|
+
} else {
|
|
100
|
+
const stackIdx = this._spans.findIndex((s) => s.id === span.id);
|
|
101
|
+
if (stackIdx !== -1) {
|
|
102
|
+
newSpans = this._spans
|
|
103
|
+
.slice(0, stackIdx)
|
|
104
|
+
.concat(this._spans.slice(stackIdx + 1));
|
|
105
|
+
newRc = new this.constructor(this._trans, newSpans, this._values);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return newRc;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// A string representation useful for debug logging.
|
|
112
|
+
// For example:
|
|
113
|
+
// RunContext(Transaction(abc123, 'trans name'), [Span(def456, 'span name', ended)])
|
|
114
|
+
// ^^^^^^^-- if the span has ended
|
|
115
|
+
// ^^^^^^ ^^^^^^-- id
|
|
116
|
+
// ^^^^^^^^^^-- the class name, typically "RunContext", but can be overriden
|
|
117
|
+
toString() {
|
|
118
|
+
const bits = [];
|
|
119
|
+
if (this._trans) {
|
|
120
|
+
bits.push(this._trans.toString());
|
|
121
|
+
}
|
|
122
|
+
if (this._spans.length > 0) {
|
|
123
|
+
const spanStrs = this._spans.map((s) => s.toString());
|
|
124
|
+
bits.push('[' + spanStrs + ']');
|
|
125
|
+
}
|
|
126
|
+
return `${this.constructor.name}(${bits.join(', ')})`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ---- The following implements the OTel Context interface.
|
|
130
|
+
// https://github.com/open-telemetry/opentelemetry-js-api/blob/v1.0.4/src/context/types.ts#L17
|
|
131
|
+
|
|
132
|
+
getValue(key) {
|
|
133
|
+
return this._values.get(key);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
setValue(key, value) {
|
|
137
|
+
const rc = new this.constructor(this._trans, this._spans, this._values);
|
|
138
|
+
rc._values.set(key, value);
|
|
139
|
+
return rc;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
deleteValue(key) {
|
|
143
|
+
const rc = new this.constructor(this._trans, this._spans, this._values);
|
|
144
|
+
rc._values.delete(key);
|
|
145
|
+
return rc;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
RunContext,
|
|
151
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
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 {
|
|
10
|
+
AsyncHooksRunContextManager,
|
|
11
|
+
} = require('./AsyncHooksRunContextManager');
|
|
12
|
+
const {
|
|
13
|
+
AsyncLocalStorageRunContextManager,
|
|
14
|
+
} = require('./AsyncLocalStorageRunContextManager');
|
|
15
|
+
const { BasicRunContextManager } = require('./BasicRunContextManager');
|
|
16
|
+
const { RunContext } = require('./RunContext');
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
AsyncHooksRunContextManager,
|
|
20
|
+
AsyncLocalStorageRunContextManager,
|
|
21
|
+
BasicRunContextManager,
|
|
22
|
+
RunContext,
|
|
23
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
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
|
+
/**
|
|
10
|
+
* This file is extracted from the 'shimmer' project copyright by Forrest L
|
|
11
|
+
* Norvell. It have been modified slightly to be used in the current context.
|
|
12
|
+
*
|
|
13
|
+
* https://github.com/othiym23/shimmer
|
|
14
|
+
*
|
|
15
|
+
* Original file:
|
|
16
|
+
*
|
|
17
|
+
* https://github.com/othiym23/shimmer/blob/master/index.js
|
|
18
|
+
*
|
|
19
|
+
* License:
|
|
20
|
+
*
|
|
21
|
+
* BSD-2-Clause, http://opensource.org/licenses/BSD-2-Clause
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
var symbols = require('../symbols');
|
|
25
|
+
|
|
26
|
+
var isWrappedSym = Symbol('elasticAPMIsWrapped');
|
|
27
|
+
|
|
28
|
+
exports.wrap = wrap;
|
|
29
|
+
exports.massWrap = massWrap;
|
|
30
|
+
exports.unwrap = unwrap;
|
|
31
|
+
|
|
32
|
+
// Do not load agent until used to avoid circular dependency issues.
|
|
33
|
+
var _agent;
|
|
34
|
+
function logger() {
|
|
35
|
+
if (!_agent) _agent = require('../../');
|
|
36
|
+
return _agent.logger;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isFunction(funktion) {
|
|
40
|
+
return typeof funktion === 'function';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function wrap(nodule, name, wrapper) {
|
|
44
|
+
if (!nodule || !nodule[name]) {
|
|
45
|
+
logger().debug('no original function %s to wrap', name);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!wrapper) {
|
|
50
|
+
logger().debug({ stack: new Error().stack }, 'no wrapper function');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!isFunction(nodule[name]) || !isFunction(wrapper)) {
|
|
55
|
+
logger().debug('original object and wrapper must be functions');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (nodule[name][isWrappedSym]) {
|
|
60
|
+
logger().debug('function %s already wrapped', name);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
var desc = Object.getOwnPropertyDescriptor(nodule, name);
|
|
65
|
+
if (desc && !desc.writable) {
|
|
66
|
+
logger().debug('function %s is not writable', name);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
var original = nodule[name];
|
|
71
|
+
var wrapped = wrapper(original, name);
|
|
72
|
+
|
|
73
|
+
wrapped[isWrappedSym] = true;
|
|
74
|
+
wrapped[symbols.unwrap] = function elasticAPMUnwrap() {
|
|
75
|
+
if (nodule[name] === wrapped) {
|
|
76
|
+
nodule[name] = original;
|
|
77
|
+
wrapped[isWrappedSym] = false;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
nodule[name] = wrapped;
|
|
82
|
+
|
|
83
|
+
return wrapped;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function massWrap(nodules, names, wrapper) {
|
|
87
|
+
if (!nodules) {
|
|
88
|
+
logger().debug(
|
|
89
|
+
{ stack: new Error().stack },
|
|
90
|
+
'must provide one or more modules to patch',
|
|
91
|
+
);
|
|
92
|
+
return;
|
|
93
|
+
} else if (!Array.isArray(nodules)) {
|
|
94
|
+
nodules = [nodules];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!(names && Array.isArray(names))) {
|
|
98
|
+
logger().debug('must provide one or more functions to wrap on modules');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
for (const nodule of nodules) {
|
|
103
|
+
for (const name of names) {
|
|
104
|
+
wrap(nodule, name, wrapper);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function unwrap(nodule, name) {
|
|
110
|
+
if (!nodule || !nodule[name]) {
|
|
111
|
+
logger().debug({ stack: new Error().stack }, 'no function to unwrap');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!nodule[name][symbols.unwrap]) {
|
|
116
|
+
logger().debug(
|
|
117
|
+
'no original to unwrap to -- has %s already been unwrapped?',
|
|
118
|
+
name,
|
|
119
|
+
);
|
|
120
|
+
} else {
|
|
121
|
+
return nodule[name][symbols.unwrap]();
|
|
122
|
+
}
|
|
123
|
+
}
|