1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

feat: Prometheus last day metrics (#5878)

This commit is contained in:
Mateusz Kwasniewski 2024-01-15 15:31:38 +01:00 committed by GitHub
parent 6cfb7b4fb8
commit 65eb8956e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 61 additions and 6 deletions

View File

@ -216,7 +216,7 @@ test('count previous day metrics', async () => {
}, },
]); ]);
const result = await clientMetricsStore.countPreviousDayMetrics(); const result = await clientMetricsStore.countPreviousDayMetricsBuckets();
expect(result).toMatchObject({ enabledCount: 2, variantCount: 4 }); expect(result).toMatchObject({ enabledCount: 2, variantCount: 4 });
}); });

View File

@ -339,7 +339,7 @@ export class ClientMetricsStoreV2 implements IClientMetricsStoreV2 {
.del(); .del();
} }
async countPreviousDayMetrics(): Promise<{ async countPreviousDayMetricsBuckets(): Promise<{
enabledCount: number; enabledCount: number;
variantCount: number; variantCount: number;
}> { }> {

View File

@ -3,6 +3,7 @@ import { Logger } from '../../logger';
import { IUnleashConfig } from '../../types/option'; import { IUnleashConfig } from '../../types/option';
import { import {
IClientInstanceStore, IClientInstanceStore,
IClientMetricsStoreV2,
IEventStore, IEventStore,
IUnleashStores, IUnleashStores,
} from '../../types/stores'; } from '../../types/stores';
@ -54,6 +55,10 @@ export interface InstanceStats {
clientApps: { range: TimeRange; count: number }[]; clientApps: { range: TimeRange; count: number }[];
activeUsers: Awaited<ReturnType<GetActiveUsers>>; activeUsers: Awaited<ReturnType<GetActiveUsers>>;
productionChanges: Awaited<ReturnType<GetProductionChanges>>; productionChanges: Awaited<ReturnType<GetProductionChanges>>;
previousDayMetricsBucketsCount: {
enabledCount: number;
variantCount: number;
};
} }
export type InstanceStatsSigned = Omit<InstanceStats, 'projects'> & { export type InstanceStatsSigned = Omit<InstanceStats, 'projects'> & {
@ -92,6 +97,8 @@ export class InstanceStatsService {
private clientInstanceStore: IClientInstanceStore; private clientInstanceStore: IClientInstanceStore;
private clientMetricsStore: IClientMetricsStoreV2;
private snapshot?: InstanceStats; private snapshot?: InstanceStats;
private appCount?: Partial<{ [key in TimeRange]: number }>; private appCount?: Partial<{ [key in TimeRange]: number }>;
@ -115,6 +122,7 @@ export class InstanceStatsService {
clientInstanceStore, clientInstanceStore,
eventStore, eventStore,
apiTokenStore, apiTokenStore,
clientMetricsStoreV2,
}: Pick< }: Pick<
IUnleashStores, IUnleashStores,
| 'featureToggleStore' | 'featureToggleStore'
@ -130,6 +138,7 @@ export class InstanceStatsService {
| 'clientInstanceStore' | 'clientInstanceStore'
| 'eventStore' | 'eventStore'
| 'apiTokenStore' | 'apiTokenStore'
| 'clientMetricsStoreV2'
>, >,
{ getLogger }: Pick<IUnleashConfig, 'getLogger'>, { getLogger }: Pick<IUnleashConfig, 'getLogger'>,
versionService: VersionService, versionService: VersionService,
@ -153,6 +162,7 @@ export class InstanceStatsService {
this.getActiveUsers = getActiveUsers; this.getActiveUsers = getActiveUsers;
this.getProductionChanges = getProductionChanges; this.getProductionChanges = getProductionChanges;
this.apiTokenStore = apiTokenStore; this.apiTokenStore = apiTokenStore;
this.clientMetricsStore = clientMetricsStoreV2;
} }
async refreshStatsSnapshot(): Promise<void> { async refreshStatsSnapshot(): Promise<void> {
@ -223,6 +233,7 @@ export class InstanceStatsService {
featureExports, featureExports,
featureImports, featureImports,
productionChanges, productionChanges,
previousDayMetricsBucketsCount,
] = await Promise.all([ ] = await Promise.all([
this.getToggleCount(), this.getToggleCount(),
this.userStore.count(), this.userStore.count(),
@ -244,6 +255,7 @@ export class InstanceStatsService {
this.eventStore.filteredCount({ type: FEATURES_EXPORTED }), this.eventStore.filteredCount({ type: FEATURES_EXPORTED }),
this.eventStore.filteredCount({ type: FEATURES_IMPORTED }), this.eventStore.filteredCount({ type: FEATURES_IMPORTED }),
this.getProductionChanges(), this.getProductionChanges(),
this.clientMetricsStore.countPreviousDayMetricsBuckets(),
]); ]);
return { return {
@ -271,6 +283,7 @@ export class InstanceStatsService {
featureExports, featureExports,
featureImports, featureImports,
productionChanges, productionChanges,
previousDayMetricsBucketsCount,
}; };
} }

View File

@ -112,6 +112,14 @@ export default class MetricsMonitor {
help: 'Number of API tokens', help: 'Number of API tokens',
labelNames: ['type'], labelNames: ['type'],
}); });
const enabledMetricsBucketsPreviousDay = new client.Gauge({
name: 'enabled_metrics_buckets_previous_day',
help: 'Number of hourly enabled/disabled metric buckets in the previous day',
});
const variantMetricsBucketsPreviousDay = new client.Gauge({
name: 'variant_metrics_buckets_previous_day',
help: 'Number of hourly variant metric buckets in the previous day',
});
const usersActive7days = new client.Gauge({ const usersActive7days = new client.Gauge({
name: 'users_active_7', name: 'users_active_7',
help: 'Number of users active in the last 7 days', help: 'Number of users active in the last 7 days',
@ -235,6 +243,15 @@ export default class MetricsMonitor {
apiTokens.labels(type).set(value); apiTokens.labels(type).set(value);
} }
enabledMetricsBucketsPreviousDay.reset();
enabledMetricsBucketsPreviousDay.set(
stats.previousDayMetricsBucketsCount.enabledCount,
);
variantMetricsBucketsPreviousDay.reset();
variantMetricsBucketsPreviousDay.set(
stats.previousDayMetricsBucketsCount.variantCount,
);
usersActive7days.reset(); usersActive7days.reset();
usersActive7days.set(stats.activeUsers.last7); usersActive7days.set(stats.activeUsers.last7);
usersActive30days.reset(); usersActive30days.reset();

View File

@ -39,6 +39,27 @@ export const instanceAdminStatsSchema = {
example: 8, example: 8,
minimum: 0, minimum: 0,
}, },
previousDayMetricsBucketsCount: {
type: 'object',
description:
'The number client metrics buckets records recorded in the previous day. # features * # apps * # envs * # hours with metrics',
properties: {
enabledCount: {
type: 'number',
description:
'The number of enabled/disabled metrics buckets recorded in the previous day',
example: 10,
minimum: 0,
},
variantCount: {
type: 'number',
description:
'The number of variant metrics buckets recorded in the previous day',
example: 10,
minimum: 0,
},
},
},
activeUsers: { activeUsers: {
type: 'object', type: 'object',
description: description:

View File

@ -120,6 +120,10 @@ class InstanceAdminController extends Controller {
last60: 200, last60: 200,
last90: 200, last90: 200,
}, },
previousDayMetricsBucketsCount: {
variantCount: 100,
enabledCount: 200,
},
}; };
} }

