Skip to main content
Glama
metrics.ts4.82 kB
/** * Metric search engine using Orama for semantic search * * Indexes live Prometheus metrics and enables semantic search * by name and description, not just regex pattern matching. */ import { SearchEngine, type BaseDocument } from '@prodisco/search-libs'; import type { MetricInfo, MetricType } from './types.js'; import { PrometheusClient } from './client.js'; /** * Search options for finding metrics */ export interface MetricSearchOptions { /** Maximum number of results (default: 20) */ limit?: number; /** Filter by metric type */ type?: MetricType; } /** * MetricSearchEngine - Semantic search for Prometheus metrics * * Uses Orama search engine to index metric names and descriptions, * enabling natural language search like "memory consumption" instead * of requiring exact metric names. */ export class MetricSearchEngine { private client: PrometheusClient; private searchEngine: SearchEngine; private indexed = false; private indexedCount = 0; private lastIndexTime: number | null = null; /** Cache TTL in milliseconds (5 minutes) */ private static readonly CACHE_TTL_MS = 5 * 60 * 1000; constructor(client: PrometheusClient) { this.client = client; this.searchEngine = new SearchEngine({ tokenizerOptions: { stemming: true, stemmerSkipProperties: ['name'], }, }); } /** * Index all metrics from Prometheus into the search engine. * * @param force - Force re-indexing even if cache is valid */ async index(force = false): Promise<number> { // Check if cache is still valid if (!force && this.indexed && this.lastIndexTime) { const elapsed = Date.now() - this.lastIndexTime; if (elapsed < MetricSearchEngine.CACHE_TTL_MS) { return this.indexedCount; } } // Fetch all metrics from Prometheus const metrics = await this.client.listMetrics(); // Build documents for indexing const docs: BaseDocument[] = metrics.map((m) => ({ id: `metric:${m.name}`, documentType: 'metric' as const, name: m.name, description: m.help, searchTokens: `${m.name.replace(/_/g, ' ')} ${m.type} ${m.help}`, library: 'prometheus', category: m.type, properties: '', typeDefinition: '', nestedTypes: '', typeKind: '', parameters: '', returnType: '', returnTypeDefinition: '', signature: '', className: '', filePath: '', keywords: m.type, })); // Re-initialize search engine for fresh index this.searchEngine = new SearchEngine({ tokenizerOptions: { stemming: true, stemmerSkipProperties: ['name'], }, }); await this.searchEngine.initialize(); await this.searchEngine.insertBatch(docs); this.indexed = true; this.indexedCount = docs.length; this.lastIndexTime = Date.now(); return this.indexedCount; } /** * Search for metrics using natural language. * * Examples: * - "memory usage" → finds container_memory_usage_bytes, etc. * - "http requests" → finds http_requests_total, etc. * - "cpu" → finds all CPU-related metrics * * @param query - Natural language search query * @param options - Search options (limit, type filter) * @returns Ranked list of matching metrics */ async search(query: string, options: MetricSearchOptions = {}): Promise<MetricInfo[]> { const { limit = 20, type } = options; if (!this.indexed) { await this.index(); } const result = await this.searchEngine.search({ query, limit, category: type, }); return result.results.map((doc) => ({ name: doc.name, type: (doc.category as MetricType) || 'unknown', help: doc.description, })); } /** * List all indexed metrics */ async list(options: MetricSearchOptions = {}): Promise<MetricInfo[]> { const { limit = 100, type } = options; if (!this.indexed) { await this.index(); } const result = await this.searchEngine.search({ query: '', limit, category: type, }); return result.results.map((doc) => ({ name: doc.name, type: (doc.category as MetricType) || 'unknown', help: doc.description, })); } getIndexedCount(): number { return this.indexedCount; } isReady(): boolean { return this.indexed; } async clear(): Promise<void> { await this.searchEngine.shutdown(); this.indexed = false; this.indexedCount = 0; this.lastIndexTime = null; } } /** * Create a MetricSearchEngine from a Prometheus endpoint */ export function createMetricSearchEngine(endpoint: string): MetricSearchEngine { const client = new PrometheusClient({ endpoint }); return new MetricSearchEngine(client); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/harche/ProDisco'

If you have feedback or need assistance with the MCP directory API, please join our Discord server