feat(api): Protokollzeile je Anfrage und je Nextcloud-Pruefung im Docker-Log

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-02 23:42:10 +02:00
parent fffb7ffbec
commit 0afcf237e8
5 changed files with 96 additions and 4 deletions
+51
View File
@@ -0,0 +1,51 @@
import { Logger } from '@nestjs/common';
import type { NextFunction, Request, Response } from 'express';
/**
* Eine Protokollzeile je API-Anfrage im Docker-Log (quick-261002):
* `GET /modules/nextcloud-status/instances 200 34 ms user=admin`.
*
* Nur Methode, Pfad OHNE Abfrageteil (dort koennten Kennungen oder Token
* stehen), Status, Dauer und Benutzername — nie Koerper, Cookies oder
* Kopfzeilen. `/health` wird ausgelassen, der Docker-Healthcheck fragt es
* alle paar Sekunden ab. Fehler (>= 500) als `error`, Abweisungen (>= 400)
* als `warn`, langsame Anfragen (>= 3 s) mit Vermerk.
*/
const logger = new Logger('HTTP');
export const SLOW_REQUEST_MS = 3000;
export function formatRequestLine(input: {
method: string;
url: string;
status: number;
ms: number;
username?: string | null;
}): string {
const path = input.url.split('?')[0] ?? input.url;
const slow = input.ms >= SLOW_REQUEST_MS ? ' LANGSAM' : '';
return `${input.method} ${path} ${input.status} ${input.ms} ms user=${input.username ?? '-'}${slow}`;
}
export function requestLogMiddleware(req: Request, res: Response, next: NextFunction): void {
const url = req.originalUrl ?? req.url;
if (url === '/health' || url.startsWith('/health?') || url.startsWith('/health/')) {
next();
return;
}
const started = process.hrtime.bigint();
res.on('finish', () => {
const ms = Number((process.hrtime.bigint() - started) / 1_000_000n);
const username = (req as Request & { user?: { username?: string } }).user?.username;
const line = formatRequestLine({
method: req.method,
url,
status: res.statusCode,
ms,
username,
});
if (res.statusCode >= 500) logger.error(line);
else if (res.statusCode >= 400 || ms >= SLOW_REQUEST_MS) logger.warn(line);
else logger.log(line);
});
next();
}