@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,100 @@
|
|
|
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
|
+
// This is a copy of load-source-map@2.0.0. It is inlined in elastic-apm-node
|
|
10
|
+
// solely to update its `source-map` dependency to fix
|
|
11
|
+
// https://github.com/elastic/apm-agent-nodejs/issues/2589
|
|
12
|
+
// If/when there is a new release of load-source-map with
|
|
13
|
+
// https://github.com/rexxars/load-source-map/pull/6
|
|
14
|
+
// then we could move back to using load-source-map as a dependency.
|
|
15
|
+
|
|
16
|
+
var fs = require('fs');
|
|
17
|
+
var path = require('path');
|
|
18
|
+
var SourceMapConsumer = require('source-map').SourceMapConsumer;
|
|
19
|
+
|
|
20
|
+
var INLINE_SOURCEMAP_REGEX = /^data:application\/json[^,]+base64,/;
|
|
21
|
+
var SOURCEMAP_REGEX =
|
|
22
|
+
/(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^*]+?)[ \t]*(?:\*\/)[ \t]*$)/;
|
|
23
|
+
var READ_FILE_OPTS = { encoding: 'utf8' };
|
|
24
|
+
|
|
25
|
+
module.exports = function readSourceMap(filename, cb) {
|
|
26
|
+
fs.readFile(filename, READ_FILE_OPTS, function (err, sourceFile) {
|
|
27
|
+
if (err) {
|
|
28
|
+
return cb(err);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Look for a sourcemap URL
|
|
32
|
+
var sourceMapUrl = resolveSourceMapUrl(sourceFile, path.dirname(filename));
|
|
33
|
+
if (!sourceMapUrl) {
|
|
34
|
+
return cb();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// If it's an inline map, decode it and pass it through the same consumer factory
|
|
38
|
+
if (isInlineMap(sourceMapUrl)) {
|
|
39
|
+
return onMapRead(null, decodeInlineMap(sourceMapUrl));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Load actual source map from given path
|
|
43
|
+
fs.readFile(sourceMapUrl, READ_FILE_OPTS, onMapRead);
|
|
44
|
+
|
|
45
|
+
function onMapRead(readErr, sourceMap) {
|
|
46
|
+
if (readErr) {
|
|
47
|
+
readErr.message =
|
|
48
|
+
'Error reading sourcemap for file "' +
|
|
49
|
+
filename +
|
|
50
|
+
'":\n' +
|
|
51
|
+
readErr.message;
|
|
52
|
+
return cb(readErr);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
new SourceMapConsumer(sourceMap).then(function onConsumerReady(
|
|
57
|
+
consumer,
|
|
58
|
+
) {
|
|
59
|
+
return cb(null, consumer);
|
|
60
|
+
}, onConsumerError);
|
|
61
|
+
} catch (parseErr) {
|
|
62
|
+
onConsumerError(parseErr);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function onConsumerError(parseErr) {
|
|
67
|
+
parseErr.message =
|
|
68
|
+
'Error parsing sourcemap for file "' +
|
|
69
|
+
filename +
|
|
70
|
+
'":\n' +
|
|
71
|
+
parseErr.message;
|
|
72
|
+
return cb(parseErr);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
function resolveSourceMapUrl(sourceFile, sourcePath) {
|
|
78
|
+
var lines = sourceFile.split(/\r?\n/);
|
|
79
|
+
var sourceMapUrl = null;
|
|
80
|
+
for (var i = lines.length - 1; i >= 0 && !sourceMapUrl; i--) {
|
|
81
|
+
sourceMapUrl = lines[i].match(SOURCEMAP_REGEX);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!sourceMapUrl) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return isInlineMap(sourceMapUrl[1])
|
|
89
|
+
? sourceMapUrl[1]
|
|
90
|
+
: path.resolve(sourcePath, sourceMapUrl[1]);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function isInlineMap(url) {
|
|
94
|
+
return INLINE_SOURCEMAP_REGEX.test(url);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function decodeInlineMap(data) {
|
|
98
|
+
var rawData = data.slice(data.indexOf(',') + 1);
|
|
99
|
+
return Buffer.from(rawData, 'base64').toString();
|
|
100
|
+
}
|
package/lib/logging.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
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
|
+
* @typedef {Object} Logger
|
|
11
|
+
* @property {function(Record<string, any> | string, ...any): undefined} fatal
|
|
12
|
+
* @property {function(Record<string, any> | string, ...any): undefined} error
|
|
13
|
+
* @property {function(Record<string, any> | string, ...any): undefined} warn
|
|
14
|
+
* @property {function(Record<string, any> | string, ...any): undefined} info
|
|
15
|
+
* @property {function(Record<string, any> | string, ...any): undefined} debug
|
|
16
|
+
* @property {function(Record<string, any> | string, ...any): undefined} trace
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// Internal logging for the Elastic APM Node.js Agent.
|
|
20
|
+
//
|
|
21
|
+
// Promised interface:
|
|
22
|
+
// - The amount of logging can be controlled via the `logLevel` config var,
|
|
23
|
+
// and via the `log_level` central config var.
|
|
24
|
+
// - A custom logger can be provided via the `logging` config var.
|
|
25
|
+
//
|
|
26
|
+
// Nothing else about this package's logging (e.g. structure or the particular
|
|
27
|
+
// message text) is promised/stable.
|
|
28
|
+
//
|
|
29
|
+
// Per https://github.com/elastic/apm/blob/main/specs/agents/logging.md
|
|
30
|
+
// the valid log levels are:
|
|
31
|
+
// - trace
|
|
32
|
+
// - debug
|
|
33
|
+
// - info (default)
|
|
34
|
+
// - warning
|
|
35
|
+
// - error
|
|
36
|
+
// - critical
|
|
37
|
+
// - off
|
|
38
|
+
//
|
|
39
|
+
// Before this spec, the supported levels were:
|
|
40
|
+
// - trace
|
|
41
|
+
// - debug
|
|
42
|
+
// - info (default)
|
|
43
|
+
// - warn - both "warn" and "warning" will be supported for backward compat
|
|
44
|
+
// - error
|
|
45
|
+
// - fatal - mapped to "critical" for backward compat
|
|
46
|
+
|
|
47
|
+
const { ecsFormat } = require('@elastic/ecs-pino-format');
|
|
48
|
+
var pino = require('pino');
|
|
49
|
+
var semver = require('semver');
|
|
50
|
+
|
|
51
|
+
const DEFAULT_LOG_LEVEL = 'info';
|
|
52
|
+
|
|
53
|
+
// Used to mark loggers created here, for use by `isLoggerCustom()`.
|
|
54
|
+
const LOGGER_IS_OURS_SYM = Symbol('ElasticAPMLoggerIsOurs');
|
|
55
|
+
|
|
56
|
+
const PINO_LEVEL_FROM_LEVEL_NAME = {
|
|
57
|
+
trace: 'trace',
|
|
58
|
+
debug: 'debug',
|
|
59
|
+
info: 'info',
|
|
60
|
+
warning: 'warn',
|
|
61
|
+
warn: 'warn', // Supported for backwards compat
|
|
62
|
+
error: 'error',
|
|
63
|
+
critical: 'fatal',
|
|
64
|
+
fatal: 'fatal', // Supported for backwards compat
|
|
65
|
+
off: 'silent',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// SafePinoDestWrapper provides a pino destination that will pass logging calls
|
|
69
|
+
// to a given `customLogger`. The custom logger must have the following API:
|
|
70
|
+
//
|
|
71
|
+
// - `.trace(string)`
|
|
72
|
+
// - `.debug(string)`
|
|
73
|
+
// - `.info(string)`
|
|
74
|
+
// - `.warn(string)`
|
|
75
|
+
// - `.error(string)`
|
|
76
|
+
// - `.fatal(string)`
|
|
77
|
+
//
|
|
78
|
+
// The limitation of this wrapping is that structured data fields are *not*
|
|
79
|
+
// passed on to the custom logger. I.e. this is a fallback mechanism.
|
|
80
|
+
class SafePinoDestWrapper {
|
|
81
|
+
constructor(customLogger) {
|
|
82
|
+
this.customLogger = customLogger;
|
|
83
|
+
this.logFnNameFromLastLevel = pino.levels.labels;
|
|
84
|
+
this[Symbol.for('pino.metadata')] = true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
write(s) {
|
|
88
|
+
const { lastMsg, lastLevel } = this;
|
|
89
|
+
const logFnName = this.logFnNameFromLastLevel[lastLevel];
|
|
90
|
+
this.customLogger[logFnName](lastMsg);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Creates a pino logger for the agent.
|
|
96
|
+
*
|
|
97
|
+
* By default `createLogger()` will return a pino logger that logs to stdout
|
|
98
|
+
* in ecs-logging format, set to the "info" level.
|
|
99
|
+
*
|
|
100
|
+
* @param {String} levelName - Optional, default "info". It is meant to be one
|
|
101
|
+
* of the log levels specified in the top of file comment. For backward
|
|
102
|
+
* compatibility it falls back to "trace".
|
|
103
|
+
* @param {Object} customLogger - Optional. A custom logger object to which
|
|
104
|
+
* log messages will be passed. It must provide
|
|
105
|
+
* trace/debug/info/warn/error/fatal methods that take a string argument.
|
|
106
|
+
*
|
|
107
|
+
* Internally the agent uses structured logging using the pino API
|
|
108
|
+
* (https://getpino.io/#/docs/api?id=logger). However, with a custom logger,
|
|
109
|
+
* log record fields other than the *message* are dropped, to avoid issues
|
|
110
|
+
* with incompatible logger APIs.
|
|
111
|
+
*
|
|
112
|
+
* As a special case, if the provided logger is a *pino logger instance*,
|
|
113
|
+
* then it will be used directly.
|
|
114
|
+
*
|
|
115
|
+
* @param {string} [levelName=info] log level we want for the created logger
|
|
116
|
+
* @param {Logger} [customLogger] custom logger object provided by the user
|
|
117
|
+
* @returns {Logger}
|
|
118
|
+
*/
|
|
119
|
+
function createLogger(levelName, customLogger) {
|
|
120
|
+
let dest;
|
|
121
|
+
const serializers = {
|
|
122
|
+
err: pino.stdSerializers.err,
|
|
123
|
+
req: pino.stdSerializers.req,
|
|
124
|
+
res: pino.stdSerializers.res,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
if (!levelName) {
|
|
128
|
+
levelName = DEFAULT_LOG_LEVEL;
|
|
129
|
+
}
|
|
130
|
+
let pinoLevel = PINO_LEVEL_FROM_LEVEL_NAME[levelName];
|
|
131
|
+
if (!pinoLevel) {
|
|
132
|
+
// For backwards compat, support an earlier bug where an unknown log level
|
|
133
|
+
// was accepted.
|
|
134
|
+
// TODO: Consider being more strict on this for v4.0.0.
|
|
135
|
+
pinoLevel = 'trace';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (customLogger) {
|
|
139
|
+
// Is this a pino logger? If so, it supports the API the agent requires and
|
|
140
|
+
// can be used directly. We must add our custom serializers.
|
|
141
|
+
if (Symbol.for('pino.serializers') in customLogger) {
|
|
142
|
+
// Pino added `options` second arg to `logger.child` in 6.12.0.
|
|
143
|
+
if (semver.gte(customLogger.version, '6.12.0')) {
|
|
144
|
+
return customLogger.child({}, { serializers });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return customLogger.child({
|
|
148
|
+
serializers,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Otherwise, we fallback to wrapping the provided logger such that the
|
|
153
|
+
// agent can use the pino logger API without breaking. The limitation is
|
|
154
|
+
// that only the log *message* is logged. Extra structured fields are
|
|
155
|
+
// dropped.
|
|
156
|
+
dest = new SafePinoDestWrapper(customLogger);
|
|
157
|
+
// Our wrapping logger level should be 'trace', to pass through all
|
|
158
|
+
// messages to the wrapped logger.
|
|
159
|
+
pinoLevel = 'trace';
|
|
160
|
+
} else {
|
|
161
|
+
// Log to stdout, the same default as pino itself.
|
|
162
|
+
dest = pino.destination(1);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const logger = pino(
|
|
166
|
+
{
|
|
167
|
+
name: 'elastic-apm-node',
|
|
168
|
+
base: {}, // Don't want pid and hostname fields.
|
|
169
|
+
level: pinoLevel,
|
|
170
|
+
serializers,
|
|
171
|
+
...ecsFormat({ apmIntegration: false }),
|
|
172
|
+
},
|
|
173
|
+
dest,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
if (!customLogger) {
|
|
177
|
+
logger[LOGGER_IS_OURS_SYM] = true; // used for isLoggerCustom()
|
|
178
|
+
}
|
|
179
|
+
return logger;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Returns true if the logger is not ours
|
|
184
|
+
*
|
|
185
|
+
* @param {Logger} logger
|
|
186
|
+
* @returns {boolean}
|
|
187
|
+
*/
|
|
188
|
+
function isLoggerCustom(logger) {
|
|
189
|
+
return !logger[LOGGER_IS_OURS_SYM];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Adjust the level on the given logger.
|
|
194
|
+
*
|
|
195
|
+
* @param {Logger} logger
|
|
196
|
+
* @param {string} levelName
|
|
197
|
+
*/
|
|
198
|
+
function setLogLevel(logger, levelName) {
|
|
199
|
+
const pinoLevel = PINO_LEVEL_FROM_LEVEL_NAME[levelName];
|
|
200
|
+
if (!pinoLevel) {
|
|
201
|
+
logger.warn('unknown log levelName "%s": cannot setLogLevel', levelName);
|
|
202
|
+
} else {
|
|
203
|
+
logger.level = pinoLevel;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = {
|
|
208
|
+
DEFAULT_LOG_LEVEL,
|
|
209
|
+
createLogger,
|
|
210
|
+
isLoggerCustom,
|
|
211
|
+
setLogLevel,
|
|
212
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
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 assert = require('assert');
|
|
10
|
+
|
|
11
|
+
const MetricsRegistry = require('./registry');
|
|
12
|
+
const { createQueueMetrics } = require('./queue');
|
|
13
|
+
|
|
14
|
+
const registrySymbol = Symbol('metrics-registry');
|
|
15
|
+
const agentSymbol = Symbol('metrics-agent');
|
|
16
|
+
|
|
17
|
+
class NoopLogger {
|
|
18
|
+
debug() {}
|
|
19
|
+
error() {}
|
|
20
|
+
fatal() {}
|
|
21
|
+
info() {}
|
|
22
|
+
trace() {}
|
|
23
|
+
warn() {}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class Metrics {
|
|
27
|
+
constructor(agent) {
|
|
28
|
+
this[agentSymbol] = agent;
|
|
29
|
+
this[registrySymbol] = null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
start(refTimers) {
|
|
33
|
+
const metricsInterval = this[agentSymbol]._conf.metricsInterval;
|
|
34
|
+
assert(
|
|
35
|
+
metricsInterval > 0,
|
|
36
|
+
'Metrics.start() should not be called if metricsInterval <= 0',
|
|
37
|
+
);
|
|
38
|
+
this[registrySymbol] = new MetricsRegistry(this[agentSymbol], {
|
|
39
|
+
reporterOptions: {
|
|
40
|
+
defaultReportingIntervalInSeconds: metricsInterval,
|
|
41
|
+
enabled: true,
|
|
42
|
+
unrefTimers: !refTimers,
|
|
43
|
+
logger: new NoopLogger(),
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
stop() {
|
|
49
|
+
if (this[registrySymbol]) {
|
|
50
|
+
this[registrySymbol].shutdown();
|
|
51
|
+
this[registrySymbol] = null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getOrCreateCounter(...args) {
|
|
56
|
+
if (!this[registrySymbol]) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
return this[registrySymbol].getOrCreateCounter(...args);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
incrementCounter(name, dimensions, amount = 1) {
|
|
63
|
+
if (!this[registrySymbol]) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.getOrCreateCounter(name, dimensions).inc(amount);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
getOrCreateGauge(...args) {
|
|
71
|
+
if (!this[registrySymbol]) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
return this[registrySymbol].getOrCreateGauge(...args);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// factory function for creating a queue metrics collector
|
|
78
|
+
//
|
|
79
|
+
// called from instrumentation, only when the agent receives a queue message
|
|
80
|
+
createQueueMetricsCollector(queueOrTopicName) {
|
|
81
|
+
if (!this[registrySymbol]) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const collector = createQueueMetrics(
|
|
85
|
+
queueOrTopicName,
|
|
86
|
+
this[registrySymbol],
|
|
87
|
+
);
|
|
88
|
+
return collector;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = Metrics;
|
|
@@ -0,0 +1,40 @@
|
|
|
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 os = require('os');
|
|
10
|
+
|
|
11
|
+
const Stats = require('./stats');
|
|
12
|
+
|
|
13
|
+
module.exports = function createSystemMetrics(registry) {
|
|
14
|
+
// Base system metrics
|
|
15
|
+
registry.getOrCreateGauge(
|
|
16
|
+
'system.cpu.total.norm.pct',
|
|
17
|
+
require('./system-cpu'),
|
|
18
|
+
);
|
|
19
|
+
registry.getOrCreateGauge('system.memory.total', () => os.totalmem());
|
|
20
|
+
registry.getOrCreateGauge('system.memory.actual.free', () => os.freemem());
|
|
21
|
+
|
|
22
|
+
// Process metrics
|
|
23
|
+
const stats = new Stats();
|
|
24
|
+
registry.registerCollector(stats);
|
|
25
|
+
|
|
26
|
+
const metrics = [
|
|
27
|
+
'system.process.cpu.total.norm.pct',
|
|
28
|
+
'system.process.cpu.system.norm.pct',
|
|
29
|
+
'system.process.cpu.user.norm.pct',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
for (const metric of metrics) {
|
|
33
|
+
registry.getOrCreateGauge(metric, () => stats.toJSON()[metric]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
registry.getOrCreateGauge(
|
|
37
|
+
'system.process.memory.rss.bytes',
|
|
38
|
+
() => process.memoryUsage().rss,
|
|
39
|
+
);
|
|
40
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
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 os = require('os');
|
|
10
|
+
|
|
11
|
+
const processTop = require('./process-top')();
|
|
12
|
+
|
|
13
|
+
const cpus = os.cpus();
|
|
14
|
+
|
|
15
|
+
module.exports = function processCPUUsage() {
|
|
16
|
+
const cpu = processTop.cpu();
|
|
17
|
+
return {
|
|
18
|
+
total: cpu.percent / cpus.length,
|
|
19
|
+
user: cpu.user / cpu.time / cpus.length,
|
|
20
|
+
system: cpu.system / cpu.time / cpus.length,
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
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 'process-top' project copyright by
|
|
11
|
+
* Mathias Buus. It has been modified slightly to be used in the current
|
|
12
|
+
* context and where possible changes have been contributed back to the
|
|
13
|
+
* original project.
|
|
14
|
+
*
|
|
15
|
+
* https://github.com/mafintosh/process-top
|
|
16
|
+
*
|
|
17
|
+
* Original file:
|
|
18
|
+
*
|
|
19
|
+
* https://github.com/mafintosh/process-top/blob/master/index.js
|
|
20
|
+
*
|
|
21
|
+
* License:
|
|
22
|
+
*
|
|
23
|
+
* The MIT License (MIT)
|
|
24
|
+
*
|
|
25
|
+
* Copyright (c) 2018 Mathias Buus
|
|
26
|
+
*
|
|
27
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
28
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
29
|
+
* in the Software without restriction, including without limitation the rights
|
|
30
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
31
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
32
|
+
* furnished to do so, subject to the following conditions:
|
|
33
|
+
*
|
|
34
|
+
* The above copyright notice and this permission notice shall be included in
|
|
35
|
+
* all copies or substantial portions of the Software.
|
|
36
|
+
*
|
|
37
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
38
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
39
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
40
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
41
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
42
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
43
|
+
* THE SOFTWARE.
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
// const os = require('os')
|
|
48
|
+
// const p = require('prettier-bytes')
|
|
49
|
+
// const eld = require('event-loop-delay')
|
|
50
|
+
|
|
51
|
+
module.exports = top;
|
|
52
|
+
|
|
53
|
+
// function top (opts) {
|
|
54
|
+
function top() {
|
|
55
|
+
// NOTE: Replacing line above
|
|
56
|
+
// if (!opts) opts = {}
|
|
57
|
+
|
|
58
|
+
// const tick = opts.interval || 1000
|
|
59
|
+
// const started = Date.now()
|
|
60
|
+
// const interval = setInterval(perSecond, tick)
|
|
61
|
+
// const win = [{ time: process.hrtime(), cpu: process.cpuUsage(), delay: 0 }, null, null, null]
|
|
62
|
+
const win = [
|
|
63
|
+
{ time: process.hrtime(), cpu: process.cpuUsage() },
|
|
64
|
+
null,
|
|
65
|
+
null,
|
|
66
|
+
null,
|
|
67
|
+
]; // NOTE: Replacing line above
|
|
68
|
+
// const loopSampler = eld()
|
|
69
|
+
|
|
70
|
+
let sec = 1;
|
|
71
|
+
|
|
72
|
+
// interval.unref()
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
// pid: process.pid,
|
|
76
|
+
// command: process.argv.join(' '),
|
|
77
|
+
// started,
|
|
78
|
+
// time () {
|
|
79
|
+
// return Date.now() - started
|
|
80
|
+
// },
|
|
81
|
+
// delay () {
|
|
82
|
+
// const btm = oldest()
|
|
83
|
+
// const timeDelta = process.hrtime(win[btm].time)
|
|
84
|
+
// const ms = timeDelta[0] * 1e3 + Math.floor(timeDelta[1] / 1e6)
|
|
85
|
+
// return Math.floor((loopSampler.delay - win[btm].delay) / (ms / tick))
|
|
86
|
+
// },
|
|
87
|
+
cpu() {
|
|
88
|
+
const btm = oldest();
|
|
89
|
+
const cpuDelta = process.cpuUsage(win[btm].cpu);
|
|
90
|
+
const timeDelta = process.hrtime(win[btm].time);
|
|
91
|
+
const us = timeDelta[0] * 1e6 + timeDelta[1] / 1e3;
|
|
92
|
+
perSecond(); // NOTE: Added to skip timer and update at each check
|
|
93
|
+
return {
|
|
94
|
+
time: us,
|
|
95
|
+
percent: (cpuDelta.system + cpuDelta.user) / us,
|
|
96
|
+
system: cpuDelta.system,
|
|
97
|
+
user: cpuDelta.user,
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
// memory () {
|
|
101
|
+
// const mem = process.memoryUsage()
|
|
102
|
+
// const total = os.totalmem()
|
|
103
|
+
// return {
|
|
104
|
+
// percent: mem.rss / total,
|
|
105
|
+
// rss: mem.rss,
|
|
106
|
+
// total,
|
|
107
|
+
// heapPercent: mem.heapUsed / mem.heapTotal,
|
|
108
|
+
// heapUsed: mem.heapUsed,
|
|
109
|
+
// heapTotal: mem.heapTotal,
|
|
110
|
+
// external: mem.external
|
|
111
|
+
// }
|
|
112
|
+
// },
|
|
113
|
+
// loadavg () {
|
|
114
|
+
// return os.loadavg()
|
|
115
|
+
// },
|
|
116
|
+
// destroy () {
|
|
117
|
+
// clearInterval(interval)
|
|
118
|
+
// },
|
|
119
|
+
// toString () {
|
|
120
|
+
// const mem = this.memory()
|
|
121
|
+
// return `cpu: ${pct(this.cpu().percent)} | rss: ${p(mem.rss)} (${pct(mem.percent)}) | heap: ${p(mem.heapUsed)} / ${p(mem.heapTotal)} (${pct(mem.heapPercent)}) | ext: ${p(mem.external)} | delay: ${this.delay()} ms | ${time(this.time())} | loadavg: ${os.loadavg().map(fixed2).join(', ')}`
|
|
122
|
+
// }
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
function oldest() {
|
|
126
|
+
let btm = (sec - 4) & 3;
|
|
127
|
+
while (!win[btm]) btm = (btm + 1) & 3;
|
|
128
|
+
return btm;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function perSecond() {
|
|
132
|
+
const ptr = sec++ & 3;
|
|
133
|
+
// win[ptr] = { time: process.hrtime(), cpu: process.cpuUsage(), delay: loopSampler.delay }
|
|
134
|
+
win[ptr] = { time: process.hrtime(), cpu: process.cpuUsage() }; // NOTE: Replacing line above
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// function pct (n) {
|
|
139
|
+
// return (100 * n).toFixed(1) + '%'
|
|
140
|
+
// }
|
|
141
|
+
|
|
142
|
+
// function fixed2 (n) {
|
|
143
|
+
// return n.toFixed(2)
|
|
144
|
+
// }
|
|
145
|
+
|
|
146
|
+
// function time (n) {
|
|
147
|
+
// let secs = Math.floor(n / 1000)
|
|
148
|
+
// let hours = Math.floor(secs / 3600)
|
|
149
|
+
// secs -= hours * 3600
|
|
150
|
+
// let mins = Math.floor(secs / 60)
|
|
151
|
+
// secs -= mins * 60
|
|
152
|
+
// return pad(hours) + ':' + pad(mins) + ':' + pad(secs)
|
|
153
|
+
// }
|
|
154
|
+
|
|
155
|
+
// function pad (n) {
|
|
156
|
+
// return n < 10 ? '0' + n : '' + n
|
|
157
|
+
// }
|
|
@@ -0,0 +1,34 @@
|
|
|
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 processCpu = require('./process-cpu');
|
|
10
|
+
|
|
11
|
+
class Stats {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.stats = {
|
|
14
|
+
'system.process.cpu.total.norm.pct': 0,
|
|
15
|
+
'system.process.cpu.system.norm.pct': 0,
|
|
16
|
+
'system.process.cpu.user.norm.pct': 0,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
toJSON() {
|
|
21
|
+
return this.stats;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
collect(cb) {
|
|
25
|
+
const cpu = processCpu();
|
|
26
|
+
this.stats['system.process.cpu.total.norm.pct'] = cpu.total;
|
|
27
|
+
this.stats['system.process.cpu.system.norm.pct'] = cpu.system;
|
|
28
|
+
this.stats['system.process.cpu.user.norm.pct'] = cpu.user;
|
|
29
|
+
|
|
30
|
+
if (cb) process.nextTick(cb);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = Stats;
|