import type { CountResult } from "../types.js"; export class Metrics { private readonly requestCounts = new Map(); private requestDurationMs = 0; private scanCount = 0; private scanDurationMs = 0; private cachedScanCount = 0; private countedFiles = 0; private countedLines = 0; recordRequest(route: string, status: number, durationMs: number): void { const key = `${route}\u0000${status}`; this.requestCounts.set(key, (this.requestCounts.get(key) ?? 0) + 1); this.requestDurationMs += durationMs; } recordScan(result: CountResult): void { this.scanCount += 1; this.scanDurationMs += result.durationMs; this.cachedScanCount += Number(result.cached); this.countedFiles += result.fileCount; this.countedLines += result.lineCount; } renderPrometheus(): string { const lines = [ "# HELP loc_via_git_http_requests_total HTTP responses by route and status.", "# TYPE loc_via_git_http_requests_total counter" ]; for (const [key, count] of this.requestCounts) { const [route, status] = key.split("\u0000"); lines.push(`loc_via_git_http_requests_total{route="${route}",status="${status}"} ${count}`); } lines.push( "# HELP loc_via_git_http_request_duration_ms_total Total HTTP request duration in milliseconds.", "# TYPE loc_via_git_http_request_duration_ms_total counter", `loc_via_git_http_request_duration_ms_total ${this.requestDurationMs}`, "# HELP loc_via_git_scans_total Completed LOC scans.", "# TYPE loc_via_git_scans_total counter", `loc_via_git_scans_total ${this.scanCount}`, "# HELP loc_via_git_cached_scans_total Completed scans served from cache.", "# TYPE loc_via_git_cached_scans_total counter", `loc_via_git_cached_scans_total ${this.cachedScanCount}`, "# HELP loc_via_git_scan_duration_ms_total Total scan duration in milliseconds.", "# TYPE loc_via_git_scan_duration_ms_total counter", `loc_via_git_scan_duration_ms_total ${this.scanDurationMs}`, "# HELP loc_via_git_counted_files_total Files included in completed scan results.", "# TYPE loc_via_git_counted_files_total counter", `loc_via_git_counted_files_total ${this.countedFiles}`, "# HELP loc_via_git_counted_lines_total Non-empty lines included in completed scan results.", "# TYPE loc_via_git_counted_lines_total counter", `loc_via_git_counted_lines_total ${this.countedLines}` ); return `${lines.join("\n")}\n`; } }