mirror of
https://github.com/Unleash/unleash.git
synced 2025-11-10 01:19:53 +01:00
334 lines
9.2 KiB
TypeScript
334 lines
9.2 KiB
TypeScript
import dbInit, {
|
|
type ITestDb,
|
|
} from '../../../../test/e2e/helpers/database-init.js';
|
|
import {
|
|
type IUnleashTest,
|
|
setupAppWithCustomConfig,
|
|
} from '../../../../test/e2e/helpers/test-helper.js';
|
|
import getLogger from '../../../../test/fixtures/no-logger.js';
|
|
import { DEFAULT_ENV } from '../../../server-impl.js';
|
|
import type { IClientMetricsEnv } from './client-metrics-store-v2-type.js';
|
|
import { subHours } from 'date-fns';
|
|
|
|
let app: IUnleashTest;
|
|
let db: ITestDb;
|
|
|
|
const fetchHoursBack = (hoursBack: number, feature: string = 'demo') => {
|
|
return app.request
|
|
.get(
|
|
`/api/admin/client-metrics/features/${feature}/raw?hoursBack=${hoursBack}`,
|
|
)
|
|
.expect('Content-Type', /json/)
|
|
.expect(200)
|
|
.then((res) => res.body);
|
|
};
|
|
|
|
beforeAll(async () => {
|
|
db = await dbInit('client_metrics_serial', getLogger);
|
|
app = await setupAppWithCustomConfig(
|
|
db.stores,
|
|
{
|
|
experimental: {
|
|
flags: {
|
|
strictSchemaValidation: true,
|
|
extendedUsageMetrics: true,
|
|
},
|
|
},
|
|
},
|
|
db.rawDatabase,
|
|
);
|
|
});
|
|
|
|
afterAll(async () => {
|
|
if (db) {
|
|
await db.destroy();
|
|
}
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await db.reset();
|
|
await db.stores.clientMetricsStoreV2.deleteAll();
|
|
});
|
|
|
|
test('should return raw metrics, aggregated on key', async () => {
|
|
const date = new Date();
|
|
const metrics: IClientMetricsEnv[] = [
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 2,
|
|
no: 2,
|
|
},
|
|
{
|
|
featureName: 't2',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 5,
|
|
no: 5,
|
|
},
|
|
{
|
|
featureName: 't2',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 2,
|
|
no: 99,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 3,
|
|
no: 2,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: 'test',
|
|
timestamp: date,
|
|
yes: 1,
|
|
no: 3,
|
|
},
|
|
];
|
|
|
|
await db.stores.clientMetricsStoreV2.batchInsertMetrics(metrics);
|
|
|
|
const { body: demo } = await app.request
|
|
.get('/api/admin/client-metrics/features/demo/raw')
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
const { body: t2 } = await app.request
|
|
.get('/api/admin/client-metrics/features/t2/raw')
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
|
|
expect(demo.data).toHaveLength(48);
|
|
expect(demo.data[46].environment).toBe(DEFAULT_ENV);
|
|
expect(demo.data[46].yes).toBe(5);
|
|
expect(demo.data[46].no).toBe(4);
|
|
expect(demo.data[47].environment).toBe('test');
|
|
expect(demo.data[47].yes).toBe(1);
|
|
expect(demo.data[47].no).toBe(3);
|
|
|
|
expect(t2.data).toHaveLength(24);
|
|
expect(t2.data[23].environment).toBe(DEFAULT_ENV);
|
|
expect(t2.data[23].yes).toBe(7);
|
|
expect(t2.data[23].no).toBe(104);
|
|
});
|
|
|
|
test('should support the hoursBack query param for raw metrics', async () => {
|
|
const date = new Date();
|
|
const metrics: IClientMetricsEnv[] = [
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 1,
|
|
no: 1,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: subHours(date, 12),
|
|
yes: 2,
|
|
no: 2,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: subHours(date, 32),
|
|
yes: 3,
|
|
no: 3,
|
|
},
|
|
];
|
|
|
|
await db.stores.clientMetricsStoreV2.batchInsertMetrics(metrics);
|
|
await db.stores.clientMetricsStoreV2.aggregateDailyMetrics();
|
|
|
|
const hours1 = await fetchHoursBack(1);
|
|
const hours24 = await fetchHoursBack(24);
|
|
const hours48 = await fetchHoursBack(48);
|
|
const hoursTooFew = await fetchHoursBack(-999);
|
|
const hoursTooMany = await fetchHoursBack(24 * 31 * 3 + 1); // 3 months + 1 hour
|
|
const days = await fetchHoursBack(48 + 1); // switch to days after 48 hours
|
|
|
|
expect(hours1.data).toHaveLength(1);
|
|
expect(hours24.data).toHaveLength(24);
|
|
expect(hours48.data).toHaveLength(48);
|
|
expect(hoursTooFew.data).toHaveLength(24);
|
|
expect(hoursTooMany.data).toHaveLength(24);
|
|
expect(days.data).toHaveLength(2); // two days of data
|
|
});
|
|
|
|
test('should return toggle summary', async () => {
|
|
const date = new Date();
|
|
const metrics: IClientMetricsEnv[] = [
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 2,
|
|
no: 2,
|
|
},
|
|
{
|
|
featureName: 't2',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 5,
|
|
no: 5,
|
|
},
|
|
{
|
|
featureName: 't2',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 2,
|
|
no: 99,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 3,
|
|
no: 2,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: 'test',
|
|
timestamp: date,
|
|
yes: 1,
|
|
no: 3,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'backend-api',
|
|
environment: 'test',
|
|
timestamp: date,
|
|
yes: 1,
|
|
no: 3,
|
|
},
|
|
];
|
|
|
|
await db.stores.clientMetricsStoreV2.batchInsertMetrics(metrics);
|
|
|
|
const { body: demo } = await app.request
|
|
.get('/api/admin/client-metrics/features/demo')
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
|
|
const test = demo.lastHourUsage.find((u) => u.environment === 'test');
|
|
const defaultEnv = demo.lastHourUsage.find(
|
|
(u) => u.environment === DEFAULT_ENV,
|
|
);
|
|
|
|
expect(demo.featureName).toBe('demo');
|
|
expect(demo.lastHourUsage).toHaveLength(2);
|
|
expect(test.environment).toBe('test');
|
|
expect(test.yes).toBe(2);
|
|
expect(test.no).toBe(6);
|
|
expect(defaultEnv.environment).toBe(DEFAULT_ENV);
|
|
expect(defaultEnv.yes).toBe(5);
|
|
expect(defaultEnv.no).toBe(4);
|
|
expect(demo.seenApplications).toStrictEqual(['backend-api', 'web']);
|
|
});
|
|
|
|
test('should only include last hour of metrics return toggle summary', async () => {
|
|
const now = new Date();
|
|
const dateTwoHoursAgo = subHours(now, 2);
|
|
const metrics: IClientMetricsEnv[] = [
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: now,
|
|
yes: 2,
|
|
no: 2,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: now,
|
|
yes: 3,
|
|
no: 2,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: 'test',
|
|
timestamp: now,
|
|
yes: 1,
|
|
no: 3,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'backend-api',
|
|
environment: 'test',
|
|
timestamp: now,
|
|
yes: 1,
|
|
no: 3,
|
|
},
|
|
{
|
|
featureName: 'demo',
|
|
appName: 'backend-api',
|
|
environment: 'test',
|
|
timestamp: dateTwoHoursAgo,
|
|
yes: 55,
|
|
no: 55,
|
|
},
|
|
];
|
|
|
|
await db.stores.clientMetricsStoreV2.batchInsertMetrics(metrics);
|
|
|
|
const { body: demo } = await app.request
|
|
.get('/api/admin/client-metrics/features/demo')
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
|
|
const test = demo.lastHourUsage.find((u) => u.environment === 'test');
|
|
const defaultEnv = demo.lastHourUsage.find(
|
|
(u) => u.environment === DEFAULT_ENV,
|
|
);
|
|
|
|
expect(demo.featureName).toBe('demo');
|
|
expect(demo.lastHourUsage).toHaveLength(2);
|
|
expect(defaultEnv.environment).toBe(DEFAULT_ENV);
|
|
expect(defaultEnv.yes).toBe(5);
|
|
expect(defaultEnv.no).toBe(4);
|
|
expect(test.environment).toBe('test');
|
|
expect(test.yes).toBe(2);
|
|
expect(test.no).toBe(6);
|
|
expect(demo.seenApplications).toStrictEqual(['backend-api', 'web']);
|
|
});
|
|
|
|
test('should support posting and receiving variants data', async () => {
|
|
const date = new Date();
|
|
const metric = {
|
|
featureName: 'demo',
|
|
appName: 'web',
|
|
environment: DEFAULT_ENV,
|
|
timestamp: date,
|
|
yes: 7,
|
|
no: 1,
|
|
variants: { red: 3, blue: 4 },
|
|
};
|
|
const metrics: IClientMetricsEnv[] = [metric];
|
|
|
|
await db.stores.clientMetricsStoreV2.batchInsertMetrics(metrics);
|
|
|
|
const hours1 = await fetchHoursBack(1);
|
|
|
|
expect(hours1.data[0].variants).toMatchObject(metric.variants);
|
|
});
|