1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-21 13:47:39 +02:00

fix: move toggle-counters to metrics service

This commit is contained in:
Ivar Conradi Østhus 2021-12-09 21:39:00 +01:00
parent 9f13b801eb
commit bb4e6290d5
4 changed files with 32 additions and 29 deletions

View File

@ -1,6 +1,5 @@
import { applicationSchema } from './metrics-schema'; import { applicationSchema } from './metrics-schema';
import { clientMetricsSchema } from './client-metrics-schema'; import { APPLICATION_CREATED } from '../../types/events';
import { APPLICATION_CREATED, CLIENT_METRICS } 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';
@ -17,8 +16,8 @@ import { IClientApp } from '../../types/model';
import { clientRegisterSchema } from './register-schema'; import { clientRegisterSchema } from './register-schema';
import { minutesToMilliseconds, secondsToMilliseconds } from 'date-fns'; import { minutesToMilliseconds, secondsToMilliseconds } from 'date-fns';
import EventEmitter from 'events';
import { IClientMetricsStoreV2 } from '../../types/stores/client-metrics-store-v2'; import { IClientMetricsStoreV2 } from '../../types/stores/client-metrics-store-v2';
import { clientMetricsSchema } from './client-metrics-schema';
export default class ClientInstanceService { export default class ClientInstanceService {
apps = {}; apps = {};
@ -45,8 +44,6 @@ export default class ClientInstanceService {
private announcementInterval: number; private announcementInterval: number;
private eventBus: EventEmitter;
constructor( constructor(
{ {
clientMetricsStoreV2, clientMetricsStoreV2,
@ -64,7 +61,7 @@ export default class ClientInstanceService {
| 'clientInstanceStore' | 'clientInstanceStore'
| 'eventStore' | 'eventStore'
>, >,
{ getLogger, eventBus }: Pick<IUnleashConfig, 'getLogger' | 'eventBus'>, { getLogger }: Pick<IUnleashConfig, 'getLogger'>,
bulkInterval = secondsToMilliseconds(5), bulkInterval = secondsToMilliseconds(5),
announcementInterval = minutesToMilliseconds(5), announcementInterval = minutesToMilliseconds(5),
) { ) {
@ -74,9 +71,10 @@ export default class ClientInstanceService {
this.clientApplicationsStore = clientApplicationsStore; this.clientApplicationsStore = clientApplicationsStore;
this.clientInstanceStore = clientInstanceStore; this.clientInstanceStore = clientInstanceStore;
this.eventStore = eventStore; this.eventStore = eventStore;
this.eventBus = eventBus;
this.logger = getLogger('/services/client-metrics/index.ts'); this.logger = getLogger(
'/services/client-metrics/client-instance-service.ts',
);
this.bulkInterval = bulkInterval; this.bulkInterval = bulkInterval;
this.announcementInterval = announcementInterval; this.announcementInterval = announcementInterval;
@ -96,20 +94,11 @@ export default class ClientInstanceService {
clientIp: string, clientIp: string,
): Promise<void> { ): Promise<void> {
const value = await clientMetricsSchema.validateAsync(data); const value = await clientMetricsSchema.validateAsync(data);
await this.clientInstanceStore.insert({ await this.clientInstanceStore.insert({
appName: value.appName, appName: value.appName,
instanceId: value.instanceId, instanceId: value.instanceId,
clientIp, clientIp,
}); });
// TODO: move to new service
const toggleNames = Object.keys(value.bucket.toggles);
if (toggleNames.length > 0) {
await this.featureToggleStore.setLastSeen(toggleNames);
}
this.eventBus.emit(CLIENT_METRICS, value);
} }
public async registerClient( public async registerClient(

View File

@ -9,24 +9,37 @@ import {
} from '../../types/stores/client-metrics-store-v2'; } from '../../types/stores/client-metrics-store-v2';
import { clientMetricsSchema } from './client-metrics-schema'; import { clientMetricsSchema } from './client-metrics-schema';
import { hoursToMilliseconds, minutesToMilliseconds } from 'date-fns'; import { hoursToMilliseconds, minutesToMilliseconds } from 'date-fns';
import { IFeatureToggleStore } from '../../types/stores/feature-toggle-store';
import EventEmitter from 'events';
import { CLIENT_METRICS } from '../../types/events';
export default class ClientMetricsServiceV2 { export default class ClientMetricsServiceV2 {
private timer: NodeJS.Timeout; private timer: NodeJS.Timeout;
private clientMetricsStoreV2: IClientMetricsStoreV2; private clientMetricsStoreV2: IClientMetricsStoreV2;
private featureToggleStore: IFeatureToggleStore;
private eventBus: EventEmitter;
private logger: Logger; private logger: Logger;
private bulkInterval: number; private bulkInterval: number;
constructor( constructor(
{ clientMetricsStoreV2 }: Pick<IUnleashStores, 'clientMetricsStoreV2'>, {
{ getLogger }: Pick<IUnleashConfig, 'getLogger'>, featureToggleStore,
clientMetricsStoreV2,
}: Pick<IUnleashStores, 'featureToggleStore' | 'clientMetricsStoreV2'>,
{ eventBus, getLogger }: Pick<IUnleashConfig, 'eventBus' | 'getLogger'>,
bulkInterval = minutesToMilliseconds(5), bulkInterval = minutesToMilliseconds(5),
) { ) {
this.featureToggleStore = featureToggleStore;
this.clientMetricsStoreV2 = clientMetricsStoreV2; this.clientMetricsStoreV2 = clientMetricsStoreV2;
this.eventBus = eventBus;
this.logger = getLogger('/services/client-metrics/index.ts'); this.logger = getLogger(
'/services/client-metrics/client-metrics-service-v2.ts',
);
this.bulkInterval = bulkInterval; this.bulkInterval = bulkInterval;
this.timer = setInterval(async () => { this.timer = setInterval(async () => {
@ -41,6 +54,9 @@ export default class ClientMetricsServiceV2 {
): Promise<void> { ): Promise<void> {
const value = await clientMetricsSchema.validateAsync(data); const value = await clientMetricsSchema.validateAsync(data);
const toggleNames = Object.keys(value.bucket.toggles); const toggleNames = Object.keys(value.bucket.toggles);
if (toggleNames.length > 0) {
await this.featureToggleStore.setLastSeen(toggleNames);
}
this.logger.debug(`got metrics from ${clientIp}`); this.logger.debug(`got metrics from ${clientIp}`);
@ -57,6 +73,7 @@ export default class ClientMetricsServiceV2 {
// TODO: should we aggregate for a few minutes (bulkInterval) before pushing to DB? // TODO: should we aggregate for a few minutes (bulkInterval) before pushing to DB?
await this.clientMetricsStoreV2.batchInsertMetrics(clientMetrics); await this.clientMetricsStoreV2.batchInsertMetrics(clientMetrics);
this.eventBus.emit(CLIENT_METRICS, value);
} }
// Overview over usage last "hour" bucket and all applications using the toggle // Overview over usage last "hour" bucket and all applications using the toggle

View File

@ -1,4 +1,3 @@
import EventEmitter from 'events';
import ClientInstanceService from './client-instance-service'; import ClientInstanceService from './client-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';
@ -57,7 +56,7 @@ test('Multiple registrations of same appname and instanceid within same time per
clientInstanceStore, clientInstanceStore,
eventStore: null, eventStore: null,
}, },
{ getLogger, eventBus: new EventEmitter() }, { getLogger },
); );
const client1: IClientApp = { const client1: IClientApp = {
appName: 'test_app', appName: 'test_app',
@ -107,7 +106,7 @@ test('Multiple unique clients causes multiple registrations', async () => {
clientInstanceStore, clientInstanceStore,
eventStore: null, eventStore: null,
}, },
{ getLogger, eventBus: new EventEmitter() }, { getLogger },
); );
const client1 = { const client1 = {
appName: 'test_app', appName: 'test_app',
@ -160,7 +159,7 @@ test('Same client registered outside of dedup interval will be registered twice'
clientInstanceStore, clientInstanceStore,
eventStore: null, eventStore: null,
}, },
{ getLogger, eventBus: new EventEmitter() }, { getLogger },
bulkInterval, bulkInterval,
); );
const client1 = { const client1 = {
@ -213,7 +212,7 @@ test('No registrations during a time period will not call stores', async () => {
clientInstanceStore, clientInstanceStore,
eventStore: null, eventStore: null,
}, },
{ getLogger, eventBus: new EventEmitter() }, { getLogger },
); );
jest.advanceTimersByTime(6000); jest.advanceTimersByTime(6000);
expect(appStoreSpy).toHaveBeenCalledTimes(0); expect(appStoreSpy).toHaveBeenCalledTimes(0);

View File

@ -1,7 +1,6 @@
import ClientInstanceService from '../../../lib/services/client-metrics/client-instance-service'; import ClientInstanceService from '../../../lib/services/client-metrics/client-instance-service';
import { IClientApp } from '../../../lib/types/model'; import { IClientApp } from '../../../lib/types/model';
import { secondsToMilliseconds } from 'date-fns'; import { secondsToMilliseconds } from 'date-fns';
import EventEmitter from 'events';
const faker = require('faker'); const faker = require('faker');
const dbInit = require('../helpers/database-init'); const dbInit = require('../helpers/database-init');
@ -15,14 +14,13 @@ let clientInstanceService;
beforeAll(async () => { beforeAll(async () => {
db = await dbInit('client_metrics_service_serial', getLogger); db = await dbInit('client_metrics_service_serial', getLogger);
stores = db.stores; stores = db.stores;
const eventBus = new EventEmitter();
const bulkInterval = secondsToMilliseconds(0.5); const bulkInterval = secondsToMilliseconds(0.5);
const announcementInterval = secondsToMilliseconds(2); const announcementInterval = secondsToMilliseconds(2);
clientInstanceService = new ClientInstanceService( clientInstanceService = new ClientInstanceService(
stores, stores,
{ getLogger, eventBus }, { getLogger },
bulkInterval, bulkInterval,
announcementInterval, announcementInterval,
); );