1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-10-04 11:17:02 +02:00
unleash.unleash/src/lib/features/metrics/unknown-flags/unknown-flags-service.ts
Nuno Góis 3b6613360c
chore: unknown flags UI (#10332)
https://linear.app/unleash/issue/2-3682/add-unknown-flags-page-with-table-and-description

Adds a `/unknown-flags` page with a table of unknown flag reports and a
short description of what this is.

It’s only accessible via direct URL for now (if the flag is enabled),
but it allows us to share the list with some customers.

<img width="1026" alt="image"
src="https://github.com/user-attachments/assets/feee88bb-bbce-4871-98d7-f76f95076ee2"
/>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-08 17:51:03 +01:00

63 lines
2.0 KiB
TypeScript

import type { Logger } from '../../../logger.js';
import type {
IFlagResolver,
IUnknownFlagsStore,
IUnleashConfig,
} from '../../../types/index.js';
import type { IUnleashStores } from '../../../types/index.js';
import type { QueryParams, UnknownFlag } from './unknown-flags-store.js';
export class UnknownFlagsService {
private logger: Logger;
private flagResolver: IFlagResolver;
private unknownFlagsStore: IUnknownFlagsStore;
private unknownFlagsCache: Map<string, UnknownFlag>;
constructor(
{ unknownFlagsStore }: Pick<IUnleashStores, 'unknownFlagsStore'>,
config: IUnleashConfig,
) {
this.unknownFlagsStore = unknownFlagsStore;
this.flagResolver = config.flagResolver;
this.logger = config.getLogger(
'/features/metrics/unknown-flags/unknown-flags-service.ts',
);
this.unknownFlagsCache = new Map<string, UnknownFlag>();
}
private getKey(flag: UnknownFlag) {
return `${flag.name}:${flag.appName}:${flag.environment}`;
}
register(unknownFlags: UnknownFlag[]) {
if (!this.flagResolver.isEnabled('reportUnknownFlags')) return;
for (const flag of unknownFlags) {
const key = this.getKey(flag);
this.unknownFlagsCache.set(key, flag);
}
}
async flush(): Promise<void> {
if (!this.flagResolver.isEnabled('reportUnknownFlags')) return;
if (this.unknownFlagsCache.size === 0) return;
const cached = Array.from(this.unknownFlagsCache.values());
await this.unknownFlagsStore.insert(cached);
this.unknownFlagsCache.clear();
}
async getAll(queryParams?: QueryParams): Promise<UnknownFlag[]> {
if (!this.flagResolver.isEnabled('reportUnknownFlags')) return [];
return this.unknownFlagsStore.getAll(queryParams);
}
async clear(hoursAgo: number) {
if (!this.flagResolver.isEnabled('reportUnknownFlags')) return;
return this.unknownFlagsStore.clear(hoursAgo);
}
}