mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-04 01:18:20 +02:00
## About the changes - `getActiveUsers` is using multiple stores, so it is refactored into read-model - Refactored Instance stats service into `features` to co-locate related code Closes https://linear.app/unleash/issue/UNL-230/active-users-prometheus ### Important files `src/lib/features/instance-stats/getActiveUsers.ts` ## Discussion points `getActiveUsers` is coded less _class-based_ then previous similar read-models. In one file instead of 3 (read-model interface, fake read model, sql read model). I find types and functions way more readable, but I'm ready to refactor it to interfaces and classes if consistency is more important.
147 lines
5.0 KiB
TypeScript
147 lines
5.0 KiB
TypeScript
import { Parser } from 'json2csv';
|
|
import { Response } from 'express';
|
|
import { AuthedRequest } from '../../types/core';
|
|
import { IUnleashServices } from '../../types/services';
|
|
import { IUnleashConfig } from '../../types/option';
|
|
import Controller from '../controller';
|
|
import { NONE } from '../../types/permissions';
|
|
import { UiConfigSchema } from '../../openapi/spec/ui-config-schema';
|
|
import {
|
|
InstanceStats,
|
|
InstanceStatsService,
|
|
InstanceStatsSigned,
|
|
} from '../../features/instance-stats/instance-stats-service';
|
|
import { OpenApiService } from '../../services/openapi-service';
|
|
import {
|
|
createCsvResponseSchema,
|
|
createResponseSchema,
|
|
} from '../../openapi/util/create-response-schema';
|
|
|
|
class InstanceAdminController extends Controller {
|
|
private instanceStatsService: InstanceStatsService;
|
|
|
|
private openApiService: OpenApiService;
|
|
|
|
private jsonCsvParser: Parser;
|
|
|
|
constructor(
|
|
config: IUnleashConfig,
|
|
{
|
|
instanceStatsService,
|
|
openApiService,
|
|
}: Pick<IUnleashServices, 'instanceStatsService' | 'openApiService'>,
|
|
) {
|
|
super(config);
|
|
this.jsonCsvParser = new Parser();
|
|
this.openApiService = openApiService;
|
|
this.instanceStatsService = instanceStatsService;
|
|
|
|
this.route({
|
|
method: 'get',
|
|
path: '/statistics/csv',
|
|
handler: this.getStatisticsCSV,
|
|
permission: NONE,
|
|
middleware: [
|
|
openApiService.validPath({
|
|
tags: ['Instance Admin'],
|
|
summary: 'Instance usage statistics',
|
|
description:
|
|
'Provides statistics about various features of Unleash to allow for reporting of usage for self-hosted customers. The response contains data such as the number of users, groups, features, strategies, versions, etc.',
|
|
operationId: 'getInstanceAdminStatsCsv',
|
|
responses: {
|
|
200: createCsvResponseSchema(
|
|
'instanceAdminStatsSchemaCsv',
|
|
this.jsonCsvParser.parse(
|
|
this.instanceStatsExample(),
|
|
),
|
|
),
|
|
},
|
|
}),
|
|
],
|
|
});
|
|
|
|
this.route({
|
|
method: 'get',
|
|
path: '/statistics',
|
|
handler: this.getStatistics,
|
|
permission: NONE,
|
|
middleware: [
|
|
openApiService.validPath({
|
|
tags: ['Instance Admin'],
|
|
operationId: 'getInstanceAdminStats',
|
|
summary: 'Instance usage statistics',
|
|
description:
|
|
'Provides statistics about various features of Unleash to allow for reporting of usage for self-hosted customers. The response contains data such as the number of users, groups, features, strategies, versions, etc.',
|
|
responses: {
|
|
200: createResponseSchema('instanceAdminStatsSchema'),
|
|
},
|
|
deprecated: true,
|
|
}),
|
|
],
|
|
});
|
|
}
|
|
|
|
instanceStatsExample(): InstanceStatsSigned {
|
|
return {
|
|
OIDCenabled: true,
|
|
SAMLenabled: false,
|
|
clientApps: [
|
|
{ range: 'allTime', count: 15 },
|
|
{ range: '30d', count: 9 },
|
|
{ range: '7d', count: 5 },
|
|
],
|
|
contextFields: 6,
|
|
environments: 2,
|
|
featureExports: 0,
|
|
featureImports: 0,
|
|
featureToggles: 29,
|
|
groups: 3,
|
|
instanceId: 'ed3861ae-78f9-4e8c-8e57-b57efc15f82b',
|
|
projects: 1,
|
|
roles: 5,
|
|
customRootRoles: 2,
|
|
customRootRolesInUse: 1,
|
|
segments: 2,
|
|
strategies: 8,
|
|
sum: 'some-sha256-hash',
|
|
timestamp: new Date(2023, 6, 12, 10, 0, 0, 0),
|
|
users: 10,
|
|
versionEnterprise: '5.1.7',
|
|
versionOSS: '5.1.7',
|
|
activeUsers: {
|
|
last90: 15,
|
|
last60: 12,
|
|
last30: 10,
|
|
last7: 5,
|
|
},
|
|
};
|
|
}
|
|
|
|
async getStatistics(
|
|
req: AuthedRequest,
|
|
res: Response<InstanceStats>,
|
|
): Promise<void> {
|
|
const instanceStats = await this.instanceStatsService.getSignedStats();
|
|
res.json(instanceStats);
|
|
}
|
|
|
|
async getStatisticsCSV(
|
|
req: AuthedRequest,
|
|
res: Response<UiConfigSchema>,
|
|
): Promise<void> {
|
|
const instanceStats = await this.instanceStatsService.getSignedStats();
|
|
const fileName = `unleash-${
|
|
instanceStats.instanceId
|
|
}-${Date.now()}.csv`;
|
|
|
|
const json2csvParser = new Parser();
|
|
const csv = json2csvParser.parse(instanceStats);
|
|
|
|
res.contentType('csv');
|
|
res.attachment(fileName);
|
|
res.send(csv);
|
|
}
|
|
}
|
|
|
|
export default InstanceAdminController;
|