mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-31 13:47:02 +02:00
parent
22014f3c62
commit
5bacc7ba36
@ -2,7 +2,11 @@ import { register } from 'prom-client';
|
|||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import { createTestConfig } from '../test/config/test-config';
|
import { createTestConfig } from '../test/config/test-config';
|
||||||
import { REQUEST_TIME, DB_TIME } from './metric-events';
|
import { REQUEST_TIME, DB_TIME } from './metric-events';
|
||||||
import { CLIENT_METRICS, FEATURE_UPDATED } from './types/events';
|
import {
|
||||||
|
CLIENT_METRICS,
|
||||||
|
CLIENT_REGISTER,
|
||||||
|
FEATURE_UPDATED,
|
||||||
|
} from './types/events';
|
||||||
import { createMetricsMonitor } from './metrics';
|
import { createMetricsMonitor } from './metrics';
|
||||||
import createStores from '../test/fixtures/store';
|
import createStores from '../test/fixtures/store';
|
||||||
|
|
||||||
@ -32,7 +36,6 @@ beforeAll(() => {
|
|||||||
// @ts-ignore - We don't want a full knex implementation for our tests, it's enough that it actually yields the numbers we want.
|
// @ts-ignore - We don't want a full knex implementation for our tests, it's enough that it actually yields the numbers we want.
|
||||||
monitor.startMonitoring(config, stores, '4.0.0', eventBus, db);
|
monitor.startMonitoring(config, stores, '4.0.0', eventBus, db);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
monitor.stopMonitoring();
|
monitor.stopMonitoring();
|
||||||
});
|
});
|
||||||
@ -108,3 +111,37 @@ test('Should collect metrics for database', async () => {
|
|||||||
expect(metrics).toMatch(/db_pool_pending_creates/);
|
expect(metrics).toMatch(/db_pool_pending_creates/);
|
||||||
expect(metrics).toMatch(/db_pool_pending_acquires/);
|
expect(metrics).toMatch(/db_pool_pending_acquires/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Should collect metrics for client sdk versions', async () => {
|
||||||
|
eventBus.emit(CLIENT_REGISTER, { sdkVersion: 'unleash-client-node:3.2.5' });
|
||||||
|
eventBus.emit(CLIENT_REGISTER, { sdkVersion: 'unleash-client-node:3.2.5' });
|
||||||
|
eventBus.emit(CLIENT_REGISTER, { sdkVersion: 'unleash-client-node:3.2.5' });
|
||||||
|
eventBus.emit(CLIENT_REGISTER, { sdkVersion: 'unleash-client-java:5.0.0' });
|
||||||
|
eventBus.emit(CLIENT_REGISTER, { sdkVersion: 'unleash-client-java:5.0.0' });
|
||||||
|
eventBus.emit(CLIENT_REGISTER, { sdkVersion: 'unleash-client-java:5.0.0' });
|
||||||
|
const metrics = await prometheusRegister.getSingleMetricAsString(
|
||||||
|
'client_sdk_versions',
|
||||||
|
);
|
||||||
|
expect(metrics).toMatch(
|
||||||
|
/client_sdk_versions\{sdk_name="unleash-client-node",sdk_version="3\.2\.5"} 3/,
|
||||||
|
);
|
||||||
|
expect(metrics).toMatch(
|
||||||
|
/client_sdk_versions\{sdk_name="unleash-client-java",sdk_version="5\.0\.0"} 3/,
|
||||||
|
);
|
||||||
|
eventBus.emit(CLIENT_REGISTER, { sdkVersion: 'unleash-client-node:3.2.5' });
|
||||||
|
const newmetrics = await prometheusRegister.getSingleMetricAsString(
|
||||||
|
'client_sdk_versions',
|
||||||
|
);
|
||||||
|
expect(newmetrics).toMatch(
|
||||||
|
/client_sdk_versions\{sdk_name="unleash-client-node",sdk_version="3\.2\.5"} 4/,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should not collect client sdk version if sdkVersion is of wrong format or non-existent', async () => {
|
||||||
|
eventBus.emit(CLIENT_REGISTER, { sdkVersion: 'unleash-client-rust' });
|
||||||
|
eventBus.emit(CLIENT_REGISTER, {});
|
||||||
|
const metrics = await prometheusRegister.getSingleMetricAsString(
|
||||||
|
'client_sdk_versions',
|
||||||
|
);
|
||||||
|
expect(metrics).not.toMatch(/unleash-client-rust/);
|
||||||
|
});
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
FEATURE_STRATEGY_UPDATE,
|
FEATURE_STRATEGY_UPDATE,
|
||||||
FEATURE_UPDATED,
|
FEATURE_UPDATED,
|
||||||
CLIENT_METRICS,
|
CLIENT_METRICS,
|
||||||
|
CLIENT_REGISTER,
|
||||||
} from './types/events';
|
} from './types/events';
|
||||||
import { IUnleashConfig } from './types/option';
|
import { IUnleashConfig } from './types/option';
|
||||||
import { IUnleashStores } from './types/stores';
|
import { IUnleashStores } from './types/stores';
|
||||||
@ -80,6 +81,12 @@ export default class MetricsMonitor {
|
|||||||
help: 'Number of projects',
|
help: 'Number of projects',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const clientSdkVersionUsage = new client.Counter({
|
||||||
|
name: 'client_sdk_versions',
|
||||||
|
help: 'Which sdk versions are being used',
|
||||||
|
labelNames: ['sdk_name', 'sdk_version'],
|
||||||
|
});
|
||||||
|
|
||||||
async function collectStaticCounters() {
|
async function collectStaticCounters() {
|
||||||
let togglesCount: number = 0;
|
let togglesCount: number = 0;
|
||||||
let usersCount: number;
|
let usersCount: number;
|
||||||
@ -157,6 +164,12 @@ export default class MetricsMonitor {
|
|||||||
.inc(entry[1].no);
|
.inc(entry[1].no);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
eventBus.on(CLIENT_REGISTER, (m) => {
|
||||||
|
if (m.sdkVersion && m.sdkVersion.indexOf(':') > -1) {
|
||||||
|
const [sdkName, sdkVersion] = m.sdkVersion.split(':');
|
||||||
|
clientSdkVersionUsage.labels(sdkName, sdkVersion).inc();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.configureDbMetrics(db, eventBus);
|
this.configureDbMetrics(db, eventBus);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import ClientInstanceService from './instance-service';
|
|||||||
import getLogger from '../../../test/fixtures/no-logger';
|
import getLogger from '../../../test/fixtures/no-logger';
|
||||||
import { IClientApp } from '../../types/model';
|
import { IClientApp } from '../../types/model';
|
||||||
import { secondsToMilliseconds } from 'date-fns';
|
import { secondsToMilliseconds } from 'date-fns';
|
||||||
|
import FakeEventStore from '../../../test/fixtures/fake-event-store';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility to wait for any pending promises in the test subject code.
|
* A utility to wait for any pending promises in the test subject code.
|
||||||
@ -54,7 +55,7 @@ test('Multiple registrations of same appname and instanceid within same time per
|
|||||||
featureToggleStore: null,
|
featureToggleStore: null,
|
||||||
clientApplicationsStore,
|
clientApplicationsStore,
|
||||||
clientInstanceStore,
|
clientInstanceStore,
|
||||||
eventStore: null,
|
eventStore: new FakeEventStore(),
|
||||||
},
|
},
|
||||||
{ getLogger },
|
{ getLogger },
|
||||||
);
|
);
|
||||||
@ -104,7 +105,7 @@ test('Multiple unique clients causes multiple registrations', async () => {
|
|||||||
featureToggleStore: null,
|
featureToggleStore: null,
|
||||||
clientApplicationsStore,
|
clientApplicationsStore,
|
||||||
clientInstanceStore,
|
clientInstanceStore,
|
||||||
eventStore: null,
|
eventStore: new FakeEventStore(),
|
||||||
},
|
},
|
||||||
{ getLogger },
|
{ getLogger },
|
||||||
);
|
);
|
||||||
@ -157,7 +158,7 @@ test('Same client registered outside of dedup interval will be registered twice'
|
|||||||
featureToggleStore: null,
|
featureToggleStore: null,
|
||||||
clientApplicationsStore,
|
clientApplicationsStore,
|
||||||
clientInstanceStore,
|
clientInstanceStore,
|
||||||
eventStore: null,
|
eventStore: new FakeEventStore(),
|
||||||
},
|
},
|
||||||
{ getLogger },
|
{ getLogger },
|
||||||
bulkInterval,
|
bulkInterval,
|
||||||
@ -210,7 +211,7 @@ test('No registrations during a time period will not call stores', async () => {
|
|||||||
featureToggleStore: null,
|
featureToggleStore: null,
|
||||||
clientApplicationsStore,
|
clientApplicationsStore,
|
||||||
clientInstanceStore,
|
clientInstanceStore,
|
||||||
eventStore: null,
|
eventStore: new FakeEventStore(),
|
||||||
},
|
},
|
||||||
{ getLogger },
|
{ getLogger },
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { applicationSchema } from './schema';
|
import { applicationSchema } from './schema';
|
||||||
import { APPLICATION_CREATED } from '../../types/events';
|
import { APPLICATION_CREATED, CLIENT_REGISTER } from '../../types/events';
|
||||||
import { IApplication } from './models';
|
import { IApplication } from './models';
|
||||||
import { IUnleashStores } from '../../types/stores';
|
import { IUnleashStores } from '../../types/stores';
|
||||||
import { IUnleashConfig } from '../../types/option';
|
import { IUnleashConfig } from '../../types/option';
|
||||||
@ -111,6 +111,7 @@ export default class ClientInstanceService {
|
|||||||
value.clientIp = clientIp;
|
value.clientIp = clientIp;
|
||||||
value.createdBy = clientIp;
|
value.createdBy = clientIp;
|
||||||
this.seenClients[this.clientKey(value)] = value;
|
this.seenClients[this.clientKey(value)] = value;
|
||||||
|
this.eventStore.emit(CLIENT_REGISTER, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
async announceUnannounced(): Promise<void> {
|
async announceUnannounced(): Promise<void> {
|
||||||
|
@ -74,6 +74,7 @@ export const SETTING_UPDATED = 'setting-updated';
|
|||||||
export const SETTING_DELETED = 'setting-deleted';
|
export const SETTING_DELETED = 'setting-deleted';
|
||||||
|
|
||||||
export const CLIENT_METRICS = 'client-metrics';
|
export const CLIENT_METRICS = 'client-metrics';
|
||||||
|
export const CLIENT_REGISTER = 'client-register';
|
||||||
|
|
||||||
export interface IBaseEvent {
|
export interface IBaseEvent {
|
||||||
type: string;
|
type: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user