* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix * fix: track native source modules with root-anchored runtime ignores
49 lines
2.4 KiB
JavaScript
49 lines
2.4 KiB
JavaScript
import { randomUUID } from 'node:crypto';
|
|
|
|
const startedAt = new Date().toISOString();
|
|
const telemetry = {
|
|
total: 0, active: 0, errors: 0, blocked: 0,
|
|
by_status: {}, by_method: {}, last_error_at: null, last_blocked_at: null,
|
|
recent: [],
|
|
};
|
|
|
|
function safePath(req) { return String(req.path || req.url || '').split('?')[0].slice(0, 300); }
|
|
function enabled() { return !/^(0|false|no)$/i.test(String(process.env.VENDOO_JSON_LOGS || 'true')); }
|
|
|
|
export function recordSecurityBlock(reason) {
|
|
telemetry.blocked += 1;
|
|
telemetry.last_blocked_at = new Date().toISOString();
|
|
if (enabled()) console.warn(JSON.stringify({ level: 'warn', event: 'security.blocked', reason, time: telemetry.last_blocked_at }));
|
|
}
|
|
|
|
export function requestContextMiddleware(req, res, next) {
|
|
const requestId = String(req.get('x-vendoo-request-id') || randomUUID()).replace(/[^a-zA-Z0-9._:-]/g, '').slice(0, 100) || randomUUID();
|
|
const correlationId = String(req.get('x-correlation-id') || requestId).replace(/[^a-zA-Z0-9._:-]/g, '').slice(0, 100) || requestId;
|
|
const started = process.hrtime.bigint();
|
|
req.requestId = requestId;
|
|
req.correlationId = correlationId;
|
|
res.setHeader('X-Vendoo-Request-ID', requestId);
|
|
res.setHeader('X-Correlation-ID', correlationId);
|
|
telemetry.total += 1; telemetry.active += 1;
|
|
telemetry.by_method[req.method] = (telemetry.by_method[req.method] || 0) + 1;
|
|
res.on('finish', () => {
|
|
telemetry.active = Math.max(0, telemetry.active - 1);
|
|
const durationMs = Number(process.hrtime.bigint() - started) / 1e6;
|
|
const status = String(res.statusCode);
|
|
telemetry.by_status[status] = (telemetry.by_status[status] || 0) + 1;
|
|
if (res.statusCode >= 500) { telemetry.errors += 1; telemetry.last_error_at = new Date().toISOString(); }
|
|
const entry = {
|
|
time: new Date().toISOString(), request_id: requestId, correlation_id: correlationId,
|
|
method: req.method, path: safePath(req), status: res.statusCode,
|
|
duration_ms: Math.round(durationMs * 10) / 10, user_id: req.user?.id || null,
|
|
};
|
|
telemetry.recent.unshift(entry); telemetry.recent = telemetry.recent.slice(0, 50);
|
|
if (enabled()) console.log(JSON.stringify({ level: res.statusCode >= 500 ? 'error' : 'info', event: 'http.request', ...entry }));
|
|
});
|
|
next();
|
|
}
|
|
|
|
export function getRequestTelemetry() {
|
|
return { started_at: startedAt, ...telemetry, recent: telemetry.recent.map(item => ({ ...item })) };
|
|
}
|