import { Injectable } from '@nestjs/common'; import { HttpService } from '@nestjs/axios'; import { ConfigService } from '@nestjs/config'; import { lastValueFrom } from 'rxjs'; import { PrometheusMetric } from './prometheus-metric.interface'; @Injectable() export class PrometheusService { private readonly prometheusUrl: string; constructor( private readonly httpService: HttpService, private readonly configService: ConfigService ) { this.prometheusUrl = this.configService.get('PROMETHEUS_API', 'http://localhost:9090'); console.log('Prometheus API URL:', this.prometheusUrl); } // Получаем тип метрики async fetchMetricType(metric: string): Promise { try { const response = await lastValueFrom( this.httpService.get(`${this.prometheusUrl}/metadata`, { params: { metric }, }) ); const metadata = response.data.data[metric]; return metadata?.length ? metadata[0].type : null; } catch (error) { console.error(`Ошибка при получении типа метрики ${metric}:`, error); return null; } } // Получаем описание метрики async fetchMetricDescription(metric: string): Promise { try { const response = await lastValueFrom( this.httpService.get(`${this.prometheusUrl}/metadata`, { params: { metric }, }) ); const metadata = response.data.data[metric]; return metadata?.length ? metadata[0].help : undefined; } catch (error) { console.error(`Ошибка при получении описания метрики ${metric}:`, error); return undefined; } } // Получаем данные метрики (текущие значения) async fetchMetrics(metric: string): Promise { const response = await lastValueFrom( this.httpService.get(`${this.prometheusUrl}/query`, { params: { query: metric }, }) ); const metricType = await this.fetchMetricType(metric); const metricDescription = await this.fetchMetricDescription(metric); return response.data.data.result.map((entry): PrometheusMetric => ({ ...entry.metric, timestamp: entry.value[0] * 1000, value: parseFloat(entry.value[1]), type: metricType || 'unknown', description: metricDescription, // Добавляем описание })); } // Получаем данные метрики за интервал async fetchMetricsRange(metric: string, start: number, end: number, step: number): Promise { const response = await lastValueFrom( this.httpService.get(`${this.prometheusUrl}/query_range`, { params: { query: metric, start, end, step, }, }) ); const metricType = await this.fetchMetricType(metric); const metricDescription = await this.fetchMetricDescription(metric); return response.data.data.result.flatMap((entry) => entry.values.map((value): PrometheusMetric => ({ ...entry.metric, timestamp: value[0] * 1000, value: parseFloat(value[1]), type: metricType || 'unknown', description: metricDescription, // Добавляем описание })) ); } // Получаем список всех метрик async fetchAllMetrics(): Promise { const response = await lastValueFrom( this.httpService.get(`${this.prometheusUrl}/label/__name__/values`) ); return response.data.data; } // Получаем все метрики с их значениями async fetchAllMetricsWithValues(): Promise { const metricNames = await this.fetchAllMetrics(); const promises = metricNames.map(async (metric) => { const data = await this.fetchMetrics(metric); return { metric, data }; }); return Promise.all(promises); } }