/** * LandveX Finance — Prometheus Metrics * Sprint 3: Observability */ import promClient from 'prom-client'; const registry = new promClient.Registry(); // ── Journal / Verifikat ── export const journalCounter = new promClient.Counter({ name: 'finance_journal_entries_total', help: 'Total journal entries created', labelNames: ['tenant', 'period', 'status'], registers: [registry], }); export const journalAmount = new promClient.Counter({ name: 'finance_journal_amount_total', help: 'Total journal amount by direction', labelNames: ['tenant', 'period', 'direction'], registers: [registry], }); // ── Invoices / Fakturor ── export const invoiceGauge = new promClient.Gauge({ name: 'finance_invoices_total', help: 'Total invoices by status', labelNames: ['tenant', 'status'], registers: [registry], }); // ── VAT / Moms ── export const vatGauge = new promClient.Gauge({ name: 'finance_vat_payable', help: 'VAT payable to tax authority', labelNames: ['tenant', 'period'], registers: [registry], }); // ── Payroll / Löner ── export const payrollGauge = new promClient.Gauge({ name: 'finance_payroll_total', help: 'Total payroll cost for period', labelNames: ['tenant', 'period'], registers: [registry], }); // ── Receipts / Kvitton ── export const receiptCounter = new promClient.Counter({ name: 'finance_receipts_uploaded_total', help: 'Total receipts uploaded', labelNames: ['tenant'], registers: [registry], }); // ── API Performance ── export const apiHistogram = new promClient.Histogram({ name: 'finance_api_duration_seconds', help: 'Finance API endpoint duration', labelNames: ['endpoint', 'method', 'status'], buckets: [0.01, 0.05, 0.1, 0.3, 0.5, 1, 2, 5], registers: [registry], }); // ── Period Close ── export const periodCloseCounter = new promClient.Counter({ name: 'finance_period_closures_total', help: 'Period closures attempted', labelNames: ['tenant', 'period', 'result'], registers: [registry], }); // ── Health Check Duration ── export const healthCheckDuration = new promClient.Histogram({ name: 'finance_health_check_duration_ms', help: 'Health check duration in milliseconds', labelNames: ['check'], buckets: [1, 5, 10, 25, 50, 100, 250, 500], registers: [registry], }); // ── Disk Usage ── export const diskGauge = new promClient.Gauge({ name: 'finance_disk_used_percent', help: 'Disk usage percentage', labelNames: ['path'], registers: [registry], }); // ── Helper: timed API call ── export async function timedAPI(endpoint, method, fn) { const end = apiHistogram.startTimer(); try { const result = await fn(); end({ endpoint, method, status: 'success' }); return result; } catch (e) { end({ endpoint, method, status: 'error' }); throw e; } } // ── Export all metrics ── export function getMetrics() { return registry.metrics(); } export function getContentType() { return registry.contentType; }