View File

@ -246,7 +246,7 @@ test('aggregate previous day metrics when metrics count is below limit', async (
aggregationCalled = true; aggregationCalled = true;
return Promise.resolve(); return Promise.resolve();
}, },
countPreviousDayMetrics() { countPreviousDayMetricsBuckets() {
return { enabledCount, variantCount }; return { enabledCount, variantCount };
}, },
} as unknown as IClientMetricsStoreV2; } as unknown as IClientMetricsStoreV2;

View File

@ -62,7 +62,7 @@ export default class ClientMetricsServiceV2 {
async aggregateDailyMetrics() { async aggregateDailyMetrics() {
if (this.flagResolver.isEnabled('extendedUsageMetrics')) { if (this.flagResolver.isEnabled('extendedUsageMetrics')) {
const { enabledCount, variantCount } = const { enabledCount, variantCount } =
await this.clientMetricsStoreV2.countPreviousDayMetrics(); await this.clientMetricsStoreV2.countPreviousDayMetricsBuckets();
const { payload } = this.flagResolver.getVariant( const { payload } = this.flagResolver.getVariant(
'extendedUsageMetrics', 'extendedUsageMetrics',
); );

View File

@ -39,7 +39,7 @@ export interface IClientMetricsStoreV2
): Promise<string[]>; ): Promise<string[]>;
clearMetrics(hoursAgo: number): Promise<void>; clearMetrics(hoursAgo: number): Promise<void>;
clearDailyMetrics(daysAgo: number): Promise<void>; clearDailyMetrics(daysAgo: number): Promise<void>;
countPreviousDayMetrics(): Promise<{ countPreviousDayMetricsBuckets(): Promise<{
enabledCount: number; enabledCount: number;
variantCount: number; variantCount: number;
}>; }>;

View File

@ -29,7 +29,7 @@ export default class FakeClientMetricsStoreV2
clearDailyMetrics(daysBack: number): Promise<void> { clearDailyMetrics(daysBack: number): Promise<void> {
return Promise.resolve(); return Promise.resolve();
} }
countPreviousDayMetrics(): Promise<{ countPreviousDayMetricsBuckets(): Promise<{
enabledCount: number; enabledCount: number;
variantCount: number; variantCount: number;
}> { }> {