From 79dc5b652127b075ecd1da4107438114a28b3bc6 Mon Sep 17 00:00:00 2001 From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:37:31 +0200 Subject: [PATCH] remove impact metrics backend --- .../createImpactMetricsService.ts | 10 -- .../impact-metrics-controller.ts | 67 -------- .../impact-metrics/impact-metrics-service.ts | 155 ------------------ src/lib/openapi/spec/impact-metrics-schema.ts | 15 -- src/lib/openapi/spec/index.ts | 1 - src/lib/services/index.ts | 11 -- 6 files changed, 259 deletions(-) delete mode 100644 src/lib/features/impact-metrics/createImpactMetricsService.ts delete mode 100644 src/lib/features/impact-metrics/impact-metrics-controller.ts delete mode 100644 src/lib/features/impact-metrics/impact-metrics-service.ts delete mode 100644 src/lib/openapi/spec/impact-metrics-schema.ts diff --git a/src/lib/features/impact-metrics/createImpactMetricsService.ts b/src/lib/features/impact-metrics/createImpactMetricsService.ts deleted file mode 100644 index 457a0b79b9..0000000000 --- a/src/lib/features/impact-metrics/createImpactMetricsService.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { IUnleashConfig } from '../../types/index.js'; -import ImpactMetricsService from './impact-metrics-service.js'; - -export const createImpactMetricsService = (config: IUnleashConfig) => { - return new ImpactMetricsService(config); -}; - -export const createFakeImpactMetricsService = (config: IUnleashConfig) => { - return new ImpactMetricsService(config); -}; diff --git a/src/lib/features/impact-metrics/impact-metrics-controller.ts b/src/lib/features/impact-metrics/impact-metrics-controller.ts deleted file mode 100644 index bc416ec703..0000000000 --- a/src/lib/features/impact-metrics/impact-metrics-controller.ts +++ /dev/null @@ -1,67 +0,0 @@ -import type { Response } from 'express'; -import Controller from '../../routes/controller.js'; -import type { IAuthRequest } from '../../routes/unleash-types.js'; -import type { IUnleashConfig } from '../../types/option.js'; -import { NONE } from '../../types/permissions.js'; -import type { OpenApiService } from '../../services/openapi-service.js'; -import { getStandardResponses } from '../../openapi/util/standard-responses.js'; -import { createResponseSchema } from '../../openapi/util/create-response-schema.js'; -import type ImpactMetricsService from './impact-metrics-service.js'; -import { - impactMetricsSchema, - type ImpactMetricsSchema, -} from '../../openapi/spec/impact-metrics-schema.js'; - -interface ImpactMetricsServices { - impactMetricsService: ImpactMetricsService; - openApiService: OpenApiService; -} - -export default class ImpactMetricsController extends Controller { - private impactMetricsService: ImpactMetricsService; - private openApiService: OpenApiService; - - constructor( - config: IUnleashConfig, - { impactMetricsService, openApiService }: ImpactMetricsServices, - ) { - super(config); - this.impactMetricsService = impactMetricsService; - this.openApiService = openApiService; - - this.route({ - method: 'get', - path: '', - handler: this.getImpactMetrics, - permission: NONE, - middleware: [ - openApiService.validPath({ - tags: ['Unstable'], - operationId: 'getImpactMetrics', - summary: 'Get impact metrics', - description: - 'Retrieves impact metrics data from Prometheus and forwards it to the frontend.', - responses: { - 200: createResponseSchema('impactMetricsSchema'), - ...getStandardResponses(401, 403, 404), - }, - }), - ], - }); - } - - async getImpactMetrics( - req: IAuthRequest, - res: Response, - ): Promise { - const metrics = - await this.impactMetricsService.getMetricsFromPrometheus(); - - this.openApiService.respondWithValidation( - 200, - res, - impactMetricsSchema.$id, - metrics, - ); - } -} diff --git a/src/lib/features/impact-metrics/impact-metrics-service.ts b/src/lib/features/impact-metrics/impact-metrics-service.ts deleted file mode 100644 index fa57886558..0000000000 --- a/src/lib/features/impact-metrics/impact-metrics-service.ts +++ /dev/null @@ -1,155 +0,0 @@ -import type { Logger } from '../../logger.js'; -import type { IUnleashConfig } from '../../types/index.js'; - -interface PrometheusResponse { - status: string; - data: any; -} - -interface MetricSeries { - name: string; - available: boolean; - labels: Record; -} - -export interface IImpactMetricsService { - getMetricsFromPrometheus(): Promise<{ - availableMetrics: MetricSeries[]; - totalCount: number; - }>; -} - -// TODO: URL -const prometheusUrl = 'http://localhost:9090'; - -export default class ImpactMetricsService implements IImpactMetricsService { - private logger: Logger; - private config: IUnleashConfig; - - constructor(config: IUnleashConfig) { - this.logger = config.getLogger( - 'impact-metrics/impact-metrics-service.ts', - ); - this.config = config; - } - - async getMetricsFromPrometheus(): Promise<{ - availableMetrics: MetricSeries[]; - totalCount: number; - }> { - const testingMetrics = [ - 'node_cpu_seconds_total', - 'node_load5', - 'node_memory_MemAvailable_bytes', - 'node_disk_read_bytes_total', - 'node_disk_written_bytes_total', - 'node_network_receive_bytes_total', - 'node_network_transmit_bytes_total', - 'node_filesystem_avail_bytes', - 'node_filesystem_size_bytes', - ]; - - try { - this.logger.info('Fetching all metrics from Prometheus'); - - const metricsResponse = await fetch( - `${prometheusUrl}/api/v1/label/__name__/values`, - ); - - if (!metricsResponse.ok) { - throw new Error( - `Failed to fetch metrics: ${metricsResponse.status}`, - ); - } - - const metricsData = - (await metricsResponse.json()) as PrometheusResponse; - if (metricsData.status !== 'success') { - throw new Error('Prometheus API returned error status'); - } - - const allMetrics: string[] = metricsData.data; - this.logger.info( - `Found ${allMetrics.length} total metrics in Prometheus`, - ); - - const availableMetrics: MetricSeries[] = []; - - for (const metricName of testingMetrics) { - const isAvailable = allMetrics.includes(metricName); - - let labels: Record = {}; - - if (isAvailable) { - try { - const seriesUrl = `${prometheusUrl}/api/v1/series?match[]=${encodeURIComponent(metricName)}`; - this.logger.debug( - `Fetching series for metric: ${metricName}`, - ); - - const seriesResponse = await fetch(seriesUrl); - const seriesData = - (await seriesResponse.json()) as PrometheusResponse; - if (seriesData.status === 'success') { - const labelMap: Record> = {}; - - seriesData.data.forEach( - (series: Record) => { - Object.entries(series).forEach( - ([key, value]) => { - if (key !== '__name__') { - if (!labelMap[key]) { - labelMap[key] = new Set(); - } - labelMap[key].add(value); - } - }, - ); - }, - ); - - labels = Object.fromEntries( - Object.entries(labelMap).map( - ([key, valueSet]) => [ - key, - Array.from(valueSet).sort(), - ], - ), - ); - } - } catch (error) { - this.logger.warn( - `Failed to fetch labels for metric ${metricName}:`, - error, - ); - } - } - - availableMetrics.push({ - name: metricName, - available: isAvailable, - labels, - }); - - this.logger.debug( - `Metric ${metricName}: available=${isAvailable}, labelCount=${Object.keys(labels).length}`, - ); - } - - const availableCount = availableMetrics.filter( - (m) => m.available, - ).length; - this.logger.info( - `Found ${availableCount}/${testingMetrics.length} test metrics available in Prometheus`, - ); - - return { - availableMetrics, - totalCount: allMetrics.length, - }; - } catch (error) { - this.logger.error('Error fetching metrics from Prometheus:', error); - throw error; - } - } -} diff --git a/src/lib/openapi/spec/impact-metrics-schema.ts b/src/lib/openapi/spec/impact-metrics-schema.ts deleted file mode 100644 index 6b877dfec1..0000000000 --- a/src/lib/openapi/spec/impact-metrics-schema.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { FromSchema } from 'json-schema-to-ts'; - -export const impactMetricsSchema = { - $id: '#/components/schemas/impactMetricsSchema', - type: 'object', - description: 'Impact metrics data from Prometheus', - additionalProperties: true, - required: [], - properties: {}, - components: { - schemas: {}, - }, -} as const; - -export type ImpactMetricsSchema = FromSchema; diff --git a/src/lib/openapi/spec/index.ts b/src/lib/openapi/spec/index.ts index 6e44c2ba4b..04771b2f0e 100644 --- a/src/lib/openapi/spec/index.ts +++ b/src/lib/openapi/spec/index.ts @@ -113,7 +113,6 @@ export * from './health-overview-schema.js'; export * from './health-report-schema.js'; export * from './id-schema.js'; export * from './ids-schema.js'; -export * from './impact-metrics-schema.js'; export * from './import-toggles-schema.js'; export * from './import-toggles-validate-item-schema.js'; export * from './import-toggles-validate-schema.js'; diff --git a/src/lib/services/index.ts b/src/lib/services/index.ts index 19aaf35332..0f80b77f38 100644 --- a/src/lib/services/index.ts +++ b/src/lib/services/index.ts @@ -171,11 +171,6 @@ import type { import type { IPrivateProjectChecker } from '../features/private-project/privateProjectCheckerType.js'; import { UnknownFlagsService } from '../features/metrics/unknown-flags/unknown-flags-service.js'; import type FeatureLinkService from '../features/feature-links/feature-link-service.js'; -import { - createFakeImpactMetricsService, - createImpactMetricsService, -} from '../features/impact-metrics/createImpactMetricsService.js'; -import type ImpactMetricsService from '../features/impact-metrics/impact-metrics-service.js'; export const createServices = ( stores: IUnleashStores, @@ -446,10 +441,6 @@ export const createServices = ( ? withTransactional(createUserSubscriptionsService(config), db) : withFakeTransactional(createFakeUserSubscriptionsService(config)); - const impactMetricsService = db - ? createImpactMetricsService(config) - : createFakeImpactMetricsService(config); - return { transactionalAccessService, accessService, @@ -516,7 +507,6 @@ export const createServices = ( integrationEventsService, onboardingService, personalDashboardService, - impactMetricsService, projectStatusService, transactionalUserSubscriptionsService, uniqueConnectionService, @@ -648,7 +638,6 @@ export interface IUnleashServices { integrationEventsService: IntegrationEventsService; onboardingService: OnboardingService; personalDashboardService: PersonalDashboardService; - impactMetricsService: ImpactMetricsService; projectStatusService: ProjectStatusService; transactionalUserSubscriptionsService: WithTransactional; uniqueConnectionService: UniqueConnectionService;