Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add remaining resource usage to instance stats #7958

Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import {
TableRow,
} from '@mui/material';
import { Box } from '@mui/system';
import type { VFC } from 'react';
import type { FC } from 'react';
import { useInstanceStats } from 'hooks/api/getters/useInstanceStats/useInstanceStats';
import { formatApiPath } from '../../../../utils/formatPath';
import { PageContent } from '../../../common/PageContent/PageContent';
import { PageHeader } from '../../../common/PageHeader/PageHeader';

export const InstanceStats: VFC = () => {
export const InstanceStats: FC = () => {
const { stats } = useInstanceStats();

let versionTitle: string;
Expand All @@ -28,6 +28,11 @@ export const InstanceStats: VFC = () => {
version = stats?.versionOSS;
}

const apiTokensTotal = Object.values(stats?.apiTokens ?? {}).reduce(
(acc, val) => acc + val,
0,
);

const rows = [
{ title: 'Instance Id', value: stats?.instanceId, offset: false },
{ title: versionTitle, value: version },
Expand All @@ -41,6 +46,23 @@ export const InstanceStats: VFC = () => {
{ title: 'Strategies', value: stats?.strategies },
{ title: 'Feature exports', value: stats?.featureExports },
{ title: 'Feature imports', value: stats?.featureImports },
{ title: 'Admin API tokens', value: stats?.apiTokens?.admin },
{ title: 'Client API tokens', value: stats?.apiTokens?.client },
{ title: 'Frontend API tokens', value: stats?.apiTokens?.frontend },
{ title: 'API tokens total', value: apiTokensTotal },
{ title: 'Segments', value: stats?.segments },
{
title: 'Highest number of strategies used for a single flag in a single environment',
value: stats?.maxEnvironmentStrategies,
},
{
title: 'Highest number of constraints used on a single strategy',
value: stats?.maxConstraints,
},
{
title: 'Highest number of values used for a single constraint',
value: stats?.maxConstraintValues,
},
];

if (stats?.versionEnterprise) {
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/openapi/models/instanceAdminStatsSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,20 @@ export interface InstanceAdminStatsSchema {
versionEnterprise?: string;
/** The version of Unleash OSS that is bundled in this instance */
versionOSS?: string;

/** A breakdown of API tokens that exist in this instance */
apiTokens: {
client: number;
admin: number;
frontend: number;
};

// The highest number of strategies used on a single feature flag in a single environment.
maxEnvironmentStrategies: number;

// The highest number of constraints used on a single strategy.
maxConstraints: number;

// The highest number of constraint values used on a single constraint.
maxConstraintValues: number;
}
7 changes: 7 additions & 0 deletions src/lib/features/instance-stats/createInstanceStatsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import FakeSettingStore from '../../../test/fixtures/fake-setting-store';
import FakeSegmentStore from '../../../test/fixtures/fake-segment-store';
import FakeStrategiesStore from '../../../test/fixtures/fake-strategies-store';
import FakeFeatureStrategiesStore from '../feature-toggle/fakes/fake-feature-strategies-store';
import { FeatureStrategiesReadModel } from '../feature-toggle/feature-strategies-read-model';
import { FakeFeatureStrategiesReadModel } from '../feature-toggle/fake-feature-strategies-read-model';

export const createInstanceStatsService = (db: Db, config: IUnleashConfig) => {
const { eventBus, getLogger, flagResolver } = config;
Expand Down Expand Up @@ -89,6 +91,8 @@ export const createInstanceStatsService = (db: Db, config: IUnleashConfig) => {
getLogger,
flagResolver,
);

const featureStrategiesReadModel = new FeatureStrategiesReadModel(db);
const instanceStatsServiceStores = {
featureToggleStore,
userStore,
Expand All @@ -104,6 +108,7 @@ export const createInstanceStatsService = (db: Db, config: IUnleashConfig) => {
eventStore,
apiTokenStore,
clientMetricsStoreV2,
featureStrategiesReadModel,
};
const featureStrategiesStore = new FeatureStrategyStore(
db,
Expand Down Expand Up @@ -151,6 +156,7 @@ export const createFakeInstanceStatsService = (config: IUnleashConfig) => {
const eventStore = new FakeEventStore();
const apiTokenStore = new FakeApiTokenStore();
const clientMetricsStoreV2 = new FakeClientMetricsStoreV2();
const featureStrategiesReadModel = new FakeFeatureStrategiesReadModel();

const instanceStatsServiceStores = {
featureToggleStore,
Expand All @@ -167,6 +173,7 @@ export const createFakeInstanceStatsService = (config: IUnleashConfig) => {
eventStore,
apiTokenStore,
clientMetricsStoreV2,
featureStrategiesReadModel,
};
const featureStrategiesStore = new FakeFeatureStrategiesStore();
const versionServiceStores = {
Expand Down
18 changes: 18 additions & 0 deletions src/lib/features/instance-stats/instance-stats-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
IClientInstanceStore,
IClientMetricsStoreV2,
IEventStore,
IFeatureStrategiesReadModel,
IUnleashStores,
} from '../../types/stores';
import type { IContextFieldStore } from '../../types/stores/context-field-store';
Expand Down Expand Up @@ -61,6 +62,9 @@ export interface InstanceStats {
enabledCount: number;
variantCount: number;
};
maxEnvironmentStrategies: number;
maxConstraints: number;
maxConstraintValues: number;
}

export type InstanceStatsSigned = Omit<InstanceStats, 'projects'> & {
Expand Down Expand Up @@ -109,6 +113,8 @@ export class InstanceStatsService {

private getProductionChanges: GetProductionChanges;

private featureStrategiesReadModel: IFeatureStrategiesReadModel;

constructor(
{
featureToggleStore,
Expand All @@ -125,6 +131,7 @@ export class InstanceStatsService {
eventStore,
apiTokenStore,
clientMetricsStoreV2,
featureStrategiesReadModel,
}: Pick<
IUnleashStores,
| 'featureToggleStore'
Expand All @@ -141,6 +148,7 @@ export class InstanceStatsService {
| 'eventStore'
| 'apiTokenStore'
| 'clientMetricsStoreV2'
| 'featureStrategiesReadModel'
>,
{
getLogger,
Expand Down Expand Up @@ -169,6 +177,7 @@ export class InstanceStatsService {
this.apiTokenStore = apiTokenStore;
this.clientMetricsStore = clientMetricsStoreV2;
this.flagResolver = flagResolver;
this.featureStrategiesReadModel = featureStrategiesReadModel;
}

async refreshAppCountSnapshot(): Promise<
Expand Down Expand Up @@ -250,6 +259,9 @@ export class InstanceStatsService {
featureImports,
productionChanges,
previousDayMetricsBucketsCount,
maxEnvironmentStrategies,
maxConstraintValues,
maxConstraints,
] = await Promise.all([
this.getToggleCount(),
this.getArchivedToggleCount(),
Expand Down Expand Up @@ -277,6 +289,9 @@ export class InstanceStatsService {
}),
this.getProductionChanges(),
this.clientMetricsStore.countPreviousDayHourlyMetricsBuckets(),
this.featureStrategiesReadModel.getMaxFeatureEnvironmentStrategies(),
this.featureStrategiesReadModel.getMaxConstraintValues(),
this.featureStrategiesReadModel.getMaxConstraintsPerStrategy(),
]);

return {
Expand Down Expand Up @@ -309,6 +324,9 @@ export class InstanceStatsService {
featureImports,
productionChanges,
previousDayMetricsBucketsCount,
maxEnvironmentStrategies: maxEnvironmentStrategies?.count ?? 0,
maxConstraintValues: maxConstraintValues?.count ?? 0,
maxConstraints: maxConstraints?.count ?? 0,
};
}

Expand Down
Loading
Loading