@emartech/aggregate-metric-logger 3.0.1 → 3.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emartech/aggregate-metric-logger",
3
- "version": "3.0.1",
3
+ "version": "3.2.0",
4
4
  "description": "aggregate metrics in memory for logging",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -29,19 +29,20 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@emartech/json-logger": "^3.1.0",
32
+ "@emartech/json-logger": "^7.2.3",
33
33
  "@google-cloud/monitoring": "^3.0.2",
34
34
  "date-fns": "^2.3.0",
35
35
  "json-stable-stringify": "^1.0.1",
36
- "lodash": "^4.17.15"
36
+ "lodash": "^4.17.15",
37
+ "ms": "^2.1.3"
37
38
  },
38
39
  "devDependencies": {
39
- "@sinonjs/fake-timers": "9.1.1",
40
- "@types/jest": "27.4.1",
40
+ "@sinonjs/fake-timers": "^10.0.0",
41
+ "@types/jest": "^29.2.3",
41
42
  "dotenv-haphap": "^3.1.2",
42
43
  "eslint": "^8.12.0",
43
44
  "eslint-config-emarsys": "^5.1.0",
44
- "eslint-plugin-jest": "^26.1.3",
45
+ "eslint-plugin-jest": "^27.1.5",
45
46
  "jest": "^29.2.2",
46
47
  "semantic-release": "^19.0.2"
47
48
  }
@@ -25,10 +25,10 @@ const addToMetric = (metricName, labels = {}, type, value) => {
25
25
  }
26
26
  const key = `${metricName}_${stringify(labels)}`;
27
27
  if (!metrics[key]) {
28
- const value = type === 'counter' ? createCounter() : createDistribution();
29
- metrics[key] = { name: metricName, labels, value };
28
+ const aggregator = type === 'counter' ? createCounter() : createDistribution();
29
+ metrics[key] = { name: metricName, labels, aggregator };
30
30
  }
31
- metrics[key].value.add(value);
31
+ metrics[key].aggregator.add(value);
32
32
  };
33
33
 
