mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			380 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			380 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
const test = require('ava');
 | 
						|
const UnleashClientMetrics = require('./index');
 | 
						|
const moment = require('moment');
 | 
						|
const lolex = require('lolex');
 | 
						|
 | 
						|
const { EventEmitter } = require('events');
 | 
						|
 | 
						|
const appName = 'appName';
 | 
						|
const instanceId = 'instanceId';
 | 
						|
 | 
						|
test('should work without state', t => {
 | 
						|
    const store = new EventEmitter();
 | 
						|
    const metrics = new UnleashClientMetrics(store);
 | 
						|
 | 
						|
    t.truthy(metrics.getAppsWithToggles());
 | 
						|
    t.truthy(metrics.getTogglesMetrics());
 | 
						|
 | 
						|
    metrics.destroy();
 | 
						|
});
 | 
						|
 | 
						|
test.cb('data should expire', t => {
 | 
						|
    const clock = lolex.install();
 | 
						|
 | 
						|
    const store = new EventEmitter();
 | 
						|
    const metrics = new UnleashClientMetrics(store);
 | 
						|
 | 
						|
    metrics.addPayload({
 | 
						|
        appName,
 | 
						|
        instanceId,
 | 
						|
        bucket: {
 | 
						|
            start: Date.now() - 2000,
 | 
						|
            stop: Date.now() - 1000,
 | 
						|
            toggles: {
 | 
						|
                toggleX: {
 | 
						|
                    yes: 123,
 | 
						|
                    no: 0,
 | 
						|
                },
 | 
						|
            },
 | 
						|
        },
 | 
						|
    });
 | 
						|
 | 
						|
    let lastHourExpires = 0;
 | 
						|
    metrics.lastHourList.on('expire', () => {
 | 
						|
        lastHourExpires++;
 | 
						|
    });
 | 
						|
 | 
						|
    let lastMinExpires = 0;
 | 
						|
    metrics.lastMinuteList.on('expire', () => {
 | 
						|
        lastMinExpires++;
 | 
						|
    });
 | 
						|
 | 
						|
    clock.tick(60 * 1000);
 | 
						|
    t.true(lastMinExpires === 1);
 | 
						|
    t.true(lastHourExpires === 0);
 | 
						|
 | 
						|
    clock.tick(60 * 60 * 1000);
 | 
						|
    t.true(lastMinExpires === 1);
 | 
						|
    t.true(lastHourExpires === 1);
 | 
						|
 | 
						|
    clock.uninstall();
 | 
						|
    t.end();
 | 
						|
});
 | 
						|
 | 
						|
test('should listen to metrics from store', t => {
 | 
						|
    const store = new EventEmitter();
 | 
						|
    const metrics = new UnleashClientMetrics(store);
 | 
						|
    store.emit('metrics', {
 | 
						|
        appName,
 | 
						|
        instanceId,
 | 
						|
        bucket: {
 | 
						|
            start: new Date(),
 | 
						|
            stop: new Date(),
 | 
						|
            toggles: {
 | 
						|
                toggleX: {
 | 
						|
                    yes: 123,
 | 
						|
                    no: 0,
 | 
						|
                },
 | 
						|
            },
 | 
						|
        },
 | 
						|
    });
 | 
						|
 | 
						|
    t.truthy(metrics.apps[appName].count === 123);
 | 
						|
    t.truthy(metrics.globalCount === 123);
 | 
						|
 | 
						|
    t.deepEqual(metrics.getTogglesMetrics().lastHour.toggleX, {
 | 
						|
        yes: 123,
 | 
						|
        no: 0,
 | 
						|
    });
 | 
						|
    t.deepEqual(metrics.getTogglesMetrics().lastMinute.toggleX, {
 | 
						|
        yes: 123,
 | 
						|
        no: 0,
 | 
						|
    });
 | 
						|
 | 
						|
    metrics.addPayload({
 | 
						|
        appName,
 | 
						|
        instanceId,
 | 
						|
        bucket: {
 | 
						|
            start: new Date(),
 | 
						|
            stop: new Date(),
 | 
						|
            toggles: {
 | 
						|
                toggleX: {
 | 
						|
                    yes: 10,
 | 
						|
                    no: 10,
 | 
						|
                },
 | 
						|
            },
 | 
						|
        },
 | 
						|
    });
 | 
						|
 | 
						|
    t.truthy(metrics.globalCount === 143);
 | 
						|
    t.deepEqual(metrics.getTogglesMetrics().lastHour.toggleX, {
 | 
						|
        yes: 133,
 | 
						|
        no: 10,
 | 
						|
    });
 | 
						|
    t.deepEqual(metrics.getTogglesMetrics().lastMinute.toggleX, {
 | 
						|
        yes: 133,
 | 
						|
        no: 10,
 | 
						|
    });
 | 
						|
 | 
						|
    metrics.destroy();
 | 
						|
});
 | 
						|
 | 
						|
