teraslice 2.10.0 → 2.12.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 (118) hide show
  1. package/dist/src/interfaces.js +12 -0
  2. package/dist/src/lib/cluster/cluster_master.js +246 -0
  3. package/dist/src/lib/cluster/node_master.js +355 -0
  4. package/dist/src/lib/cluster/services/api.js +663 -0
  5. package/dist/src/lib/cluster/services/assets.js +226 -0
  6. package/dist/src/lib/cluster/services/cluster/backends/kubernetes/index.js +192 -0
  7. package/dist/src/lib/cluster/services/cluster/backends/kubernetes/k8s.js +481 -0
  8. package/dist/src/lib/cluster/services/cluster/backends/kubernetes/k8sResource.js +414 -0
  9. package/dist/src/lib/cluster/services/cluster/backends/kubernetes/k8sState.js +59 -0
  10. package/dist/src/lib/cluster/services/cluster/backends/kubernetes/utils.js +43 -0
  11. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/index.js +192 -0
  12. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/interfaces.js +2 -0
  13. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8s.js +423 -0
  14. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sDeploymentResource.js +60 -0
  15. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sJobResource.js +55 -0
  16. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sResource.js +359 -0
  17. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sServiceResource.js +37 -0
  18. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sState.js +60 -0
  19. package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/utils.js +170 -0
  20. package/dist/src/lib/cluster/services/cluster/backends/native/dispatch.js +13 -0
  21. package/dist/src/lib/cluster/services/cluster/backends/native/index.js +526 -0
  22. package/dist/src/lib/cluster/services/cluster/backends/native/messaging.js +547 -0
  23. package/dist/src/lib/cluster/services/cluster/backends/state-utils.js +26 -0
  24. package/dist/src/lib/cluster/services/cluster/index.js +17 -0
  25. package/dist/src/lib/cluster/services/execution.js +435 -0
  26. package/dist/src/lib/cluster/services/index.js +6 -0
  27. package/dist/src/lib/cluster/services/interfaces.js +2 -0
  28. package/dist/src/lib/cluster/services/jobs.js +454 -0
  29. package/dist/src/lib/config/default-sysconfig.js +26 -0
  30. package/dist/src/lib/config/index.js +22 -0
  31. package/dist/src/lib/config/schemas/system.js +360 -0
  32. package/dist/src/lib/storage/analytics.js +86 -0
  33. package/dist/src/lib/storage/assets.js +401 -0
  34. package/dist/src/lib/storage/backends/elasticsearch_store.js +494 -0
  35. package/dist/src/lib/storage/backends/mappings/analytics.js +50 -0
  36. package/dist/src/lib/storage/backends/mappings/asset.js +41 -0
  37. package/dist/src/lib/storage/backends/mappings/ex.js +62 -0
  38. package/dist/src/lib/storage/backends/mappings/job.js +38 -0
  39. package/dist/src/lib/storage/backends/mappings/state.js +38 -0
  40. package/dist/src/lib/storage/backends/s3_store.js +237 -0
  41. package/dist/src/lib/storage/execution.js +300 -0
  42. package/dist/src/lib/storage/index.js +7 -0
  43. package/dist/src/lib/storage/jobs.js +81 -0
  44. package/dist/src/lib/storage/state.js +255 -0
  45. package/dist/src/lib/utils/api_utils.js +157 -0
  46. package/dist/src/lib/utils/asset_utils.js +94 -0
  47. package/dist/src/lib/utils/date_utils.js +52 -0
  48. package/dist/src/lib/utils/encoding_utils.js +27 -0
  49. package/dist/src/lib/utils/events.js +4 -0
  50. package/dist/src/lib/utils/file_utils.js +124 -0
  51. package/dist/src/lib/utils/id_utils.js +15 -0
  52. package/dist/src/lib/utils/port_utils.js +32 -0
  53. package/dist/src/lib/workers/assets/index.js +3 -0
  54. package/dist/src/lib/workers/assets/loader-executable.js +40 -0
  55. package/dist/src/lib/workers/assets/loader.js +73 -0
  56. package/dist/src/lib/workers/assets/spawn.js +55 -0
  57. package/dist/src/lib/workers/context/execution-context.js +12 -0
  58. package/dist/src/lib/workers/context/terafoundation-context.js +8 -0
  59. package/dist/src/lib/workers/execution-controller/execution-analytics.js +188 -0
  60. package/dist/src/lib/workers/execution-controller/index.js +1024 -0
  61. package/dist/src/lib/workers/execution-controller/recovery.js +151 -0
  62. package/dist/src/lib/workers/execution-controller/scheduler.js +390 -0
  63. package/dist/src/lib/workers/execution-controller/slice-analytics.js +96 -0
  64. package/dist/src/lib/workers/helpers/job.js +80 -0
  65. package/dist/src/lib/workers/helpers/op-analytics.js +22 -0
  66. package/dist/src/lib/workers/helpers/terafoundation.js +34 -0
  67. package/dist/src/lib/workers/helpers/worker-shutdown.js +169 -0
  68. package/dist/src/lib/workers/metrics/index.js +108 -0
  69. package/dist/src/lib/workers/worker/index.js +378 -0
  70. package/dist/src/lib/workers/worker/slice.js +122 -0
  71. package/dist/test/config/schemas/system_schema-spec.js +37 -0
  72. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/k8s-spec.js +316 -0
  73. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/k8sResource-spec.js +795 -0
  74. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/k8sState-multicluster-spec.js +67 -0
  75. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/k8sState-spec.js +84 -0
  76. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/utils-spec.js +132 -0
  77. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8s-v2-spec.js +455 -0
  78. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sResource-v2-spec.js +818 -0
  79. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sState-multicluster-v2-spec.js +67 -0
  80. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sState-v2-spec.js +84 -0
  81. package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/utils-v2-spec.js +320 -0
  82. package/dist/test/lib/cluster/services/cluster/backends/state-utils-spec.js +37 -0
  83. package/dist/test/node_master-spec.js +188 -0
  84. package/dist/test/services/api-spec.js +80 -0
  85. package/dist/test/services/assets-spec.js +158 -0
  86. package/dist/test/services/messaging-spec.js +440 -0
  87. package/dist/test/storage/assets_storage-spec.js +95 -0
  88. package/dist/test/storage/s3_store-spec.js +138 -0
  89. package/dist/test/test.config.js +8 -0
  90. package/dist/test/test.setup.js +6 -0
  91. package/dist/test/utils/api_utils-spec.js +86 -0
  92. package/dist/test/utils/asset_utils-spec.js +141 -0
  93. package/dist/test/utils/elastic_utils-spec.js +25 -0
  94. package/dist/test/workers/execution-controller/execution-controller-spec.js +371 -0
  95. package/dist/test/workers/execution-controller/execution-special-test-cases-spec.js +520 -0
  96. package/dist/test/workers/execution-controller/execution-test-cases-spec.js +338 -0
  97. package/dist/test/workers/execution-controller/recovery-spec.js +160 -0
  98. package/dist/test/workers/execution-controller/scheduler-spec.js +249 -0
  99. package/dist/test/workers/execution-controller/slice-analytics-spec.js +121 -0
  100. package/dist/test/workers/fixtures/ops/example-op/processor.js +20 -0
  101. package/dist/test/workers/fixtures/ops/example-op/schema.js +19 -0
  102. package/dist/test/workers/fixtures/ops/example-reader/fetcher.js +20 -0
  103. package/dist/test/workers/fixtures/ops/example-reader/schema.js +41 -0
  104. package/dist/test/workers/fixtures/ops/example-reader/slicer.js +37 -0
  105. package/dist/test/workers/fixtures/ops/new-op/processor.js +29 -0
  106. package/dist/test/workers/fixtures/ops/new-op/schema.js +18 -0
  107. package/dist/test/workers/fixtures/ops/new-reader/fetcher.js +19 -0
  108. package/dist/test/workers/fixtures/ops/new-reader/schema.js +23 -0
  109. package/dist/test/workers/fixtures/ops/new-reader/slicer.js +13 -0
  110. package/dist/test/workers/helpers/configs.js +130 -0
  111. package/dist/test/workers/helpers/execution-controller-helper.js +49 -0
  112. package/dist/test/workers/helpers/index.js +5 -0
  113. package/dist/test/workers/helpers/test-context.js +210 -0
  114. package/dist/test/workers/helpers/zip-directory.js +25 -0
  115. package/dist/test/workers/worker/slice-spec.js +333 -0
  116. package/dist/test/workers/worker/worker-spec.js +356 -0
  117. package/package.json +94 -93
  118. package/service.js +0 -0
