@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,93 @@
|
|
|
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 semver = require('semver');
|
|
10
|
+
|
|
11
|
+
var shimmer = require('../shimmer');
|
|
12
|
+
|
|
13
|
+
var massWrap = shimmer.massWrap;
|
|
14
|
+
var wrap = shimmer.wrap;
|
|
15
|
+
|
|
16
|
+
var BLUEBIRD_FNS = ['_then', '_addCallbacks'];
|
|
17
|
+
|
|
18
|
+
module.exports = function (bluebird, agent, { version }) {
|
|
19
|
+
var ins = agent._instrumentation;
|
|
20
|
+
|
|
21
|
+
if (!semver.satisfies(version, '>=2 <4')) {
|
|
22
|
+
agent.logger.debug(
|
|
23
|
+
'bluebird version %s not supported - aborting...',
|
|
24
|
+
version,
|
|
25
|
+
);
|
|
26
|
+
return bluebird;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
agent.logger.debug('shimming bluebird.prototype functions: %j', BLUEBIRD_FNS);
|
|
30
|
+
massWrap(bluebird.prototype, BLUEBIRD_FNS, wrapThen);
|
|
31
|
+
|
|
32
|
+
// Calling bluebird.config might overwrite the
|
|
33
|
+
// bluebird.prototype._attachCancellationCallback function with a new
|
|
34
|
+
// function. We need to hook into this new function
|
|
35
|
+
agent.logger.debug('shimming bluebird.config');
|
|
36
|
+
wrap(bluebird, 'config', function wrapConfig(original) {
|
|
37
|
+
return function wrappedConfig() {
|
|
38
|
+
var result = original.apply(this, arguments);
|
|
39
|
+
|
|
40
|
+
agent.logger.debug(
|
|
41
|
+
'shimming bluebird.prototype._attachCancellationCallback',
|
|
42
|
+
);
|
|
43
|
+
wrap(
|
|
44
|
+
bluebird.prototype,
|
|
45
|
+
'_attachCancellationCallback',
|
|
46
|
+
function wrapAttachCancellationCallback(original) {
|
|
47
|
+
return function wrappedAttachCancellationCallback(onCancel) {
|
|
48
|
+
if (arguments.length !== 1) return original.apply(this, arguments);
|
|
49
|
+
return original.call(this, ins.bindFunction(onCancel));
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return result;
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// WARNING: even if you remove these two shims, the tests might still pass
|
|
59
|
+
// for bluebird@2. The tests are flaky and will only fail sometimes and in
|
|
60
|
+
// some cases only if run together with the other tests.
|
|
61
|
+
//
|
|
62
|
+
// To test, run in a while-loop:
|
|
63
|
+
//
|
|
64
|
+
// while :; do node test/instrumentation/modules/bluebird/bluebird.js || exit $?; done
|
|
65
|
+
if (semver.satisfies(version, '<3')) {
|
|
66
|
+
agent.logger.debug('shimming bluebird.each');
|
|
67
|
+
wrap(bluebird, 'each', function wrapEach(original) {
|
|
68
|
+
return function wrappedEach(promises, fn) {
|
|
69
|
+
if (arguments.length !== 2) return original.apply(this, arguments);
|
|
70
|
+
return original.call(this, promises, ins.bindFunction(fn));
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
agent.logger.debug('shimming bluebird.prototype.each');
|
|
75
|
+
wrap(bluebird.prototype, 'each', function wrapEach(original) {
|
|
76
|
+
return function wrappedEach(fn) {
|
|
77
|
+
if (arguments.length !== 1) return original.apply(this, arguments);
|
|
78
|
+
return original.call(this, ins.bindFunction(fn));
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return bluebird;
|
|
84
|
+
|
|
85
|
+
function wrapThen(original) {
|
|
86
|
+
return function wrappedThen() {
|
|
87
|
+
var args = Array.prototype.slice.call(arguments);
|
|
88
|
+
if (typeof args[0] === 'function') args[0] = ins.bindFunction(args[0]);
|
|
89
|
+
if (typeof args[1] === 'function') args[1] = ins.bindFunction(args[1]);
|
|
90
|
+
return original.apply(this, args);
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
};
|
|
@@ -0,0 +1,280 @@
|
|
|
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 semver = require('semver');
|
|
10
|
+
const sqlSummary = require('sql-summary');
|
|
11
|
+
|
|
12
|
+
const shimmer = require('../shimmer');
|
|
13
|
+
|
|
14
|
+
module.exports = function (cassandra, agent, { version, enabled }) {
|
|
15
|
+
if (!enabled) return cassandra;
|
|
16
|
+
if (!semver.satisfies(version, '>=3 <5')) {
|
|
17
|
+
agent.logger.debug(
|
|
18
|
+
'cassandra-driver version %s not supported - aborting...',
|
|
19
|
+
version,
|
|
20
|
+
);
|
|
21
|
+
return cassandra;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const ins = agent._instrumentation;
|
|
25
|
+
|
|
26
|
+
if (cassandra.Client) {
|
|
27
|
+
if (semver.gte(version, '4.4.0')) {
|
|
28
|
+
// Prior to v4.4.0, the regular `connect` function would be called by the
|
|
29
|
+
// other functions (e.g. `execute`). In newer versions an internal
|
|
30
|
+
// `_connect` function is called instead (this is also called by
|
|
31
|
+
// `connect`).
|
|
32
|
+
shimmer.wrap(cassandra.Client.prototype, '_connect', wrapAsyncConnect);
|
|
33
|
+
} else {
|
|
34
|
+
shimmer.wrap(cassandra.Client.prototype, 'connect', wrapConnect);
|
|
35
|
+
}
|
|
36
|
+
shimmer.wrap(cassandra.Client.prototype, 'execute', wrapExecute);
|
|
37
|
+
shimmer.wrap(cassandra.Client.prototype, 'eachRow', wrapEachRow);
|
|
38
|
+
shimmer.wrap(cassandra.Client.prototype, 'batch', wrapBatch);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return cassandra;
|
|
42
|
+
|
|
43
|
+
function wrapAsyncConnect(original) {
|
|
44
|
+
return async function wrappedAsyncConnect() {
|
|
45
|
+
const span = ins.createSpan(
|
|
46
|
+
'Cassandra: Connect',
|
|
47
|
+
'db',
|
|
48
|
+
'cassandra',
|
|
49
|
+
'connect',
|
|
50
|
+
{ exitSpan: true },
|
|
51
|
+
);
|
|
52
|
+
if (!span) {
|
|
53
|
+
return original.apply(this, arguments);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const dbContext = { type: 'cassandra' };
|
|
57
|
+
if (this.keyspace) {
|
|
58
|
+
dbContext.instance = this.keyspace;
|
|
59
|
+
}
|
|
60
|
+
span.setDbContext(dbContext);
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
return await original.apply(this, arguments);
|
|
64
|
+
} finally {
|
|
65
|
+
span.end();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function wrapConnect(original) {
|
|
71
|
+
return function wrappedConnect(callback) {
|
|
72
|
+
const span = ins.createSpan(
|
|
73
|
+
'Cassandra: Connect',
|
|
74
|
+
'db',
|
|
75
|
+
'cassandra',
|
|
76
|
+
'connect',
|
|
77
|
+
{ exitSpan: true },
|
|
78
|
+
);
|
|
79
|
+
if (!span) {
|
|
80
|
+
return original.apply(this, arguments);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const dbContext = { type: 'cassandra' };
|
|
84
|
+
if (this.keyspace) {
|
|
85
|
+
dbContext.instance = this.keyspace;
|
|
86
|
+
}
|
|
87
|
+
span.setDbContext(dbContext);
|
|
88
|
+
|
|
89
|
+
function resolve() {
|
|
90
|
+
span.end();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Wrap the callback
|
|
94
|
+
const ret = original.call(this, wrapCallback(callback));
|
|
95
|
+
|
|
96
|
+
if (typeof callback !== 'function') {
|
|
97
|
+
if (typeof ret.then === 'function') {
|
|
98
|
+
ret.then(resolve, resolve);
|
|
99
|
+
} else {
|
|
100
|
+
agent.logger.error(
|
|
101
|
+
'unable to identify span exit point for cassandra-driver',
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return ret;
|
|
107
|
+
|
|
108
|
+
function wrapCallback(cb) {
|
|
109
|
+
if (typeof cb !== 'function') return cb;
|
|
110
|
+
return function wrappedCallback() {
|
|
111
|
+
resolve();
|
|
112
|
+
return cb.apply(this, arguments);
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function toQueryString(query) {
|
|
119
|
+
return query.query;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function wrapBatch(original) {
|
|
123
|
+
return function wrappedBatch(queries, options, callback) {
|
|
124
|
+
const span = ins.createSpan(
|
|
125
|
+
'Cassandra: Batch query',
|
|
126
|
+
'db',
|
|
127
|
+
'cassandra',
|
|
128
|
+
'query',
|
|
129
|
+
{ exitSpan: true },
|
|
130
|
+
);
|
|
131
|
+
if (!span) {
|
|
132
|
+
return original.apply(this, arguments);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const queryStrings = queries.map(toQueryString);
|
|
136
|
+
const query = queryStrings.join(';\n');
|
|
137
|
+
const dbContext = { type: 'cassandra', statement: query };
|
|
138
|
+
const keyspace =
|
|
139
|
+
(options && typeof options === 'object' && options.keyspace) ||
|
|
140
|
+
this.keyspace;
|
|
141
|
+
if (keyspace) {
|
|
142
|
+
dbContext.instance = keyspace;
|
|
143
|
+
}
|
|
144
|
+
span.setDbContext(dbContext);
|
|
145
|
+
|
|
146
|
+
function resolve() {
|
|
147
|
+
span.end();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Wrap the callback
|
|
151
|
+
const index = arguments.length - 1;
|
|
152
|
+
const cb = arguments[index];
|
|
153
|
+
const isPromise = typeof cb !== 'function';
|
|
154
|
+
if (!isPromise) {
|
|
155
|
+
arguments[index] = function wrappedCallback() {
|
|
156
|
+
resolve();
|
|
157
|
+
return cb.apply(this, arguments);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const ret = original.apply(this, arguments);
|
|
162
|
+
|
|
163
|
+
if (isPromise) {
|
|
164
|
+
if (typeof ret.then === 'function') {
|
|
165
|
+
ret.then(resolve, resolve);
|
|
166
|
+
} else {
|
|
167
|
+
agent.logger.error(
|
|
168
|
+
'unable to identify span exit point for cassandra-driver',
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return ret;
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function wrapExecute(original) {
|
|
178
|
+
return function wrappedExecute(query, params, options, callback) {
|
|
179
|
+
const span = ins.createSpan(null, 'db', 'cassandra', 'query', {
|
|
180
|
+
exitSpan: true,
|
|
181
|
+
});
|
|
182
|
+
if (!span) {
|
|
183
|
+
return original.apply(this, arguments);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
span.name = sqlSummary(query);
|
|
187
|
+
const dbContext = { type: 'cassandra', statement: query };
|
|
188
|
+
const keyspace =
|
|
189
|
+
(options && typeof options === 'object' && options.keyspace) ||
|
|
190
|
+
this.keyspace;
|
|
191
|
+
if (keyspace) {
|
|
192
|
+
dbContext.instance = keyspace;
|
|
193
|
+
}
|
|
194
|
+
span.setDbContext(dbContext);
|
|
195
|
+
|
|
196
|
+
function resolve() {
|
|
197
|
+
span.end();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Wrap the callback
|
|
201
|
+
const index = arguments.length - 1;
|
|
202
|
+
const cb = arguments[index];
|
|
203
|
+
const isPromise = typeof cb !== 'function';
|
|
204
|
+
if (!isPromise) {
|
|
205
|
+
arguments[index] = function wrappedCallback() {
|
|
206
|
+
resolve();
|
|
207
|
+
return cb.apply(this, arguments);
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const ret = original.apply(this, arguments);
|
|
212
|
+
|
|
213
|
+
if (isPromise) {
|
|
214
|
+
if (typeof ret.then === 'function') {
|
|
215
|
+
ret.then(resolve, resolve);
|
|
216
|
+
} else {
|
|
217
|
+
agent.logger.error(
|
|
218
|
+
'unable to identify span exit point for cassandra-driver',
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return ret;
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function wrapEachRow(original) {
|
|
228
|
+
return function wrappedEachRow(
|
|
229
|
+
query,
|
|
230
|
+
params,
|
|
231
|
+
options,
|
|
232
|
+
rowCallback,
|
|
233
|
+
callback,
|
|
234
|
+
) {
|
|
235
|
+
const span = ins.createSpan(null, 'db', 'cassandra', 'query', {
|
|
236
|
+
exitSpan: true,
|
|
237
|
+
});
|
|
238
|
+
if (!span) {
|
|
239
|
+
return original.apply(this, arguments);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
span.name = sqlSummary(query);
|
|
243
|
+
const dbContext = { type: 'cassandra', statement: query };
|
|
244
|
+
const keyspace =
|
|
245
|
+
(options && typeof options === 'object' && options.keyspace) ||
|
|
246
|
+
this.keyspace;
|
|
247
|
+
if (keyspace) {
|
|
248
|
+
dbContext.instance = keyspace;
|
|
249
|
+
}
|
|
250
|
+
span.setDbContext(dbContext);
|
|
251
|
+
|
|
252
|
+
// Wrap the callback
|
|
253
|
+
const index = arguments.length - 1;
|
|
254
|
+
const hasRowCallback = typeof arguments[index - 1] === 'function';
|
|
255
|
+
|
|
256
|
+
function resolve() {
|
|
257
|
+
span.end();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (hasRowCallback) {
|
|
261
|
+
const cb = arguments[index];
|
|
262
|
+
if (typeof cb === 'function') {
|
|
263
|
+
arguments[index] = function wrappedCallback() {
|
|
264
|
+
resolve();
|
|
265
|
+
return cb.apply(this, arguments);
|
|
266
|
+
};
|
|
267
|
+
} else {
|
|
268
|
+
agent.logger.error(
|
|
269
|
+
'unable to identify span exit point for cassandra-driver',
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
arguments[index + 1] = resolve;
|
|
274
|
+
arguments.length++;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return original.apply(this, arguments);
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
};
|
|
@@ -0,0 +1,191 @@
|
|
|
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, URLSearchParams } = require('url');
|
|
10
|
+
|
|
11
|
+
var shimmer = require('../shimmer');
|
|
12
|
+
var { getDBDestination } = require('../context');
|
|
13
|
+
const { getElasticsearchDbStatement } = require('../elasticsearch-shared');
|
|
14
|
+
|
|
15
|
+
const startsWithProtocolRE = /^([a-z]+:)?\/\//i;
|
|
16
|
+
const DEFAULT_PORT = 9200;
|
|
17
|
+
const DEFAULT_PORT_FROM_PROTO = {
|
|
18
|
+
'http:': 80,
|
|
19
|
+
'https:': 443,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// This is an imperfect equivalent of the handling in the `Transport`
|
|
23
|
+
// constructor and internal `Host` parsing function in the ES client.
|
|
24
|
+
// This returns a `URL` object or null.
|
|
25
|
+
function getTargetUrlFromTransportConfig(config) {
|
|
26
|
+
const transportHosts = config ? config.host || config.hosts : null;
|
|
27
|
+
if (!transportHosts) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let firstTransportHost = Array.isArray(transportHosts)
|
|
32
|
+
? transportHosts[0]
|
|
33
|
+
: transportHosts;
|
|
34
|
+
if (!firstTransportHost) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (typeof firstTransportHost === 'string') {
|
|
39
|
+
// "example.com:42" or "someprotocol://example.com:42" or
|
|
40
|
+
// "someprotocol://example.com".
|
|
41
|
+
if (!startsWithProtocolRE.test(firstTransportHost)) {
|
|
42
|
+
firstTransportHost = 'http://' + firstTransportHost;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
return new URL(firstTransportHost);
|
|
46
|
+
} catch (_err) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
} else if (typeof firstTransportHost === 'object') {
|
|
50
|
+
let proto = firstTransportHost.protocol || 'http:';
|
|
51
|
+
if (!proto.endsWith(':')) {
|
|
52
|
+
proto += ':';
|
|
53
|
+
}
|
|
54
|
+
const hostname = firstTransportHost.hostname || firstTransportHost.host;
|
|
55
|
+
const port = firstTransportHost.port || DEFAULT_PORT;
|
|
56
|
+
try {
|
|
57
|
+
return new URL(proto + '//' + hostname + ':' + port);
|
|
58
|
+
} catch (_ignoredErr) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = function (elasticsearch, agent, { enabled }) {
|
|
67
|
+
if (!enabled) return elasticsearch;
|
|
68
|
+
|
|
69
|
+
const ins = agent._instrumentation;
|
|
70
|
+
const elasticsearchCaptureBodyUrlsRegExp =
|
|
71
|
+
agent._conf.elasticsearchCaptureBodyUrlsRegExp;
|
|
72
|
+
|
|
73
|
+
agent.logger.debug('shimming elasticsearch.Transport.prototype.request');
|
|
74
|
+
shimmer.wrap(
|
|
75
|
+
elasticsearch.Transport && elasticsearch.Transport.prototype,
|
|
76
|
+
'request',
|
|
77
|
+
wrapRequest,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return elasticsearch;
|
|
81
|
+
|
|
82
|
+
function wrapRequest(original) {
|
|
83
|
+
return function wrappedRequest(params, cb) {
|
|
84
|
+
var span = ins.createSpan(null, 'db', 'elasticsearch', 'request', {
|
|
85
|
+
exitSpan: true,
|
|
86
|
+
});
|
|
87
|
+
var id = span && span.transaction.id;
|
|
88
|
+
var method = params && params.method;
|
|
89
|
+
var path = params && params.path;
|
|
90
|
+
|
|
91
|
+
agent.logger.debug(
|
|
92
|
+
'intercepted call to elasticsearch.Transport.prototype.request %o',
|
|
93
|
+
{ id, method, path },
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
if (span && method && path) {
|
|
97
|
+
span.name = `Elasticsearch: ${method} ${path}`;
|
|
98
|
+
|
|
99
|
+
// Set DB context.
|
|
100
|
+
const dbContext = {
|
|
101
|
+
type: 'elasticsearch',
|
|
102
|
+
};
|
|
103
|
+
const statement = getElasticsearchDbStatement(
|
|
104
|
+
path,
|
|
105
|
+
params && params.body,
|
|
106
|
+
elasticsearchCaptureBodyUrlsRegExp,
|
|
107
|
+
);
|
|
108
|
+
if (statement) {
|
|
109
|
+
dbContext.statement = statement;
|
|
110
|
+
}
|
|
111
|
+
span.setDbContext(dbContext);
|
|
112
|
+
|
|
113
|
+
// Get the remote host information from elasticsearch Transport options.
|
|
114
|
+
const targetUrl = getTargetUrlFromTransportConfig(this._config);
|
|
115
|
+
let port = targetUrl && targetUrl.port;
|
|
116
|
+
if (!port && targetUrl) {
|
|
117
|
+
port = DEFAULT_PORT_FROM_PROTO[targetUrl.protocol];
|
|
118
|
+
}
|
|
119
|
+
span._setDestinationContext(
|
|
120
|
+
getDBDestination(targetUrl && targetUrl.hostname, port),
|
|
121
|
+
);
|
|
122
|
+
if (targetUrl) {
|
|
123
|
+
targetUrl.pathname = path;
|
|
124
|
+
targetUrl.search = new URLSearchParams(params.query).toString();
|
|
125
|
+
span.setHttpContext({
|
|
126
|
+
url: targetUrl.toString(),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const parentRunContext = ins.currRunContext();
|
|
131
|
+
const spanRunContext = parentRunContext.enterSpan(span);
|
|
132
|
+
if (typeof cb === 'function') {
|
|
133
|
+
var args = Array.prototype.slice.call(arguments);
|
|
134
|
+
args[1] = function () {
|
|
135
|
+
span.end();
|
|
136
|
+
ins.withRunContext(parentRunContext, cb, this, ...arguments);
|
|
137
|
+
};
|
|
138
|
+
return ins.withRunContext(spanRunContext, original, this, ...args);
|
|
139
|
+
} else {
|
|
140
|
+
const originalPromise = ins.withRunContext(
|
|
141
|
+
spanRunContext,
|
|
142
|
+
original,
|
|
143
|
+
this,
|
|
144
|
+
...arguments,
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const descriptors = Object.getOwnPropertyDescriptors(originalPromise);
|
|
148
|
+
delete descriptors.domain;
|
|
149
|
+
|
|
150
|
+
const inspectedPromise = originalPromise.then(
|
|
151
|
+
function (value) {
|
|
152
|
+
span.end();
|
|
153
|
+
return value;
|
|
154
|
+
},
|
|
155
|
+
function (err) {
|
|
156
|
+
span.end();
|
|
157
|
+
throw err;
|
|
158
|
+
},
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
Object.defineProperties(inspectedPromise, descriptors);
|
|
162
|
+
|
|
163
|
+
// we have to properly end the span when user aborts the request
|
|
164
|
+
shimmer.wrap(
|
|
165
|
+
inspectedPromise,
|
|
166
|
+
'abort',
|
|
167
|
+
function wrapAbort(originalAbort) {
|
|
168
|
+
return function wrappedAbort() {
|
|
169
|
+
if (span.ended) return;
|
|
170
|
+
agent.logger.debug(
|
|
171
|
+
'intercepted call to elasticsearch.Transport.request.abort %o',
|
|
172
|
+
{ id, method, path },
|
|
173
|
+
);
|
|
174
|
+
const originalReturn = originalAbort.apply(this, args);
|
|
175
|
+
span.end();
|
|
176
|
+
return originalReturn;
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
return inspectedPromise;
|
|
182
|
+
}
|
|
183
|
+
} else {
|
|
184
|
+
agent.logger.debug('could not instrument elasticsearch request %o', {
|
|
185
|
+
id,
|
|
186
|
+
});
|
|
187
|
+
return original.apply(this, arguments);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
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 semver = require('semver');
|
|
10
|
+
|
|
11
|
+
const shimmer = require('../shimmer');
|
|
12
|
+
|
|
13
|
+
module.exports = function (expressGraphql, agent, { version, enabled }) {
|
|
14
|
+
if (!enabled) {
|
|
15
|
+
return expressGraphql;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (semver.satisfies(version, '>=0.10.0 <0.13.0')) {
|
|
19
|
+
// https://github.com/graphql/express-graphql/pull/626 changed `graphqlHTTP`
|
|
20
|
+
// to no longer be the top-level export:
|
|
21
|
+
// {
|
|
22
|
+
// graphqlHTTP: [Function: graphqlHTTP],
|
|
23
|
+
// getGraphQLParams: [AsyncFunction: getGraphQLParams]
|
|
24
|
+
// }
|
|
25
|
+
shimmer.wrap(expressGraphql, 'graphqlHTTP', wrapGraphqlHTTP);
|
|
26
|
+
return expressGraphql;
|
|
27
|
+
} else if (
|
|
28
|
+
semver.satisfies(version, '>=0.6.1 <0.10.0') &&
|
|
29
|
+
typeof expressGraphql === 'function'
|
|
30
|
+
) {
|
|
31
|
+
// Up to and including 0.9.x, `require('express-graphql')` is:
|
|
32
|
+
// [Function: graphqlHTTP] {
|
|
33
|
+
// getGraphQLParams: [AsyncFunction: getGraphQLParams]
|
|
34
|
+
// }
|
|
35
|
+
const wrappedGraphqlHTTP = wrapGraphqlHTTP(expressGraphql);
|
|
36
|
+
for (const key of Object.keys(expressGraphql)) {
|
|
37
|
+
wrappedGraphqlHTTP[key] = expressGraphql[key];
|
|
38
|
+
}
|
|
39
|
+
return wrappedGraphqlHTTP;
|
|
40
|
+
} else {
|
|
41
|
+
agent.logger.debug(
|
|
42
|
+
'express-graphql@%s not supported: skipping instrumentation',
|
|
43
|
+
version,
|
|
44
|
+
);
|
|
45
|
+
return expressGraphql;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function wrapGraphqlHTTP(origGraphqlHTTP) {
|
|
49
|
+
return function wrappedGraphqlHTTP() {
|
|
50
|
+
var orig = origGraphqlHTTP.apply(this, arguments);
|
|
51
|
+
|
|
52
|
+
if (typeof orig !== 'function') {
|
|
53
|
+
return orig;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Express is very particular with the number of arguments!
|
|
57
|
+
return function (req, res) {
|
|
58
|
+
var trans = agent._instrumentation.currTransaction();
|
|
59
|
+
if (trans) {
|
|
60
|
+
trans._graphqlRoute = true;
|
|
61
|
+
}
|
|
62
|
+
return orig.apply(this, arguments);
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
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 shimmer = require('../shimmer');
|
|
10
|
+
|
|
11
|
+
module.exports = function (expressQueue, agent, { enabled }) {
|
|
12
|
+
if (!enabled) return expressQueue;
|
|
13
|
+
|
|
14
|
+
var ins = agent._instrumentation;
|
|
15
|
+
|
|
16
|
+
return function wrappedExpressQueue(config) {
|
|
17
|
+
var result = expressQueue(config);
|
|
18
|
+
shimmer.wrap(result.queue, 'createJob', function (original) {
|
|
19
|
+
return function (job) {
|
|
20
|
+
if (job.next) {
|
|
21
|
+
job.next = ins.bindFunction(job.next);
|
|
22
|
+
}
|
|
23
|
+
return original.apply(this, arguments);
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
};
|