34
34
  exports.reset = () => {
@@ -44,7 +44,7 @@ const setupNextFlush = () => {
44
44
  const flush = async () => {
45
45
  const timeSeries = buildTimeSeries(metrics);
46
46
  for (const [, metric] of Object.entries(metrics)) {
47
- metric.value.advanceTimer();
47
+ metric.aggregator.advanceTimer();
48
48
  }
49
49
  await publishTimeSeries(timeSeries);
50
50
  setupNextFlush();
@@ -36,7 +36,7 @@ describe('gcpMetricCollector', () => {
36
36
  name: 'jolo',
37
37
  labels: { kacsa: 'A' },
38
38
  value: { int64Value: '88' },
39
- startTime: 20000,
39
+ startTime: 19999,
40
40
  endTime: 80000,
41
41
  metricKind: 'CUMULATIVE',
42
42
  valueType: 'int64Value'
@@ -2,7 +2,7 @@
2
2
 
3
3
  exports.buildTimeSeries = metrics =>
4
4
  Object.values(metrics).map(metric => {
5
- const state = metric.value.getState();
5
+ const state = metric.aggregator.getState();
6
6
  return {
7
7
  metric: {
8
8
  type: `custom.googleapis.com/${metric.name}`,
@@ -15,7 +15,7 @@ const dummyMetric = ({
15
15
  }) => ({
16
16
  name,
17
17
  labels,
18
- value: {
18
+ aggregator: {
19
19
  getState: () => ({
20
20
  value: { int64Value: `${count}` },
21
21
  startTime,
@@ -1,26 +1,36 @@
1
1
  'use strict';
2
2
 
3
- const logger = require('@emartech/json-logger')('aggregate-metric-logger');
3
+ const { createLogger } = require('@emartech/json-logger');
4
4
  const monitoring = require('@google-cloud/monitoring');
5
5
  const { chunk } = require('lodash');
6
+ const ms = require('ms');
6
7
 
8
+ const logger = createLogger('aggregate-metric-logger');
7
9
  const MAX_TIME_SERIES_COUNT = 200;
8
10
 
9
11
  exports.publishTimeSeries = async timeSeries => {
10
12
  try {
11
13
  const client = getMonitoringClient();
12
-
13
14
  for (const timeSeriesChunk of chunk(timeSeries, MAX_TIME_SERIES_COUNT)) {
14
- await client.createTimeSeries({
15
- name: client.projectPath(process.env.MONITORING_PROJECT_ID),
16
- timeSeries: timeSeriesChunk
17
- });
15
+ await createTimeSeries(client, timeSeriesChunk);
18
16
  }
19
17
  } catch (error) {
20
18
  logger.warnFromError('pushing-metrics-failed', error, { do_not_alert: true });
21
19
  }
22
20
  };
23
21
 
22
+ const createTimeSeries = async (client, timeSeries) => {
23
+ const name = client.projectPath(process.env.MONITORING_PROJECT_ID);
24
+ try {
25
+ await client.createTimeSeries({ name, timeSeries });
26
+ } catch (error) {
27
+ await sleep(ms('10 sec'));
28
+ await client.createTimeSeries({ name, timeSeries });
29
+ }
30
+ };
31
+
32
+ const sleep = async sleepTime => new Promise(resolve => setTimeout(resolve, sleepTime));
33
+
24
34
  let monitoringClientInstance = null;
25
35
  const getMonitoringClient = () => {
26
36
  if (!monitoringClientInstance) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const loggerFactory = require('@emartech/json-logger');
3
+ const { createLogger } = require('@emartech/json-logger');
4
4
  const { getSeconds, startOfMinute, addSeconds } = require('date-fns');
5
5
  const { omit, pick, fromPairs, toPairs } = require('lodash');
6
6
  const stringify = require('json-stable-stringify');
@@ -9,7 +9,7 @@ module.exports = ({
9
9
  enabled = true,
10
10
  namespace = 'aggregate-metric-logger'
11
11
  } = {}) => {
12
- const logger = loggerFactory(namespace);
12
+ const logger = createLogger(namespace);
13
13
 
14
14
  const thresholdsByTag = {};
15
15
  let metrics = {};
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const Logger = require('@emartech/json-logger').Logger;
3
+ const { Logger } = require('@emartech/json-logger');
4
4
  const fakeTimers = require('@sinonjs/fake-timers');
5
5
  const metricLoggerFactory = require('./laas-metric-logger');
6
6
 
@@ -19,7 +19,7 @@ describe('metricLogger', () => {
19
19
  metricLogger.measure('elfogyasztot-tap', 4);
20
20
 
21
21
  clock.tick(60 * 1000 + 1);
22
- expect(Logger.prototype.info).toBeCalledWith('elfogyasztot-tap', {
22
+ expect(Logger.prototype.info).toHaveBeenCalledWith('elfogyasztot-tap', {
23
23
  min: 4,
24
24
  max: 4,
25
25
  count: 1,
@@ -35,7 +35,7 @@ describe('metricLogger', () => {
35
35
  metricLogger.measure('kacsa-cucc', 18);
36
36
 
37
37
  clock.tick(60 * 1000 + 1);
38
- expect(Logger.prototype.info).toBeCalledWith('elfogyasztot-tap', {
38
+ expect(Logger.prototype.info).toHaveBeenCalledWith('elfogyasztot-tap', {
39
39
  min: 4,
40
40
  max: 8,
41
41
  count: 2,
@@ -43,7 +43,7 @@ describe('metricLogger', () => {
43
43
  average: 6,
44
44
  is_metric: true
45
45
  });
46
- expect(Logger.prototype.info).toBeCalledWith('kacsa-cucc', {
46
+ expect(Logger.prototype.info).toHaveBeenCalledWith('kacsa-cucc', {
47
47
  min: 18,
48
48
  max: 18,
49
49
  count: 1,
@@ -59,7 +59,7 @@ describe('metricLogger', () => {
59
59
  metricLogger.measure('elfogyasztot-tap', 18, { emberke: 'jano' });
60
60
 
61
61
  clock.tick(60 * 1000 + 1);
62
- expect(Logger.prototype.info).toBeCalledWith('elfogyasztot-tap', {
62
+ expect(Logger.prototype.info).toHaveBeenCalledWith('elfogyasztot-tap', {
63
63
  min: 4,
64
64
  max: 8,
65
65
  count: 2,
@@ -68,7 +68,7 @@ describe('metricLogger', () => {
68
68
  emberke: 'bela',
69
69
  is_metric: true
70
70
  });
71
- expect(Logger.prototype.info).toBeCalledWith('elfogyasztot-tap', {
71
+ expect(Logger.prototype.info).toHaveBeenCalledWith('elfogyasztot-tap', {
72
72
  min: 18,
73
73
  max: 18,
74
74
  count: 1,
@@ -84,7 +84,7 @@ describe('metricLogger', () => {
84
84
  metricLogger.measure('elfogyasztot-tap', 8, { b: 2, a: 1 });
85
85
 
86
86
  clock.tick(60 * 1000 + 1);
87
- expect(Logger.prototype.info).toBeCalledWith('elfogyasztot-tap', {
87
+ expect(Logger.prototype.info).toHaveBeenCalledWith('elfogyasztot-tap', {
88
88
  min: 4,
89
89
  max: 8,
90
90
  count: 2,
@@ -108,7 +108,7 @@ describe('metricLogger', () => {
108
108
  metricLogger.measure('etwas', 816);
109
109
 
110
110
  clock.tick(60 * 1000 + 1);
111
- expect(Logger.prototype.info).toBeCalledWith('etwas', {
111
+ expect(Logger.prototype.info).toHaveBeenCalledWith('etwas', {
112
112
  min: 2,
113
113
  max: 816,
114
114
  count: 7,
@@ -141,7 +141,7 @@ describe('metricLogger', () => {
141
141
  metricLogger.stop(measurement);
142
142
 
143
143
  clock.tick(60 * 1000);
144
- expect(Logger.prototype.info).toBeCalledWith('utlegeles', {
144
+ expect(Logger.prototype.info).toHaveBeenCalledWith('utlegeles', {
145
145
  min: 50,
146
146
  max: 50,
147
147
  count: 1,
@@ -160,7 +160,7 @@ describe('metricLogger', () => {
160
160
  metricLogger.stop(measurement2);
161
161
 
162
162
  clock.tick(60 * 1000);
163
- expect(Logger.prototype.info).toBeCalledWith('utlegeles', {
163
+ expect(Logger.prototype.info).toHaveBeenCalledWith('utlegeles', {
164
164
  min: 50,
165
165
  max: 70,
166
166
  sum: 120,
@@ -175,9 +175,9 @@ describe('metricLogger', () => {
175
175
  metricLogger.stop(measurement);
176
176
 
177
177
  clock.tick(29 * 1000 + 999);
178
- expect(Logger.prototype.info).not.toBeCalled();
178
+ expect(Logger.prototype.info).not.toHaveBeenCalled();
179
179
  clock.tick(1 * 1000);
180
- expect(Logger.prototype.info).toBeCalledWith('utlegeles', expect.anything());
180
+ expect(Logger.prototype.info).toHaveBeenCalledWith('utlegeles', expect.anything());
181
181
  });
182
182
 
183
183
  it('should flush at next minute:30 if we are after 30 in current minute', () => {
@@ -186,9 +186,9 @@ describe('metricLogger', () => {
186
186
  metricLogger.stop(measurement);
187
187
 
188
188
  clock.tick(44 * 1000);
189
- expect(Logger.prototype.info).not.toBeCalled();
189
+ expect(Logger.prototype.info).not.toHaveBeenCalled();
190
190
  clock.tick(1 * 1000);
191
- expect(Logger.prototype.info).toBeCalledWith('utlegeles', expect.anything());
191
+ expect(Logger.prototype.info).toHaveBeenCalledWith('utlegeles', expect.anything());
192
192
  });
193
193
 
194
194
  it('should periodically log measuerments', () => {
@@ -199,7 +199,7 @@ describe('metricLogger', () => {
199
199
  metricLogger.stop(measurement1);
200
200
 
201
201
  clock.tick(21 * 1000);
202
- expect(Logger.prototype.info).toBeCalledWith('utlegeles', {
202
+ expect(Logger.prototype.info).toHaveBeenCalledWith('utlegeles', {
203
203
  count: 1,
204
204
  max: 10000,
205
205
  min: 10000,
@@ -211,7 +211,7 @@ describe('metricLogger', () => {
211
211
  metricLogger.stop(measurement2);
212
212
  metricLogger.stop(measurement3);
213
213
  clock.tick(60 * 1000);
214
- expect(Logger.prototype.info).toBeCalledWith('utlegeles', {
214
+ expect(Logger.prototype.info).toHaveBeenCalledWith('utlegeles', {
215
215
  count: 2,
216
216
  max: 31000,
217
217
  min: 21000,
@@ -230,7 +230,7 @@ describe('metricLogger', () => {
230
230
  metricLogger.stop(measurement2);
231
231
  clock.tick(15 * 1000);
232
232
 
233
- expect(Logger.prototype.info).toBeCalledWith('utlegeles', {
233
+ expect(Logger.prototype.info).toHaveBeenCalledWith('utlegeles', {
234
234
  count: 1,
235
235
  max: 10000,
236
236
  min: 10000,
@@ -239,7 +239,7 @@ describe('metricLogger', () => {
239
239
  a: 21,
240
240
  is_metric: true
241
241
  });
242
- expect(Logger.prototype.info).toBeCalledWith('nyavogas', {
242
+ expect(Logger.prototype.info).toHaveBeenCalledWith('nyavogas', {
243
243
  count: 1,
244
244
  max: 15000,
245
245
  min: 15000,
@@ -260,7 +260,7 @@ describe('metricLogger', () => {
260
260
  metricLogger[method]('elfogyasztot-tap', { alma: 2 });
261
261
 
262
262
  clock.tick(60 * 1000 + 11500);
263
- expect(Logger.prototype[method]).toBeCalledWith('elfogyasztot-tap', {
263
+ expect(Logger.prototype[method]).toHaveBeenCalledWith('elfogyasztot-tap', {
264
264
  count: 2,
265
265
  alma: 2,
266
266
  is_metric: true
@@ -2,7 +2,7 @@
2
2
 
3
3
  exports.createCounter = () => {
4
4
  let count = 0;
5
- const startTime = Date.now();
5
+ const startTime = Date.now() - 1;
6
6
 
7
7
  return {
8
8
  getState: () => ({
@@ -8,7 +8,7 @@ describe('count', () => {
8
8
  const counter = createCounter();
9
9
 
10
10
  expect(counter.getState()).toEqual({
11
- startTime: 880,
11
+ startTime: 879,
12
12
  endTime: 880,
13
13
  metricKind: 'CUMULATIVE',
14
14
  valueType: 'int64Value',
@@ -16,6 +16,13 @@ describe('count', () => {
16
16
  });
17
17
  });
18
18
 
19
+ it('should return with the startTime which is before the endTime even when no time passes', () => {
20
+ // which is a must-have for non-gauge metrics
21
+ jest.useFakeTimers().setSystemTime(new Date(880));
22
+ const counter = createCounter();
23
+ expect(counter.getState().endTime).toBeGreaterThan(counter.getState().startTime);
24
+ });
25
+
19
26
  it('should increment counter when a value is added', () => {
20
27
  const counter = createCounter();
21
28
 
@@ -36,7 +43,7 @@ describe('count', () => {
36
43
 
37
44
  expect(counter.getState()).toMatchObject({
38
45
  value: { int64Value: '3' },
39
- startTime: 880,
46
+ startTime: 879,
40
47
  endTime: 900
41
48
  });
42
49
  });