test('should build up list of seend toggles when new metrics arrives', t => {
 | 
						|
    const store = new EventEmitter();
 | 
						|
    const metrics = new UnleashClientMetrics(store);
 | 
						|
    store.emit('metrics', {
 | 
						|
        appName,
 | 
						|
        instanceId,
 | 
						|
        bucket: {
 | 
						|
            start: new Date(),
 | 
						|
            stop: new Date(),
 | 
						|
            toggles: {
 | 
						|
                toggleX: {
 | 
						|
                    yes: 123,
 | 
						|
                    no: 0,
 | 
						|
                },
 | 
						|
                toggleY: {
 | 
						|
                    yes: 50,
 | 
						|
                    no: 50,
 | 
						|
                },
 | 
						|
            },
 | 
						|
        },
 | 
						|
    });
 | 
						|
 | 
						|
    const appToggles = metrics.getAppsWithToggles();
 | 
						|
    const togglesForApp = metrics.getSeenTogglesByAppName(appName);
 | 
						|
 | 
						|
    t.truthy(appToggles.length === 1);
 | 
						|
    t.truthy(appToggles[0].seenToggles.length === 2);
 | 
						|
    t.truthy(appToggles[0].seenToggles.includes('toggleX'));
 | 
						|
    t.truthy(appToggles[0].seenToggles.includes('toggleY'));
 | 
						|
 | 
						|
    t.truthy(togglesForApp.length === 2);
 | 
						|
    t.truthy(togglesForApp.includes('toggleX'));
 | 
						|
    t.truthy(togglesForApp.includes('toggleY'));
 | 
						|
    metrics.destroy();
 | 
						|
});
 | 
						|
 | 
						|
test('should handle a lot of toggles', t => {
 | 
						|
    const store = new EventEmitter();
 | 
						|
    const metrics = new UnleashClientMetrics(store);
 | 
						|
 | 
						|
    const toggleCounts = {};
 | 
						|
    for (let i = 0; i < 100; i++) {
 | 
						|
        toggleCounts[`toggle${i}`] = { yes: i, no: i };
 | 
						|
    }
 | 
						|
 | 
						|
    store.emit('metrics', {
 | 
						|
        appName,
 | 
						|
        instanceId,
 | 
						|
        bucket: {
 | 
						|
            start: new Date(),
 | 
						|
            stop: new Date(),
 | 
						|
            toggles: toggleCounts,
 | 
						|
        },
 | 
						|
    });
 | 
						|
 | 
						|
    const seenToggles = metrics.getSeenTogglesByAppName(appName);
 | 
						|
 | 
						|
    t.truthy(seenToggles.length === 100);
 | 
						|
    metrics.destroy();
 | 
						|
});
 | 
						|
 | 
						|
test('should have correct values for lastMinute', t => {
 | 
						|
    const clock = lolex.install();
 | 
						|
 | 
						|
    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.uninstall();
 | 
						|
});
 | 
						|
 | 
						|
test('should have correct values for lastHour', t => {
 | 
						|
    const clock = lolex.install();
 | 
						|
 | 
						|
    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.uninstall();
 | 
						|
});
 | 
						|
 | 
						|
test('should not fail when toggle metrics is missing yes/no field', t => {
 | 
						|
    const store = new EventEmitter();
 | 
						|
    const metrics = new UnleashClientMetrics(store);
 | 
						|
    store.emit('metrics', {
 | 
						|
        appName,
 | 
						|
        instanceId,
 | 
						|
        bucket: {
 | 
						|
            start: new Date(),
 | 
						|
            stop: new Date(),
 | 
						|
            toggles: {
 | 
						|
                toggleX: {
 | 
						|
                    yes: 123,
 | 
						|
                    no: 0,
 | 
						|
                },
 | 
						|
            },
 | 
						|
        },
 | 
						|
    });
 | 
						|
 | 
						|
    metrics.addPayload({
 | 
						|
        appName,
 | 
						|
        instanceId,
 | 
						|
        bucket: {
 | 
						|
            start: new Date(),
 | 
						|
            stop: new Date(),
 | 
						|
            toggles: {
 | 
						|
                toggleX: {
 | 
						|
                    blue: 10,
 | 
						|
                    green: 10,
 | 
						|
                },
 | 
						|
            },
 | 
						|
        },
 | 
						|
    });
 | 
						|
 | 
						|
    t.is(metrics.globalCount, 123);
 | 
						|
    t.deepEqual(metrics.getTogglesMetrics().lastMinute.toggleX, {
 | 
						|
        yes: 123,
 | 
						|
        no: 0,
 | 
						|
    });
 | 
						|
 | 
						|
    metrics.destroy();
 | 
						|
});
 |