diff --git a/lib/client-metrics/client-metrics.test.js b/lib/client-metrics/client-metrics.test.js index 3cc6418b4c..2ff289314b 100644 --- a/lib/client-metrics/client-metrics.test.js +++ b/lib/client-metrics/client-metrics.test.js @@ -2,6 +2,7 @@ const { test } = require('ava'); const UnleashClientMetrics = require('./index'); +const moment = require('moment'); const sinon = require('sinon'); const { EventEmitter } = require('events'); @@ -58,7 +59,7 @@ test.cb('data should expire', (t) => { t.true(lastMinExpires === 1); t.true(lastHourExpires === 1); - sinon.restore(); + clock.restore(); t.end(); }); @@ -170,3 +171,158 @@ test('should handle a lot of toggles', t => { t.truthy(seenToggles.length === 100); metrics.destroy(); }); + +test('should have correct values for lastMinute', t => { + const clock = sinon.useFakeTimers(); + + const store = new EventEmitter(); + const metrics = new UnleashClientMetrics(store); + + const now = new Date(); + const input = [ + { + start: moment(now).subtract(1, 'hour'), + stop: moment(now).subtract(59, 'minutes'), + toggles: { + toggle: { yes: 10, no: 10 }, + }, + }, + { + start: moment(now).subtract(30, 'minutes'), + stop: moment(now).subtract(29, 'minutes'), + toggles: { + toggle: { yes: 10, no: 10 }, + }, + }, + { + start: moment(now).subtract(2, 'minutes'), + stop: moment(now).subtract(1, 'minutes'), + toggles: { + toggle: { yes: 10, no: 10 }, + }, + }, + { + start: moment(now).subtract(2, 'minutes'), + stop: moment(now).subtract(59, 'seconds'), + toggles: { + toggle: { yes: 10, no: 10 }, + }, + }, + { + start: moment(now), + stop: moment(now).subtract(30, 'seconds'), + toggles: { + toggle: { yes: 10, no: 10 }, + }, + }, + ]; + + input.forEach(bucket => { + store.emit('metrics', { + appName, + instanceId, + bucket, + }); + }); + + const seenToggles = metrics.getSeenTogglesByAppName(appName); + t.truthy(seenToggles.length === 1); + + // metrics.se + let c = metrics.getTogglesMetrics(); + t.deepEqual(c.lastMinute.toggle, { yes: 20, no: 20 }); + + clock.tick(10 * 1000); + c = metrics.getTogglesMetrics(); + t.deepEqual(c.lastMinute.toggle, { yes: 10, no: 10 }); + + clock.tick(20 * 1000); + c = metrics.getTogglesMetrics(); + t.deepEqual(c.lastMinute.toggle, { yes: 0, no: 0 }); + + metrics.destroy(); + clock.restore(); +}); + + +test('should have correct values for lastHour', t => { + const clock = sinon.useFakeTimers(); + + const store = new EventEmitter(); + const metrics = new UnleashClientMetrics(store); + + const now = new Date(); + const input = [ + { + start: moment(now).subtract(1, 'hour'), + stop: moment(now).subtract(59, 'minutes'), + toggles: { + toggle: { yes: 10, no: 10 }, + }, + }, + { + start: moment(now).subtract(30, 'minutes'), + stop: moment(now).subtract(29, 'minutes'), + toggles: { + toggle: { yes: 10, no: 10 }, + }, + }, + { + start: moment(now).subtract(15, 'minutes'), + stop: moment(now).subtract(14, 'minutes'), + toggles: { + toggle: { yes: 10, no: 10 }, + }, + }, + { + start: moment(now).add(59, 'minutes'), + stop: moment(now).add(1, 'hour'), + toggles: { + toggle: { yes: 11, no: 11 }, + }, + }, + ]; + + input.forEach(bucket => { + store.emit('metrics', { + appName, + instanceId, + bucket, + }); + }); + + const seenToggles = metrics.getSeenTogglesByAppName(appName); + + t.truthy(seenToggles.length === 1); + + // metrics.se + let c = metrics.getTogglesMetrics(); + t.deepEqual(c.lastHour.toggle, { yes: 41, no: 41 }); + + clock.tick(10 * 1000); + c = metrics.getTogglesMetrics(); + t.deepEqual(c.lastHour.toggle, { yes: 41, no: 41 }); + + // at 30 + clock.tick(30 * 60 * 1000); + c = metrics.getTogglesMetrics(); + t.deepEqual(c.lastHour.toggle, { yes: 31, no: 31 }); + + // at 45 + clock.tick(15 * 60 * 1000); + c = metrics.getTogglesMetrics(); + t.deepEqual(c.lastHour.toggle, { yes: 21, no: 21 }); + + // at 1:15 + clock.tick(30 * 60 * 1000); + c = metrics.getTogglesMetrics(); + t.deepEqual(c.lastHour.toggle, { yes: 11, no: 11 }); + + // at 2:00 + clock.tick(45 * 60 * 1000); + c = metrics.getTogglesMetrics(); + t.deepEqual(c.lastHour.toggle, { yes: 0, no: 0 }); + + metrics.destroy(); + clock.restore(); +}); diff --git a/lib/client-metrics/ttl-list.js b/lib/client-metrics/ttl-list.js index 208277fcc9..8049645b50 100644 --- a/lib/client-metrics/ttl-list.js +++ b/lib/client-metrics/ttl-list.js @@ -37,11 +37,15 @@ module.exports = class TTLList extends EventEmitter { add (value, timestamp = new Date()) { const ttl = moment(timestamp).add(this.expireAmount, this.expireType); - this.list.add({ ttl, value }); + if (moment().isBefore(ttl)) { + this.list.add({ ttl, value }); + } else { + this.emit('expire', value, ttl); + } } timedCheck () { - const now = moment(new Date()); + const now = moment(); this.list.reverseRemoveUntilTrue(({ value }) => now.isBefore(value.ttl)); this.startTimer(); }