@@ -0,0 +1,80 @@
1
+ import { makeISODate } from '@terascope/utils';
2
+ import { JobValidator } from '@terascope/job-components';
3
+ import { JobsStorage, ExecutionStorage, StateStorage } from '../../storage/index.js';
4
+ // TODO: fix type here
5
+ export async function validateJob(context, jobSpec) {
6
+ const jobValidator = new JobValidator(context);
7
+ try {
8
+ return await jobValidator.validateConfig(jobSpec);
9
+ }
10
+ catch (error) {
11
+ throw new Error(`validating job: ${error}`);
12
+ }
13
+ }
14
+ export async function initializeTestExecution({ context, config, stores = {}, isRecovery = false, cleanupType, createRecovery = true, shutdownStores = false, recoverySlices = [], lastStatus = 'failed' }) {
15
+ if (!stores.jobStore) {
16
+ const [jobStore, exStore, stateStore] = await Promise.all([
17
+ (async () => {
18
+ const store = new JobsStorage(context);
19
+ await store.initialize();
20
+ return store;
21
+ })(),
22
+ (async () => {
23
+ const store = new ExecutionStorage(context);
24
+ await store.initialize();
25
+ return store;
26
+ })(),
27
+ (async () => {
28
+ const store = new StateStorage(context);
29
+ await store.initialize();
30
+ return store;
31
+ })(),
32
+ ]);
33
+ stores.jobStore = jobStore;
34
+ stores.exStore = exStore;
35
+ stores.stateStore = stateStore;
36
+ }
37
+ const validJob = await validateJob(context, config);
38
+ const jobSpec = await stores.jobStore.create(config);
39
+ const job = Object.assign({}, jobSpec, validJob, {
40
+ job_id: jobSpec.job_id
41
+ });
42
+ // @ts-expect-error
43
+ const slicerHostname = job.slicer_hostname;
44
+ // @ts-expect-error
45
+ const slicerPort = job.slicer_port;
46
+ let ex;
47
+ if (isRecovery) {
48
+ ex = await stores.exStore.create(job, lastStatus);
49
+ if (recoverySlices.length) {
50
+ await Promise.all(recoverySlices
51
+ .map(({ slice, state }) => stores.stateStore.createState(ex.ex_id, slice, state, slice.error)));
52
+ await stores.stateStore.refresh();
53
+ }
54
+ if (createRecovery) {
55
+ ex = await stores.exStore.createRecoveredExecution(ex, cleanupType);
56
+ }
57
+ }
58
+ else {
59
+ ex = await stores.exStore.create(job);
60
+ }
61
+ if (slicerHostname && slicerPort) {
62
+ ex = await stores.exStore.updatePartial(ex.ex_id, async (existing) => Object.assign(existing, {
63
+ slicer_hostname: slicerHostname,
64
+ slicer_port: slicerPort,
65
+ _updated: makeISODate()
66
+ }));
67
+ }
68
+ if (shutdownStores) {
69
+ await Promise.all([
70
+ stores.exStore.shutdown(true),
71
+ stores.jobStore.shutdown(true),
72
+ stores.stateStore.shutdown(true)
73
+ ]);
74
+ }
75
+ return {
76
+ job,
77
+ ex,
78
+ };
79
+ }
80
+ //# sourceMappingURL=job.js.map
@@ -0,0 +1,22 @@
1
+ import { isString, isArray, truncate, } from '@terascope/utils';
2
+ function formatVal(value) {
3
+ if (isString(value))
4
+ return `"${value}"`;
5
+ if (isArray(value))
6
+ return `[${value.join(', ')}]`;
7
+ return truncate(JSON.stringify(value), 30);
8
+ }
9
+ function format(input) {
10
+ const list = [];
11
+ for (const [key, value] of Object.entries(input)) {
12
+ list.push(`${key}: ${formatVal(value)}`);
13
+ }
14
+ return list.join(', ');
15
+ }
16
+ // TODO: fix type here
17
+ export function logOpStats(logger, slice, analyticsData) {
18
+ const { request, ...record } = slice;
19
+ const obj = Object.assign({}, record, analyticsData);
20
+ logger.info(`analytics for slice: ${format(obj)}`);
21
+ }
22
+ //# sourceMappingURL=op-analytics.js.map
@@ -0,0 +1,34 @@
1
+ import { get, isFunction, isString } from '@terascope/utils';
2
+ import { makeContextLogger } from '@terascope/job-components';
3
+ import { safeDecode } from '../../utils/encoding_utils.js';
4
+ export function generateWorkerId(context) {
5
+ const { hostname } = context.sysconfig.teraslice;
6
+ const clusterId = get(context, 'cluster.worker.id');
7
+ return `${hostname}__${clusterId}`;
8
+ }
9
+ export function makeLogger(context, moduleName, extra = {}) {
10
+ if (!context || !context.apis) {
11
+ throw new Error('makeLogger expected terafoundation context as first arg');
12
+ }
13
+ if (!moduleName || !isString(moduleName)) {
14
+ throw new Error('makeLogger expected module name as second arg');
15
+ }
16
+ const exAPI = context.apis.executionContext;
17
+ if (exAPI && isFunction(exAPI.makeLogger)) {
18
+ return exAPI.makeLogger(moduleName, extra);
19
+ }
20
+ const defaultContext = {};
21
+ if (process.env.EX) {
22
+ const ex = safeDecode(process.env.EX);
23
+ const exId = get(ex, 'ex_id');
24
+ const jobId = get(ex, 'job_id');
25
+ if (exId) {
26
+ defaultContext.ex_id = exId;
27
+ }
28
+ if (jobId) {
29
+ defaultContext.job_id = jobId;
30
+ }
31
+ }
32
+ return makeContextLogger(context, moduleName, Object.assign(defaultContext, extra));
33
+ }
34
+ //# sourceMappingURL=terafoundation.js.map
@@ -0,0 +1,169 @@
1
+ import { get, pDelay, pRaceWithTimeout, isError, logError } from '@terascope/utils';
2
+ import ms from 'ms';
3
+ import { makeLogger } from './terafoundation.js';
4
+ export function waitForWorkerShutdown(context, eventName) {
5
+ const shutdownTimeout = get(context, 'sysconfig.teraslice.shutdown_timeout', 30000);
6
+ const events = context.apis.foundation.getSystemEvents();
7
+ return new Promise((resolve, reject) => {
8
+ const timeoutId = setTimeout(() => {
9
+ events.removeListener(eventName, handler);
10
+ reject(new Error('Timeout waiting for worker to shutdown'));
11
+ }, shutdownTimeout);
12
+ function handler(err) {
13
+ clearTimeout(timeoutId);
14
+ if (isError(err)) {
15
+ reject(err);
16
+ }
17
+ else {
18
+ resolve(true);
19
+ }
20
+ }
21
+ events.once(eventName, handler);
22
+ });
23
+ }
24
+ /* istanbul ignore next */
25
+ export function shutdownHandler(context, shutdownFn) {
26
+ const assignment = context.assignment
27
+ || process.env.NODE_TYPE
28
+ || process.env.assignment
29
+ || 'unknown-assignment';
30
+ const clusteringType = get(context, 'sysconfig.teraslice.cluster_manager_type');
31
+ const isK8s = clusteringType === 'kubernetes' || clusteringType === 'kubernetesV2';
32
+ // this is native clustering only
33
+ const isProcessRestart = process.env.process_restart;
34
+ // everything but the k8s execution_controller should not be allowed be allowed to
35
+ // set a non-zero exit code (to avoid being restarted)
36
+ // This is overridden in V2 because it can restart
37
+ const allowNonZeroExitCode = !(isK8s
38
+ && assignment === 'execution_controller'
39
+ && context.sysconfig.teraslice.cluster_manager_type === 'kubernetes');
40
+ const api = {
41
+ exiting: false,
42
+ exit
43
+ };
44
+ const shutdownTimeout = get(context, 'sysconfig.teraslice.shutdown_timeout', 20 * 1000);
45
+ const events = context.apis.foundation.getSystemEvents();
46
+ const logger = makeLogger(context, `${assignment}:shutdown_handler`);
47
+ if (assignment === 'execution_controller' && isProcessRestart) {
48
+ logger.fatal('Execution Controller runtime error led to a restart, terminating execution with failed status, please use the recover api to return slicer to a consistent state');
49
+ process.exit(0);
50
+ }
51
+ async function flushLogs() {
52
+ try {
53
+ await logger.flush();
54
+ await pDelay(1000);
55
+ const code = process.exitCode || 0;
56
+ logger.debug(`flushed logs successfully, will exit with code ${code}`);
57
+ }
58
+ catch (err) {
59
+ logError(logger, err, 'flush error on shutdown');
60
+ }
61
+ }
62
+ let startTime;
63
+ function exitingIn() {
64
+ if (!api.exiting) {
65
+ return `exiting in ${ms(shutdownTimeout)}...`;
66
+ }
67
+ const elapsed = Date.now() - startTime;
68
+ return `already shutting down, remaining ${ms(shutdownTimeout - elapsed)}`;
69
+ }
70
+ async function callShutdownFn(event, err) {
71
+ // avoid failing before the promse is try / catched in pRaceWithTimeout
72
+ await pDelay(100);
73
+ await shutdownFn(event, err);
74
+ }
75
+ async function shutdownWithTimeout(event, err) {
76
+ const timeout = shutdownTimeout - 2000;
77
+ await pRaceWithTimeout(callShutdownFn(event, err), timeout, (timeoutErr) => {
78
+ logError(logger, timeoutErr, 'shutdown error after timeout');
79
+ });
80
+ }
81
+ async function exit(event, err) {
82
+ if (api.exiting)
83
+ return;
84
+ /// Potential logic for cluster_master and asset_service
85
+ if (err) {
86
+ if (err.name.includes('Error')) {
87
+ setStatusCode(1);
88
+ }
89
+ }
90
+ api.exiting = true;
91
+ startTime = Date.now();
92
+ try {
93
+ await shutdownWithTimeout(event, err);
94
+ }
95
+ catch (error) {
96
+ logError(logger, error, `${assignment} while shutting down`);
97
+ }
98
+ finally {
99
+ await flushLogs();
100
+ if (allowNonZeroExitCode) {
101
+ const code = process.exitCode != null ? process.exitCode : 0;
102
+ logger.info(`${assignment} shutdown took ${ms(Date.now() - startTime)}, exit with ${code} status code`);
103
+ process.exit();
104
+ }
105
+ else {
106
+ logger.info(`${assignment} shutdown took ${ms(Date.now() - startTime)}, exit with zero status code`);
107
+ process.exit(0);
108
+ }
109
+ }
110
+ }
111
+ function setStatusCode(code) {
112
+ if (api.exiting)
113
+ return;
114
+ if (process.exitCode == null) {
115
+ process.exitCode = code;
116
+ }
117
+ }
118
+ process.on('SIGINT', () => {
119
+ logger.info(`${assignment} received process:SIGINT, ${exitingIn()}`);
120
+ setStatusCode(0);
121
+ exit('SIGINT');
122
+ });
123
+ process.on('SIGTERM', () => {
124
+ logger.info(`${assignment} received process:SIGTERM, ${exitingIn()}`);
125
+ setStatusCode(0);
126
+ exit('SIGTERM');
127
+ });
128
+ process.on('uncaughtException', (err) => {
129
+ logError(logger, err, `${assignment} received an uncaughtException, ${exitingIn()}`);
130
+ setStatusCode(1);
131
+ exit('uncaughtException', err);
132
+ });
133
+ process.once('unhandledRejection', (err) => {
134
+ logError(logger, err, `${assignment} received an unhandledRejection, ${exitingIn()}`);
135
+ setStatusCode(1);
136
+ exit('unhandledRejection', err);
137
+ });
138
+ // See https://github.com/trentm/node-bunyan/issues/246
139
+ function handleStdError(err) {
140
+ // @ts-expect-error TODO: fix error type
141
+ if (err.code === 'EPIPE' || err.code === 'ERR_STREAM_DESTROYED') {
142
+ // ignore
143
+ }
144
+ else {
145
+ throw err;
146
+ }
147
+ }
148
+ process.stdout.on('error', handleStdError);
149
+ process.stderr.on('error', handleStdError);
150
+ // event is fired from terafoundation when an error occurs during instantiation of a client
151
+ // **DEPRECATED:** This handler should be removed on teraslice v1
152
+ events.once('client:initialization:error', (err) => {
153
+ logError(logger, err, `${assignment} received a client initialization error, ${exitingIn()}`);
154
+ setStatusCode(1);
155
+ exit('client:initialization:error', err);
156
+ });
157
+ events.once('worker:shutdown:complete', (err) => {
158
+ setStatusCode(0);
159
+ if (err) {
160
+ logError(logger, err, `${assignment} shutdown error, ${exitingIn()}`);
161
+ }
162
+ else {
163
+ logger.info(`${assignment} shutdown, ${exitingIn()}`);
164
+ }
165
+ exit('worker:shutdown:complete', err);
166
+ });
167
+ return api;
168
+ }
169
+ //# sourceMappingURL=worker-shutdown.js.map
@@ -0,0 +1,108 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { debugLogger, isTest } from '@terascope/utils';
3
+ const defaultLogger = debugLogger('metrics');
4
+ export class Metrics extends EventEmitter {
5
+ logger;
6
+ _intervals;
7
+ eventLoopInterval;
8
+ // TODO: fix types here
9
+ _typesCollectedAt;
10
+ gcStats;
11
+ eventLoopStats;
12
+ constructor(config) {
13
+ super();
14
+ const argLogger = config && config.logger;
15
+ this.logger = argLogger
16
+ ? argLogger.child({
17
+ module: 'performance:metrics'
18
+ })
19
+ : defaultLogger;
20
+ this.eventLoopInterval = isTest ? 100 : 5000;
21
+ this._intervals = [];
22
+ this._typesCollectedAt = {};
23
+ this.gcStats = null;
24
+ }
25
+ async initialize() {
26
+ // never cause an unwanted error
27
+ try {
28
+ const module = await import('gc-stats');
29
+ this.gcStats = module.default();
30
+ }
31
+ catch (err) {
32
+ this.logger.error(err, 'Failure to construct gc-stats');
33
+ }
34
+ try {
35
+ this.eventLoopStats = await import('event-loop-stats');
36
+ }
37
+ catch (err) {
38
+ this.logger.error(err, 'Failure to construct event-loop-stats');
39
+ }
40
+ const gcEnabled = this.gcStats != null;
41
+ const loopEnabled = this.eventLoopStats != null;
42
+ this.logger.info('initializing performance metrics', {
43
+ gcEnabled,
44
+ loopEnabled
45
+ });
46
+ if (this.gcStats !== null) {
47
+ // https://github.com/dainis/node-gcstats#property-insights
48
+ const typesToName = {
49
+ 1: 'Scavenge',
50
+ 2: 'MarkSweepCompact',
51
+ 4: 'IncrementalMarking',
52
+ 8: 'WeakPhantomCallbackProcessing',
53
+ 15: 'All'
54
+ };
55
+ this.gcStats.on('stats', (metrics) => {
56
+ // never cause an unwanted error
57
+ if (!metrics) {
58
+ this.logger.warn('invalid metrics received for gc stats', metrics);
59
+ return;
60
+ }
61
+ const typeName = typesToName[metrics.gctype];
62
+ this._emitMetric('gc-stats', Object.assign({ typeName }, metrics));
63
+ });
64
+ }
65
+ if (loopEnabled) {
66
+ // https://github.com/bripkens/event-loop-stats#property-insights
67
+ this._intervals.push(setInterval(() => {
68
+ // never cause an unwanted error
69
+ let metrics;
70
+ try {
71
+ metrics = this.eventLoopStats.sense();
72
+ }
73
+ catch (err) {
74
+ this.logger.error(err, 'failure getting for event-loop-stats');
75
+ return;
76
+ }
77
+ if (!metrics) {
78
+ this.logger.warn('invalid metrics received for event-loop-stats', metrics);
79
+ return;
80
+ }
81
+ this._emitMetric('event-loop-stats', metrics);
82
+ }, this.eventLoopInterval));
83
+ }
84
+ }
85
+ async shutdown() {
86
+ try {
87
+ this._intervals.forEach(clearInterval);
88
+ this._intervals = [];
89
+ this.removeAllListeners();
90
+ this._typesCollectedAt = {};
91
+ }
92
+ catch (err) {
93
+ this.logger.debug(err, 'failure shutting down metrics');
94
+ }
95
+ }
96
+ _emitMetric(type, metrics) {
97
+ const lastCollectedAt = this._typesCollectedAt[type] || Date.now();
98
+ const msg = {
99
+ type,
100
+ timeSinceLast: Date.now() - lastCollectedAt,
101
+ metrics
102
+ };
103
+ this._typesCollectedAt[type] = Date.now();
104
+ this.emit('metric', msg);
105
+ this.logger.info(msg, `${type} performance metrics`);
106
+ }
107
+ }
108
+ //# sourceMappingURL=index.js.map