@depup/elastic-apm-node 4.15.0-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/LICENSE +26 -0
  2. package/NOTICE.md +442 -0
  3. package/README.md +48 -0
  4. package/changes.json +78 -0
  5. package/index.d.ts +398 -0
  6. package/index.js +11 -0
  7. package/lib/InflightEventSet.js +53 -0
  8. package/lib/activation-method.js +119 -0
  9. package/lib/agent.js +941 -0
  10. package/lib/apm-client/apm-client.js +313 -0
  11. package/lib/apm-client/http-apm-client/CHANGELOG.md +271 -0
  12. package/lib/apm-client/http-apm-client/README.md +485 -0
  13. package/lib/apm-client/http-apm-client/central-config.js +41 -0
  14. package/lib/apm-client/http-apm-client/container-info.js +111 -0
  15. package/lib/apm-client/http-apm-client/detect-hostname.js +96 -0
  16. package/lib/apm-client/http-apm-client/index.js +1975 -0
  17. package/lib/apm-client/http-apm-client/logging.js +31 -0
  18. package/lib/apm-client/http-apm-client/ndjson.js +20 -0
  19. package/lib/apm-client/http-apm-client/truncate.js +434 -0
  20. package/lib/apm-client/noop-apm-client.js +73 -0
  21. package/lib/async-hooks-polyfill.js +58 -0
  22. package/lib/cloud-metadata/aws.js +175 -0
  23. package/lib/cloud-metadata/azure.js +123 -0
  24. package/lib/cloud-metadata/callback-coordination.js +159 -0
  25. package/lib/cloud-metadata/gcp.js +133 -0
  26. package/lib/cloud-metadata/index.js +175 -0
  27. package/lib/config/config.js +458 -0
  28. package/lib/config/normalizers.js +701 -0
  29. package/lib/config/schema.js +1007 -0
  30. package/lib/constants.js +35 -0
  31. package/lib/errors.js +303 -0
  32. package/lib/filters/sanitize-field-names.js +69 -0
  33. package/lib/http-request.js +249 -0
  34. package/lib/instrumentation/azure-functions.js +519 -0
  35. package/lib/instrumentation/context.js +56 -0
  36. package/lib/instrumentation/dropped-spans-stats.js +112 -0
  37. package/lib/instrumentation/elasticsearch-shared.js +63 -0
  38. package/lib/instrumentation/express-utils.js +91 -0
  39. package/lib/instrumentation/generic-span.js +322 -0
  40. package/lib/instrumentation/http-shared.js +424 -0
  41. package/lib/instrumentation/ids.js +39 -0
  42. package/lib/instrumentation/index.js +1127 -0
  43. package/lib/instrumentation/modules/@apollo/server.js +30 -0
  44. package/lib/instrumentation/modules/@aws-sdk/client-dynamodb.js +143 -0
  45. package/lib/instrumentation/modules/@aws-sdk/client-s3.js +230 -0
  46. package/lib/instrumentation/modules/@aws-sdk/client-sns.js +197 -0
  47. package/lib/instrumentation/modules/@aws-sdk/client-sqs.js +336 -0
  48. package/lib/instrumentation/modules/@elastic/elasticsearch.js +343 -0
  49. package/lib/instrumentation/modules/@hapi/hapi.js +221 -0
  50. package/lib/instrumentation/modules/@opentelemetry/api.js +86 -0
  51. package/lib/instrumentation/modules/@opentelemetry/sdk-metrics.js +79 -0
  52. package/lib/instrumentation/modules/@redis/client/dist/lib/client/commands-queue.js +178 -0
  53. package/lib/instrumentation/modules/@redis/client/dist/lib/client/index.js +49 -0
  54. package/lib/instrumentation/modules/@smithy/smithy-client.js +198 -0
  55. package/lib/instrumentation/modules/_lambda-handler.js +40 -0
  56. package/lib/instrumentation/modules/apollo-server-core.js +49 -0
  57. package/lib/instrumentation/modules/aws-sdk/dynamodb.js +155 -0
  58. package/lib/instrumentation/modules/aws-sdk/s3.js +184 -0
  59. package/lib/instrumentation/modules/aws-sdk/sns.js +232 -0
  60. package/lib/instrumentation/modules/aws-sdk/sqs.js +361 -0
  61. package/lib/instrumentation/modules/aws-sdk.js +76 -0
  62. package/lib/instrumentation/modules/bluebird.js +93 -0
  63. package/lib/instrumentation/modules/cassandra-driver.js +280 -0
  64. package/lib/instrumentation/modules/elasticsearch.js +191 -0
  65. package/lib/instrumentation/modules/express-graphql.js +66 -0
  66. package/lib/instrumentation/modules/express-queue.js +28 -0
  67. package/lib/instrumentation/modules/express.js +162 -0
  68. package/lib/instrumentation/modules/fastify.js +172 -0
  69. package/lib/instrumentation/modules/finalhandler.js +41 -0
  70. package/lib/instrumentation/modules/generic-pool.js +85 -0
  71. package/lib/instrumentation/modules/graphql.js +256 -0
  72. package/lib/instrumentation/modules/handlebars.js +22 -0
  73. package/lib/instrumentation/modules/http.js +112 -0
  74. package/lib/instrumentation/modules/http2.js +320 -0
  75. package/lib/instrumentation/modules/https.js +68 -0
  76. package/lib/instrumentation/modules/ioredis.js +94 -0
  77. package/lib/instrumentation/modules/jade.js +18 -0
  78. package/lib/instrumentation/modules/kafkajs.js +476 -0
  79. package/lib/instrumentation/modules/knex.js +91 -0
  80. package/lib/instrumentation/modules/koa-router.js +74 -0
  81. package/lib/instrumentation/modules/koa.js +15 -0
  82. package/lib/instrumentation/modules/memcached.js +99 -0
  83. package/lib/instrumentation/modules/mimic-response.js +45 -0
  84. package/lib/instrumentation/modules/mongodb/lib/cmap/connection_pool.js +40 -0
  85. package/lib/instrumentation/modules/mongodb-core.js +206 -0
  86. package/lib/instrumentation/modules/mongodb.js +259 -0
  87. package/lib/instrumentation/modules/mysql.js +200 -0
  88. package/lib/instrumentation/modules/mysql2.js +140 -0
  89. package/lib/instrumentation/modules/pg.js +148 -0
  90. package/lib/instrumentation/modules/pug.js +18 -0
  91. package/lib/instrumentation/modules/redis.js +176 -0
  92. package/lib/instrumentation/modules/restify.js +52 -0
  93. package/lib/instrumentation/modules/tedious.js +159 -0
  94. package/lib/instrumentation/modules/undici.js +270 -0
  95. package/lib/instrumentation/modules/ws.js +59 -0
  96. package/lib/instrumentation/noop-transaction.js +81 -0
  97. package/lib/instrumentation/run-context/AbstractRunContextManager.js +215 -0
  98. package/lib/instrumentation/run-context/AsyncHooksRunContextManager.js +106 -0
  99. package/lib/instrumentation/run-context/AsyncLocalStorageRunContextManager.js +73 -0
  100. package/lib/instrumentation/run-context/BasicRunContextManager.js +82 -0
  101. package/lib/instrumentation/run-context/RunContext.js +151 -0
  102. package/lib/instrumentation/run-context/index.js +23 -0
  103. package/lib/instrumentation/shimmer.js +123 -0
  104. package/lib/instrumentation/span-compression.js +239 -0
  105. package/lib/instrumentation/span.js +621 -0
  106. package/lib/instrumentation/template-shared.js +43 -0
  107. package/lib/instrumentation/timer.js +84 -0
  108. package/lib/instrumentation/transaction.js +571 -0
  109. package/lib/lambda.js +992 -0
  110. package/lib/load-source-map.js +100 -0
  111. package/lib/logging.js +212 -0
  112. package/lib/metrics/index.js +92 -0
  113. package/lib/metrics/platforms/generic/index.js +40 -0
  114. package/lib/metrics/platforms/generic/process-cpu.js +22 -0
  115. package/lib/metrics/platforms/generic/process-top.js +157 -0
  116. package/lib/metrics/platforms/generic/stats.js +34 -0
  117. package/lib/metrics/platforms/generic/system-cpu.js +51 -0
  118. package/lib/metrics/platforms/linux/index.js +19 -0
  119. package/lib/metrics/platforms/linux/stats.js +213 -0
  120. package/lib/metrics/queue.js +90 -0
  121. package/lib/metrics/registry.js +52 -0
  122. package/lib/metrics/reporter.js +119 -0
  123. package/lib/metrics/runtime.js +77 -0
  124. package/lib/middleware/connect.js +16 -0
  125. package/lib/opentelemetry-bridge/OTelBridgeNonRecordingSpan.js +150 -0
  126. package/lib/opentelemetry-bridge/OTelBridgeRunContext.js +124 -0
  127. package/lib/opentelemetry-bridge/OTelContextManager.js +82 -0
  128. package/lib/opentelemetry-bridge/OTelSpan.js +344 -0
  129. package/lib/opentelemetry-bridge/OTelTracer.js +201 -0
  130. package/lib/opentelemetry-bridge/OTelTracerProvider.js +25 -0
  131. package/lib/opentelemetry-bridge/README.md +244 -0
  132. package/lib/opentelemetry-bridge/index.js +15 -0
  133. package/lib/opentelemetry-bridge/oblog.js +23 -0
  134. package/lib/opentelemetry-bridge/opentelemetry-core-mini/README.md +3 -0
  135. package/lib/opentelemetry-bridge/opentelemetry-core-mini/internal/validators.js +52 -0
  136. package/lib/opentelemetry-bridge/opentelemetry-core-mini/trace/TraceState.js +109 -0
  137. package/lib/opentelemetry-bridge/otelutils.js +99 -0
  138. package/lib/opentelemetry-bridge/setup.js +76 -0
  139. package/lib/opentelemetry-metrics/ElasticApmMetricExporter.js +285 -0
  140. package/lib/opentelemetry-metrics/index.js +50 -0
  141. package/lib/parsers.js +225 -0
  142. package/lib/propwrap.js +147 -0
  143. package/lib/stacktraces.js +537 -0
  144. package/lib/symbols.js +15 -0
  145. package/lib/tracecontext/index.js +118 -0
  146. package/lib/tracecontext/traceparent.js +185 -0
  147. package/lib/tracecontext/tracestate.js +388 -0
  148. package/lib/wildcard-matcher.js +52 -0
  149. package/loader.mjs +7 -0
  150. package/package.json +299 -0
  151. package/start.d.ts +8 -0
  152. package/start.js +29 -0
  153. package/types/aws-lambda.d.ts +98 -0
  154. package/types/connect.d.ts +23 -0
@@ -0,0 +1,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;