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:
parent
9f13b801eb
commit
bb4e6290d5
@ -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(
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user