Skip to content

Commit

Permalink
chore: use memoized stats for version
Browse files Browse the repository at this point in the history
  • Loading branch information
gastonfournier committed Nov 15, 2024
1 parent da59e61 commit 36d1fad
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 31 deletions.
155 changes: 136 additions & 19 deletions src/lib/features/instance-stats/instance-stats-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
IClientMetricsStoreV2,
IEventStore,
IFeatureStrategiesReadModel,
IFeatureStrategiesStore,
ITrafficDataUsageStore,
IUnleashStores,
} from '../../types/stores';
Expand Down Expand Up @@ -33,6 +34,7 @@ import type { GetProductionChanges } from './getProductionChanges';
import { format, minutesToMilliseconds } from 'date-fns';
import memoizee from 'memoizee';
import type { GetLicensedUsers } from './getLicensedUsers';
import type { IFeatureUsageInfo } from '../../services/version-service';

export type TimeRange = 'allTime' | '30d' | '7d';

Expand Down Expand Up @@ -124,6 +126,8 @@ export class InstanceStatsService {

private featureStrategiesReadModel: IFeatureStrategiesReadModel;

private featureStrategiesStore: IFeatureStrategiesStore;

private trafficDataUsageStore: ITrafficDataUsageStore;

constructor(
Expand Down Expand Up @@ -186,9 +190,15 @@ export class InstanceStatsService {
this.eventStore = eventStore;
this.clientInstanceStore = clientInstanceStore;
this.logger = getLogger('services/stats-service.js');
this.getActiveUsers = getActiveUsers;
this.getLicencedUsers = getLicencedUsers;
this.getProductionChanges = getProductionChanges;
this.getActiveUsers = () =>
this.memorize('getActiveUsers', getActiveUsers.bind(this));
this.getLicencedUsers = () =>
this.memorize('getLicencedUsers', getLicencedUsers.bind(this));
this.getProductionChanges = () =>
this.memorize(
'getProductionChanges',
getProductionChanges.bind(this),
);
this.apiTokenStore = apiTokenStore;
this.clientMetricsStore = clientMetricsStoreV2;
this.flagResolver = flagResolver;
Expand Down Expand Up @@ -324,8 +334,8 @@ export class InstanceStatsService {
this.getRegisteredUsers(),
this.countServiceAccounts(),
this.countApiTokensByType(),
this.memorize('getActiveUsers', this.getActiveUsers.bind(this)),
this.memorize('getLicencedUsers', this.getLicencedUsers.bind(this)),
this.getActiveUsers(),
this.getLicencedUsers(),
this.getProjectModeCount(),
this.contextFieldCount(),
this.groupCount(),
Expand All @@ -340,20 +350,9 @@ export class InstanceStatsService {
this.hasPasswordAuth(),
this.hasSCIM(),
this.appCount ? this.appCount : this.getLabeledAppCounts(),
this.memorize('deprecatedFilteredCountFeaturesExported', () =>
this.eventStore.deprecatedFilteredCount({
type: FEATURES_EXPORTED,
}),
),
this.memorize('deprecatedFilteredCountFeaturesImported', () =>
this.eventStore.deprecatedFilteredCount({
type: FEATURES_IMPORTED,
}),
),
this.memorize(
'getProductionChanges',
this.getProductionChanges.bind(this),
),
this.featuresExported(),
this.featuresImported(),
this.getProductionChanges(),
this.countPreviousDayHourlyMetricsBuckets(),
this.memorize(
'maxFeatureEnvironmentStrategies',
Expand Down Expand Up @@ -414,6 +413,124 @@ export class InstanceStatsService {
};
}

async getFeatureUsageInfo(): Promise<IFeatureUsageInfo> {
const [
featureToggles,
users,
projectModeCount,
contextFields,
groups,
roles,
customRootRoles,
customRootRolesInUse,
environments,
segments,
strategies,
SAMLenabled,
OIDCenabled,
featureExports,
featureImports,
customStrategies,
customStrategiesInUse,
userActive,
productionChanges,
postgresVersion,
] = await Promise.all([
this.getToggleCount(),
this.getRegisteredUsers(),
this.getProjectModeCount(),
this.contextFieldCount(),
this.groupCount(),
this.roleCount(),
this.customRolesCount(),
this.customRolesCountInUse(),
this.environmentCount(),
this.segmentCount(),
this.strategiesCount(),
this.hasSAML(),
this.hasOIDC(),
this.featuresExported(),
this.featuresImported(),
this.customStrategiesCount(),
this.customStrategiesInUseCount(),
this.getActiveUsers(),
this.getProductionChanges(),
this.postgresVersion(),
]);
const versionInfo = await this.versionService.getVersionInfo();

const featureInfo = {
featureToggles,
users,
projects: projectModeCount
.map((p) => p.count)
.reduce((a, b) => a + b, 0),
contextFields,
groups,
roles,
customRootRoles,
customRootRolesInUse,
environments,
segments,
strategies,
SAMLenabled,
OIDCenabled,
featureExports,
featureImports,
customStrategies,
customStrategiesInUse,
instanceId: versionInfo.instanceId,
versionOSS: versionInfo.current.oss,
versionEnterprise: versionInfo.current.enterprise,
activeUsers30: userActive.last30,
activeUsers60: userActive.last60,
activeUsers90: userActive.last90,
productionChanges30: productionChanges.last30,
productionChanges60: productionChanges.last60,
productionChanges90: productionChanges.last90,
postgresVersion,
};
return featureInfo;
}

featuresExported(): Promise<number> {
return this.memorize('deprecatedFilteredCountFeaturesExported', () =>
this.eventStore.deprecatedFilteredCount({
type: FEATURES_EXPORTED,
}),
);
}

featuresImported(): Promise<number> {
return this.memorize('deprecatedFilteredCountFeaturesImported', () =>
this.eventStore.deprecatedFilteredCount({
type: FEATURES_IMPORTED,
}),
);
}

customStrategiesCount(): Promise<number> {
return this.memorize(
'customStrategiesCount',
async () =>
(await this.strategyStore.getEditableStrategies()).length,
);
}

customStrategiesInUseCount(): Promise<number> {
return this.memorize(
'customStrategiesInUseCount',
async () =>
await this.featureStrategiesStore.getCustomStrategiesInUseCount(),
);
}

postgresVersion(): Promise<string> {
return this.memorize('postgresVersion', () =>
this.settingStore.postgresVersion(),
);
}

groupCount(): Promise<number> {
return this.memorize('groupCount', () => this.groupStore.count());
}
Expand Down
9 changes: 8 additions & 1 deletion src/lib/features/scheduler/schedule-services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,14 @@ export const scheduleServices = async (
);

schedulerService.schedule(
versionService.checkLatestVersion.bind(versionService),
() =>
versionService.checkLatestVersion(() =>
config.flagResolver.isEnabled('memorizeStats', {
memoryKey: 'getFeatureUsageInfo',
})
? instanceStatsService.getFeatureUsageInfo()
: versionService.getFeatureUsageInfo(),
),
hoursToMilliseconds(48),
'checkLatestVersion',
);
Expand Down
16 changes: 8 additions & 8 deletions src/lib/services/version-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ test('yields current versions', async () => {
createFakeGetActiveUsers(),
createFakeGetProductionChanges(),
);
await service.checkLatestVersion();
await service.checkLatestVersion(() => service.getFeatureUsageInfo());
const versionInfo = await service.getVersionInfo();
expect(scope.isDone()).toEqual(true);
expect(versionInfo.current.oss).toBe(version);
Expand Down Expand Up @@ -82,7 +82,7 @@ test('supports setting enterprise version as well', async () => {
createFakeGetActiveUsers(),
createFakeGetProductionChanges(),
);
await service.checkLatestVersion();
await service.checkLatestVersion(() => service.getFeatureUsageInfo());
const versionInfo = await service.getVersionInfo();
expect(scope.isDone()).toEqual(true);
expect(versionInfo.current.oss).toBe(version);
Expand Down Expand Up @@ -121,7 +121,7 @@ test('if version check is not enabled should not make any calls', async () => {
createFakeGetActiveUsers(),
createFakeGetProductionChanges(),
);
await service.checkLatestVersion();
await service.checkLatestVersion(() => service.getFeatureUsageInfo());
const versionInfo = await service.getVersionInfo();
expect(scope.isDone()).toEqual(false);
expect(versionInfo.current.oss).toBe(version);
Expand Down Expand Up @@ -168,7 +168,7 @@ test('sets featureinfo', async () => {
createFakeGetActiveUsers(),
createFakeGetProductionChanges(),
);
await service.checkLatestVersion();
await service.checkLatestVersion(() => service.getFeatureUsageInfo());
expect(scope.isDone()).toEqual(true);
nock.cleanAll();
});
Expand Down Expand Up @@ -225,7 +225,7 @@ test('counts toggles', async () => {
createFakeGetActiveUsers(),
createFakeGetProductionChanges(),
);
await service.checkLatestVersion();
await service.checkLatestVersion(() => service.getFeatureUsageInfo());
expect(scope.isDone()).toEqual(true);
nock.cleanAll();
});
Expand Down Expand Up @@ -297,7 +297,7 @@ test('counts custom strategies', async () => {
createFakeGetActiveUsers(),
createFakeGetProductionChanges(),
);
await service.checkLatestVersion();
await service.checkLatestVersion(() => service.getFeatureUsageInfo());
expect(scope.isDone()).toEqual(true);
nock.cleanAll();
});
Expand Down Expand Up @@ -346,7 +346,7 @@ test('counts active users', async () => {
fakeActiveUsers,
fakeProductionChanges,
);
await service.checkLatestVersion();
await service.checkLatestVersion(() => service.getFeatureUsageInfo());
expect(scope.isDone()).toEqual(true);
nock.cleanAll();
});
Expand Down Expand Up @@ -393,7 +393,7 @@ test('Counts production changes', async () => {
fakeActiveUsers,
fakeProductionChanges,
);
await service.checkLatestVersion();
await service.checkLatestVersion(() => service.getFeatureUsageInfo());
expect(scope.isDone()).toEqual(true);
nock.cleanAll();
});
8 changes: 5 additions & 3 deletions src/lib/services/version-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ export default class VersionService {
return this.instanceId;
}

async checkLatestVersion(): Promise<void> {
async checkLatestVersion(
telemetryDataProvider: () => Promise<IFeatureUsageInfo>,
): Promise<void> {
const instanceId = await this.getInstanceId();
this.logger.debug(
`Checking for newest version for instanceId=${instanceId}`,
Expand All @@ -212,8 +214,7 @@ export default class VersionService {
};

if (this.telemetryEnabled) {
versionPayload.featureInfo =
await this.getFeatureUsageInfo();
versionPayload.featureInfo = await telemetryDataProvider();
}
if (this.versionCheckUrl) {
const res = await fetch(this.versionCheckUrl, {
Expand Down Expand Up @@ -242,6 +243,7 @@ export default class VersionService {
}
}

/** @deprecated look into stats service getFeatureUsageInfo */
async getFeatureUsageInfo(): Promise<IFeatureUsageInfo> {
const [
featureToggles,
Expand Down

0 comments on commit 36d1fad

Please sign in to comment.