added a garbage filter
parent
1a63f20bb0
commit
319e2cdd69
|
|
@ -0,0 +1,5 @@
|
|||
export interface MetricMetadata {
|
||||
metric: string;
|
||||
type: string;
|
||||
help: string;
|
||||
}
|
||||
|
|
@ -1,15 +1,12 @@
|
|||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrometheusService } from '../prometheus.service';
|
||||
import { MenuItem } from './menu.interface';
|
||||
|
||||
@Injectable()
|
||||
export class MenuService {
|
||||
constructor(
|
||||
private readonly prometheusService: PrometheusService // Просто объявляем зависимость
|
||||
) {}
|
||||
constructor(private readonly prometheusService: PrometheusService) {}
|
||||
|
||||
async getFullMenu(): Promise<MenuItem> {
|
||||
// Реализация остается прежней
|
||||
const dynamicItems = await this.generateDynamicItems();
|
||||
return this.injectDynamicItems(this.getStaticStructure(), dynamicItems);
|
||||
}
|
||||
|
|
@ -37,7 +34,9 @@ export class MenuService {
|
|||
private async generateDynamicItems(): Promise<MenuItem[]> {
|
||||
const metricNames = await this.prometheusService.fetchAllMetrics();
|
||||
|
||||
const allSeries = await Promise.all(
|
||||
// Получаем все серии для каждой метрики
|
||||
const allSeries = (
|
||||
await Promise.all(
|
||||
metricNames.map(async name => {
|
||||
const series = await this.prometheusService.fetchMetricSeries(name);
|
||||
return series.map(s => ({
|
||||
|
|
@ -45,20 +44,53 @@ export class MenuService {
|
|||
labels: s
|
||||
}));
|
||||
})
|
||||
)
|
||||
).flat();
|
||||
|
||||
// Загружаем мета-информацию по каждой метрике
|
||||
const metadataMap = new Map<string, string>(); // metric -> help
|
||||
|
||||
await Promise.all(
|
||||
metricNames.map(async metric => {
|
||||
try {
|
||||
const meta = await this.prometheusService.fetchMetricMetadata(metric);
|
||||
if (meta?.help) {
|
||||
metadataMap.set(metric, meta.help);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(`No metadata for metric ${metric}`);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const flatSeries = allSeries.flat();
|
||||
const isGarbageDevice = (device: string) =>
|
||||
device.startsWith('/dev') ||
|
||||
device.startsWith('/proc') ||
|
||||
device.startsWith('/sys') ||
|
||||
device.startsWith('/rootfs') ||
|
||||
device.startsWith('/var') ||
|
||||
device.startsWith('overlay') ||
|
||||
device.startsWith('br') ||
|
||||
device.startsWith('docker0') ||
|
||||
device.startsWith('ens18') ||
|
||||
device.startsWith('sda') ||
|
||||
device.startsWith('sr0') ||
|
||||
device.startsWith('tmpfs') ||
|
||||
device.startsWith('veth') ||
|
||||
device.startsWith('gvfsd') ||
|
||||
device.startsWith('lo') ||
|
||||
device.startsWith('/run');
|
||||
|
||||
const devices = this.extractUniqueEntities(flatSeries, 'device');
|
||||
const devices = this.extractUniqueEntities(allSeries, 'device')
|
||||
.filter(device => !isGarbageDevice(device));
|
||||
|
||||
return devices.map(device => ({
|
||||
id: `device_${device}`,
|
||||
title: `Graviton S2082I (${device})`,
|
||||
items: this.generateModuleItems(device, flatSeries),
|
||||
items: this.generateModuleItems(device, allSeries, metadataMap),
|
||||
isDynamic: true
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private extractUniqueEntities(metrics: any[], field: string): string[] {
|
||||
const entities = new Set<string>();
|
||||
|
|
@ -70,7 +102,11 @@ export class MenuService {
|
|||
return Array.from(entities);
|
||||
}
|
||||
|
||||
private generateModuleItems(device: string, seriesData: { metric: string, labels: Record<string, string> }[]): MenuItem[] {
|
||||
private generateModuleItems(
|
||||
device: string,
|
||||
seriesData: { metric: string; labels: Record<string, string> }[],
|
||||
metadataMap: Map<string, string>
|
||||
): MenuItem[] {
|
||||
const modules = new Set<string>();
|
||||
|
||||
seriesData.forEach(({ labels }) => {
|
||||
|
|
@ -80,34 +116,41 @@ export class MenuService {
|
|||
});
|
||||
|
||||
return Array.from(modules).map(module => ({
|
||||
id: `module_${module.replace('module$', '')}`,
|
||||
title: `OS Linux АО (${module})`,
|
||||
items: this.generateMetricItems(device, module, seriesData),
|
||||
id: `module_${device}_${module}`,
|
||||
title: `Module ${module.replace('module$', '')}`,
|
||||
items: this.generateMetricItems(device, module, seriesData, metadataMap),
|
||||
isDynamic: true
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
private generateMetricItems(device: string, module: string, seriesData: { metric: string, labels: Record<string, string> }[]): MenuItem[] {
|
||||
private generateMetricItems(
|
||||
device: string,
|
||||
module: string,
|
||||
seriesData: { metric: string; labels: Record<string, string> }[],
|
||||
metadataMap: Map<string, string>
|
||||
): MenuItem[] {
|
||||
const filtered = seriesData.filter(
|
||||
({ labels }) => labels.device === device && labels.source_id === module
|
||||
);
|
||||
|
||||
const uniqueMetrics = new Set(filtered.map(entry => entry.metric));
|
||||
|
||||
return Array.from(uniqueMetrics).map(metric => ({
|
||||
return Array.from(uniqueMetrics).map(metric => {
|
||||
const description = metadataMap.get(metric) || metric;
|
||||
|
||||
return {
|
||||
id: `metric_${device}_${module}_${metric}`,
|
||||
title: metric, // или запрашивать описание отдельно
|
||||
title: description,
|
||||
metric,
|
||||
filters: {
|
||||
device,
|
||||
source_id: module
|
||||
},
|
||||
isDynamic: true
|
||||
}));
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private injectDynamicItems(menu: MenuItem, dynamicItems: MenuItem[]): MenuItem {
|
||||
if (menu.id === 'media_servers') {
|
||||
return { ...menu, items: dynamicItems };
|
||||
|
|
@ -119,7 +162,6 @@ export class MenuService {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
async updateMenuItem(id: string, update: Partial<MenuItem>): Promise<MenuItem> {
|
||||
const fullMenu = await this.getFullMenu();
|
||||
const item = this.findMenuItem(fullMenu, id);
|
||||
|
|
|
|||
Loading…
Reference in New Issue