mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-02 00:14:23 +00:00
- `/api/metrics` in Prometheus text format, off until `METRICS_TOKEN` or `METRICS_TOKEN_FILE` is set (404 before, 401 without the bearer token): requests per route group with status class and latency, sign-in outcomes, calls to Stalwart, WOPI, translation, the plugin proxy and OAuth, browser errors, errors today, process memory, event-loop lag, uptime and build info. Labels come from fixed lists. Each replica serves its own. - `/api/health/live` answers while the process runs; `/api/health/ready` checks the config, the shared store, writable data dirs and Stalwart's session resource. `/api/health` and `/api/ready` are unchanged. - the Docker image gets a HEALTHCHECK on the live endpoint - adds prom-client, and the OpenTelemetry packages the tracing step loads on demand
33 lines
1.4 KiB
TypeScript
33 lines
1.4 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { requireAdminAuth } from '@/lib/admin/session';
|
|
import { logger } from '@/lib/logger';
|
|
import { readErrors, summarizeDay, utcDay } from '@/lib/error-reporting/aggregate';
|
|
import { shouldCollectErrors } from '@/lib/error-reporting/settings';
|
|
import { storedDataUnavailableResponse } from '@/lib/stored-data-errors';
|
|
import { metricsEnabled } from '@/lib/metrics';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
/**
|
|
* GET /api/admin/monitoring: what System > Monitoring shows besides the
|
|
* config keys (those come from /api/admin/config): whether errors are being
|
|
* counted, today's counts and whether the metrics endpoint is on.
|
|
*/
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
const auth = await requireAdminAuth(request);
|
|
if ('error' in auth) return auth.error;
|
|
|
|
const collecting = await shouldCollectErrors();
|
|
const today = utcDay();
|
|
const errorsToday = summarizeDay(await readErrors(), today);
|
|
const metrics = { enabled: metricsEnabled() };
|
|
return NextResponse.json({ collecting, day: today, errorsToday, metrics }, { headers: { 'Cache-Control': 'no-store' } });
|
|
} catch (err) {
|
|
logger.error('monitoring GET error', { error: err instanceof Error ? err.message : 'unknown' });
|
|
const unavailable = storedDataUnavailableResponse(err);
|
|
if (unavailable) return unavailable;
|
|
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
|
}
|
|
}
|