2021-08-12 15:04:37 +02:00
|
|
|
import { register } from 'prom-client';
|
|
|
|
import EventEmitter from 'events';
|
2022-09-27 11:06:06 +02:00
|
|
|
import { IEventStore } from './types/stores/event-store';
|
2021-08-12 15:04:37 +02:00
|
|
|
import { createTestConfig } from '../test/config/test-config';
|
|
|
|
import { REQUEST_TIME, DB_TIME } from './metric-events';
|
2022-07-22 11:00:22 +02:00
|
|
|
import {
|
|
|
|
CLIENT_METRICS,
|
|
|
|
CLIENT_REGISTER,
|
|
|
|
FEATURE_UPDATED,
|
|
|
|
} from './types/events';
|
2021-08-12 15:04:37 +02:00
|
|
|
import { createMetricsMonitor } from './metrics';
|
|
|
|
import createStores from '../test/fixtures/store';
|
2022-10-25 13:10:27 +02:00
|
|
|
import { InstanceStatsService } from './services/instance-stats-service';
|
|
|
|
import VersionService from './services/version-service';
|
2020-12-16 14:49:11 +01:00
|
|
|
|
|
|
|
const monitor = createMetricsMonitor();
|
2021-08-12 15:04:37 +02:00
|
|
|
const eventBus = new EventEmitter();
|
|
|
|
const prometheusRegister = register;
|
2022-09-27 11:06:06 +02:00
|
|
|
let eventStore: IEventStore;
|
2022-10-25 13:10:27 +02:00
|
|
|
let statsService: InstanceStatsService;
|
2021-08-12 15:04:37 +02:00
|
|
|
let stores;
|
2021-05-28 11:10:24 +02:00
|
|
|
beforeAll(() => {
|
2021-04-22 10:07:10 +02:00
|
|
|
const config = createTestConfig({
|
|
|
|
server: {
|
|
|
|
serverMetrics: true,
|
|
|
|
},
|
|
|
|
});
|
2021-08-12 15:04:37 +02:00
|
|
|
stores = createStores();
|
2022-09-27 11:06:06 +02:00
|
|
|
eventStore = stores.eventStore;
|
2022-10-25 13:10:27 +02:00
|
|
|
const versionService = new VersionService(stores, config);
|
|
|
|
statsService = new InstanceStatsService(stores, config, versionService);
|
2021-08-12 15:04:37 +02:00
|
|
|
const db = {
|
|
|
|
client: {
|
|
|
|
pool: {
|
|
|
|
min: 0,
|
|
|
|
max: 4,
|
|
|
|
numUsed: () => 2,
|
|
|
|
numFree: () => 2,
|
|
|
|
numPendingAcquires: () => 0,
|
|
|
|
numPendingCreates: () => 1,
|
2021-02-04 14:14:46 +01:00
|
|
|
},
|
2020-08-03 13:34:10 +02:00
|
|
|
},
|
|
|
|
};
|
2021-08-12 15:04:37 +02:00
|
|
|
// @ts-ignore - We don't want a full knex implementation for our tests, it's enough that it actually yields the numbers we want.
|
2022-10-25 13:10:27 +02:00
|
|
|
monitor.startMonitoring(
|
|
|
|
config,
|
|
|
|
stores,
|
|
|
|
'4.0.0',
|
|
|
|
eventBus,
|
|
|
|
statsService,
|
|
|
|
//@ts-ignore
|
|
|
|
db,
|
|
|
|
);
|
2020-12-16 14:49:11 +01:00
|
|
|
});
|
2021-05-28 11:10:24 +02:00
|
|
|
afterAll(() => {
|
2020-12-16 14:49:11 +01:00
|
|
|
monitor.stopMonitoring();
|
2018-05-23 11:24:24 +02:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should collect metrics for requests', async () => {
|
2017-06-28 10:17:14 +02:00
|
|
|
eventBus.emit(REQUEST_TIME, {
|
|
|
|
path: 'somePath',
|
|
|
|
method: 'GET',
|
|
|
|
statusCode: 200,
|
|
|
|
time: 1337,
|
|
|
|
});
|
2016-12-04 14:09:37 +01:00
|
|
|
|
2021-02-04 13:20:10 +01:00
|
|
|
const metrics = await prometheusRegister.metrics();
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(metrics).toMatch(
|
2023-04-17 09:11:22 +02:00
|
|
|
/http_request_duration_milliseconds\{quantile="0\.99",path="somePath",method="GET",status="200",appName="undefined"\}.*1337/,
|
2017-06-28 10:17:14 +02:00
|
|
|
);
|
2016-12-04 14:09:37 +01:00
|
|
|
});
|
2018-05-23 11:24:24 +02:00
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should collect metrics for updated toggles', async () => {
|
2021-08-12 15:04:37 +02:00
|
|
|
stores.eventStore.emit(FEATURE_UPDATED, {
|
2021-11-12 13:15:51 +01:00
|
|
|
featureName: 'TestToggle',
|
2022-09-08 11:01:27 +02:00
|
|
|
project: 'default',
|
2018-05-23 11:24:24 +02:00
|
|
|
data: { name: 'TestToggle' },
|
|
|
|
});
|
|
|
|
|
2021-02-04 13:20:10 +01:00
|
|
|
const metrics = await prometheusRegister.metrics();
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(metrics).toMatch(
|
2023-04-17 09:11:22 +02:00
|
|
|
/feature_toggle_update_total\{toggle="TestToggle",project="default",environment="default"\} 1/,
|
2021-05-28 11:10:24 +02:00
|
|
|
);
|
2018-05-23 11:24:24 +02:00
|
|
|
});
|
2018-11-28 15:50:49 +01:00
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should collect metrics for client metric reports', async () => {
|
2021-12-09 21:02:58 +01:00
|
|
|
eventBus.emit(CLIENT_METRICS, {
|
2018-11-28 15:50:49 +01:00
|
|
|
bucket: {
|
|
|
|
toggles: {
|
|
|
|
TestToggle: {
|
|
|
|
yes: 10,
|
|
|
|
no: 5,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2021-02-04 13:20:10 +01:00
|
|
|
const metrics = await prometheusRegister.metrics();
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(metrics).toMatch(
|
2023-04-17 09:11:22 +02:00
|
|
|
/feature_toggle_usage_total\{toggle="TestToggle",active="true",appName="undefined"\} 10\nfeature_toggle_usage_total\{toggle="TestToggle",active="false",appName="undefined"\} 5/,
|
2018-11-28 15:50:49 +01:00
|
|
|
);
|
|
|
|
});
|
2019-08-04 11:10:51 +02:00
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should collect metrics for db query timings', async () => {
|
2019-08-04 11:10:51 +02:00
|
|
|
eventBus.emit(DB_TIME, {
|
|
|
|
store: 'foo',
|
|
|
|
action: 'bar',
|
|
|
|
time: 0.1337,
|
|
|
|
});
|
|
|
|
|
2021-02-04 13:20:10 +01:00
|
|
|
const metrics = await prometheusRegister.metrics();
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(metrics).toMatch(
|
2023-04-17 09:11:22 +02:00
|
|
|
/db_query_duration_seconds\{quantile="0\.99",store="foo",action="bar"\} 0.1337/,
|
2019-08-04 11:10:51 +02:00
|
|
|
);
|
|
|
|
});
|
2020-02-28 14:50:32 +01:00
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should collect metrics for feature toggle size', async () => {
|
2022-10-25 13:10:27 +02:00
|
|
|
await new Promise((done) => {
|
|
|
|
setTimeout(done, 10);
|
|
|
|
});
|
2021-02-04 13:20:10 +01:00
|
|
|
const metrics = await prometheusRegister.metrics();
|
2023-04-17 09:11:22 +02:00
|
|
|
expect(metrics).toMatch(/feature_toggles_total\{version="(.*)"\} 0/);
|
2020-02-28 14:50:32 +01:00
|
|
|
});
|
2021-02-04 14:14:46 +01:00
|
|
|
|
2022-12-16 12:16:51 +01:00
|
|
|
test('should collect metrics for feature toggle size', async () => {
|
|
|
|
await new Promise((done) => {
|
|
|
|
setTimeout(done, 10);
|
|
|
|
});
|
|
|
|
const metrics = await prometheusRegister.metrics();
|
2023-04-17 09:11:22 +02:00
|
|
|
expect(metrics).toMatch(/client_apps_total\{range="(.*)"\} 0/);
|
2022-12-16 12:16:51 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('Should collect metrics for database', async () => {
|
2021-02-04 14:14:46 +01:00
|
|
|
const metrics = await prometheusRegister.metrics();
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(metrics).toMatch(/db_pool_max/);
|
|
|
|
expect(metrics).toMatch(/db_pool_min/);
|
|
|
|
expect(metrics).toMatch(/db_pool_used/);
|
|
|
|
expect(metrics).toMatch(/db_pool_free/);
|
|
|
|
expect(metrics).toMatch(/db_pool_pending_creates/);
|
|
|
|
expect(metrics).toMatch(/db_pool_pending_acquires/);
|
2021-02-04 14:14:46 +01:00
|
|
|
});
|
2022-07-22 11:00:22 +02:00
|
|
|
|
|
|
|
test('Should collect metrics for client sdk versions', async () => {
|
2022-09-27 11:06:06 +02:00
|
|
|
eventStore.emit(CLIENT_REGISTER, {
|
|
|
|
sdkVersion: 'unleash-client-node:3.2.5',
|
|
|
|
});
|
|
|
|
eventStore.emit(CLIENT_REGISTER, {
|
|
|
|
sdkVersion: 'unleash-client-node:3.2.5',
|
|
|
|
});
|
|
|
|
eventStore.emit(CLIENT_REGISTER, {
|
|
|
|
sdkVersion: 'unleash-client-node:3.2.5',
|
|
|
|
});
|
|
|
|
eventStore.emit(CLIENT_REGISTER, {
|
|
|
|
sdkVersion: 'unleash-client-java:5.0.0',
|
|
|
|
});
|
|
|
|
eventStore.emit(CLIENT_REGISTER, {
|
|
|
|
sdkVersion: 'unleash-client-java:5.0.0',
|
|
|
|
});
|
|
|
|
eventStore.emit(CLIENT_REGISTER, {
|
|
|
|
sdkVersion: 'unleash-client-java:5.0.0',
|
|
|
|
});
|
2022-07-22 11:00:22 +02:00
|
|
|
const metrics = await prometheusRegister.getSingleMetricAsString(
|
|
|
|
'client_sdk_versions',
|
|
|
|
);
|
|
|
|
expect(metrics).toMatch(
|
2023-04-17 09:11:22 +02:00
|
|
|
/client_sdk_versions\{sdk_name="unleash-client-node",sdk_version="3\.2\.5"\} 3/,
|
2022-07-22 11:00:22 +02:00
|
|
|
);
|
|
|
|
expect(metrics).toMatch(
|
2023-04-17 09:11:22 +02:00
|
|
|
/client_sdk_versions\{sdk_name="unleash-client-java",sdk_version="5\.0\.0"\} 3/,
|
2022-07-22 11:00:22 +02:00
|
|
|
);
|
2022-09-27 11:06:06 +02:00
|
|
|
eventStore.emit(CLIENT_REGISTER, {
|
|
|
|
sdkVersion: 'unleash-client-node:3.2.5',
|
|
|
|
});
|
2022-07-22 11:00:22 +02:00
|
|
|
const newmetrics = await prometheusRegister.getSingleMetricAsString(
|
|
|
|
'client_sdk_versions',
|
|
|
|
);
|
|
|
|
expect(newmetrics).toMatch(
|
2023-04-17 09:11:22 +02:00
|
|
|
/client_sdk_versions\{sdk_name="unleash-client-node",sdk_version="3\.2\.5"\} 4/,
|
2022-07-22 11:00:22 +02:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Should not collect client sdk version if sdkVersion is of wrong format or non-existent', async () => {
|
2022-09-27 11:06:06 +02:00
|
|
|
eventStore.emit(CLIENT_REGISTER, { sdkVersion: 'unleash-client-rust' });
|
|
|
|
eventStore.emit(CLIENT_REGISTER, {});
|
2022-07-22 11:00:22 +02:00
|
|
|
const metrics = await prometheusRegister.getSingleMetricAsString(
|
|
|
|
'client_sdk_versions',
|
|
|
|
);
|
|
|
|
expect(metrics).not.toMatch(/unleash-client-rust/);
|
|
|
|
});
|