mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-09 13:47:13 +02:00
remove impact metrics backend
This commit is contained in:
parent
7bed75cb9f
commit
79dc5b6521
@ -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);
|
|
||||||
};
|
|
@ -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<ImpactMetricsSchema>,
|
|
||||||
): Promise<void> {
|
|
||||||
const metrics =
|
|
||||||
await this.impactMetricsService.getMetricsFromPrometheus();
|
|
||||||
|
|
||||||
this.openApiService.respondWithValidation(
|
|
||||||
200,
|
|
||||||
res,
|
|
||||||
impactMetricsSchema.$id,
|
|
||||||
metrics,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<string, string[]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
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<string, string[]> = {};
|
|
||||||
|
|
||||||
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<string, Set<string>> = {};
|
|
||||||
|
|
||||||
seriesData.data.forEach(
|
|
||||||
(series: Record<string, string>) => {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<typeof impactMetricsSchema>;
|
|
@ -113,7 +113,6 @@ export * from './health-overview-schema.js';
|
|||||||
export * from './health-report-schema.js';
|
export * from './health-report-schema.js';
|
||||||
export * from './id-schema.js';
|
export * from './id-schema.js';
|
||||||
export * from './ids-schema.js';
|
export * from './ids-schema.js';
|
||||||
export * from './impact-metrics-schema.js';
|
|
||||||
export * from './import-toggles-schema.js';
|
export * from './import-toggles-schema.js';
|
||||||
export * from './import-toggles-validate-item-schema.js';
|
export * from './import-toggles-validate-item-schema.js';
|
||||||
export * from './import-toggles-validate-schema.js';
|
export * from './import-toggles-validate-schema.js';
|
||||||
|
@ -171,11 +171,6 @@ import type {
|
|||||||
import type { IPrivateProjectChecker } from '../features/private-project/privateProjectCheckerType.js';
|
import type { IPrivateProjectChecker } from '../features/private-project/privateProjectCheckerType.js';
|
||||||
import { UnknownFlagsService } from '../features/metrics/unknown-flags/unknown-flags-service.js';
|
import { UnknownFlagsService } from '../features/metrics/unknown-flags/unknown-flags-service.js';
|
||||||
import type FeatureLinkService from '../features/feature-links/feature-link-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 = (
|
export const createServices = (
|
||||||
stores: IUnleashStores,
|
stores: IUnleashStores,
|
||||||
@ -446,10 +441,6 @@ export const createServices = (
|
|||||||
? withTransactional(createUserSubscriptionsService(config), db)
|
? withTransactional(createUserSubscriptionsService(config), db)
|
||||||
: withFakeTransactional(createFakeUserSubscriptionsService(config));
|
: withFakeTransactional(createFakeUserSubscriptionsService(config));
|
||||||
|
|
||||||
const impactMetricsService = db
|
|
||||||
? createImpactMetricsService(config)
|
|
||||||
: createFakeImpactMetricsService(config);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
transactionalAccessService,
|
transactionalAccessService,
|
||||||
accessService,
|
accessService,
|
||||||
@ -516,7 +507,6 @@ export const createServices = (
|
|||||||
integrationEventsService,
|
integrationEventsService,
|
||||||
onboardingService,
|
onboardingService,
|
||||||
personalDashboardService,
|
personalDashboardService,
|
||||||
impactMetricsService,
|
|
||||||
projectStatusService,
|
projectStatusService,
|
||||||
transactionalUserSubscriptionsService,
|
transactionalUserSubscriptionsService,
|
||||||
uniqueConnectionService,
|
uniqueConnectionService,
|
||||||
@ -648,7 +638,6 @@ export interface IUnleashServices {
|
|||||||
integrationEventsService: IntegrationEventsService;
|
integrationEventsService: IntegrationEventsService;
|
||||||
onboardingService: OnboardingService;
|
onboardingService: OnboardingService;
|
||||||
personalDashboardService: PersonalDashboardService;
|
personalDashboardService: PersonalDashboardService;
|
||||||
impactMetricsService: ImpactMetricsService;
|
|
||||||
projectStatusService: ProjectStatusService;
|
projectStatusService: ProjectStatusService;
|
||||||
transactionalUserSubscriptionsService: WithTransactional<UserSubscriptionsService>;
|
transactionalUserSubscriptionsService: WithTransactional<UserSubscriptionsService>;
|
||||||
uniqueConnectionService: UniqueConnectionService;
|
uniqueConnectionService: UniqueConnectionService;
|
||||||
|
Loading…
Reference in New Issue
Block a user