feat(admin/health): System Health Level 2 — метрики HTTP-запросов
backend/src/utils/metrics.js: лёгкие in-memory метрики (сброс при рестарте) — всего запросов, req/min (скользящее окно), латентность avg/p50/p95/p99, разбивка по статусам 2xx/3xx/4xx/5xx, топ маршрутов по частоте/латентности/ ошибкам (группировка по шаблону route.path, не по URL). server.js: middleware (на /api, по res 'finish') пишет латентность и статус. adminController.getMetrics + GET /api/admin/metrics (под admin-auth). admin.js: health-страница переведена на refreshHealth/renderHealth (Level 1) + секция «Метрики запросов»: карточки req/min/всего/avg/p95/p99/5xx, цветная полоса статусов, топ медленных/частых/ошибочных маршрутов. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -138,6 +138,19 @@ const { requireFeature } = require('./middleware/features');
|
||||
app.use('/api/classroom', rateLimit({ windowMs: 60_000, max: 6000, message: 'Слишком много запросов' }));
|
||||
app.use('/api', rateLimit({ windowMs: 60_000, max: 600, message: 'Слишком много запросов, подождите минуту' }));
|
||||
|
||||
/* ── Request metrics (System Health Level 2) ── */
|
||||
const metrics = require('./utils/metrics');
|
||||
app.use((req, res, next) => {
|
||||
if (!req.originalUrl.startsWith('/api')) return next();
|
||||
const start = process.hrtime.bigint();
|
||||
res.on('finish', () => {
|
||||
const ms = Number(process.hrtime.bigint() - start) / 1e6;
|
||||
const route = (req.baseUrl || '') + (req.route && req.route.path ? req.route.path : '');
|
||||
metrics.record(req.method, route || req.path || '(unmatched)', res.statusCode, ms);
|
||||
});
|
||||
next();
|
||||
});
|
||||
|
||||
/* ── Routes ── */
|
||||
app.use('/api/auth', authRoutes);
|
||||
app.use('/api/subjects', subjectRoutes);
|
||||
|
||||
Reference in New Issue
Block a user