1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-03-27 00:19:39 +01:00
unleash.unleash/src/lib/routes/admin-api/instance-admin.ts
Thomas Heartman b0541a0af2
feat: add remaining resource usage to instance stats ()
Updates the instance stats endpoint with 
- maxEnvironmentStrategies
- maxConstraints
- maxConstraintValues

It adds the following rows to the front end table:
- segments (already in the payload, just not used for the table before)
- API tokens (separate rows for type, + one for total) (also existed
before, but wasn't listed)
- Highest number of strategies used for a single flag in a single
environment
- Highest number of constraints used on a single strategy
- Highest number of values used for a single constraint


![image](https://github.com/user-attachments/assets/57798f8e-c466-4590-820b-15afd3729243)
2024-08-22 13:09:26 +02:00

174 lines
5.9 KiB
TypeScript

import { Parser } from 'json2csv';
import type { Response } from 'express';
import type { AuthedRequest } from '../../types/core';
import type { IUnleashServices } from '../../types/services';
import type { IUnleashConfig } from '../../types/option';
import Controller from '../controller';
import { NONE } from '../../types/permissions';
import type {
InstanceStatsService,
InstanceStatsSigned,
} from '../../features/instance-stats/instance-stats-service';
import type { OpenApiService } from '../../services/openapi-service';
import {
createCsvResponseSchema,
createResponseSchema,
} from '../../openapi/util/create-response-schema';
import type { InstanceAdminStatsSchema } from '../../openapi';
import { serializeDates } from '../../types';
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,
archivedFeatureToggles: 10,
groups: 3,
instanceId: 'ed3861ae-78f9-4e8c-8e57-b57efc15f82b',
projects: 4,
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,
serviceAccounts: 2,
apiTokens: new Map([]),
versionEnterprise: '5.1.7',
versionOSS: '5.1.7',
activeUsers: {
last90: 15,
last60: 12,
last30: 10,
last7: 5,
},
productionChanges: {
last30: 100,
last60: 200,
last90: 200,
},
previousDayMetricsBucketsCount: {
variantCount: 100,
enabledCount: 200,
},
maxEnvironmentStrategies: 20,
maxConstraints: 17,
maxConstraintValues: 123,
};
}
private serializeStats(
instanceStats: InstanceStatsSigned,
): InstanceAdminStatsSchema {
const apiTokensObj = Object.fromEntries(
instanceStats.apiTokens.entries(),
);
return serializeDates({
...instanceStats,
apiTokens: apiTokensObj,
});
}
async getStatistics(
_: AuthedRequest,
res: Response<InstanceAdminStatsSchema>,
): Promise<void> {
const instanceStats = await this.instanceStatsService.getSignedStats();
res.json(this.serializeStats(instanceStats));
}
async getStatisticsCSV(
_: AuthedRequest,
res: Response<InstanceAdminStatsSchema>,
): Promise<void> {
const instanceStats = await this.instanceStatsService.getSignedStats();
const fileName = `unleash-${
instanceStats.instanceId
}-${Date.now()}.csv`;
const json2csvParser = new Parser();
const csv = json2csvParser.parse(this.serializeStats(instanceStats));
res.contentType('csv');
res.attachment(fileName);
res.send(csv);
}
}
export default InstanceAdminController;