Files
Learn_System/backend/src/controllers/clientErrorController.js
T
Maxim Dolgolyov 43df41287f feat(errors): сбор клиентских (браузерных) ошибок в админ-вкладку «Ошибки»
Глобальный репортер в api.js (грузится на всех страницах) ловит необработанные JS-ошибки
(window 'error') и rejected-промисы ('unhandledrejection') в браузере пользователя и шлёт
в POST /api/client-errors. Дедуп по сигнатуре + лимит 15/страницу, только для залогиненных,
keepalive, не флудит и сам не падает.

Бэкенд: routes/clientErrors (auth + rate-limit 20/мин на юзера) → clientErrorController
пишет в общий error_log с level='client' (message/stack/route=url/method=kind/user_id),
поля обрезаются. Появляются в существующей админ-вкладке «Ошибки» с бейджем «БРАУЗЕР»
(фиолетовый акцент vs розовый у серверных). Тест client-errors.test.js 5/5.

lint:routes 0; node --check всех файлов.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 23:17:04 +03:00

30 lines
1.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
/* clientErrorController — приём ошибок из браузера пользователя.
Пишем в общий error_log с level='client', чтобы они появились в админ-вкладке «Ошибки».
Запись не должна ронять запрос — любые сбои глушим. */
const db = require('../db/db');
const MAX_MSG = 1000, MAX_STACK = 4000, MAX_ROUTE = 400;
const clamp = (v, n) => (v == null ? null : String(v).slice(0, n));
function report(req, res) {
const b = req.body || {};
const message = (clamp(b.message, MAX_MSG) || '').trim();
if (!message) return res.status(400).json({ error: 'message required' });
const kind = b.kind === 'unhandledrejection' ? 'rejection' : 'error';
const route = clamp(b.url || b.route, MAX_ROUTE);
let stack = clamp(b.stack, MAX_STACK);
// если стека нет — собираем источник:строка:колонка
if (!stack && (b.source || b.line)) stack = `${b.source || ''}:${b.line || ''}:${b.col || ''}`;
try {
db.prepare(
'INSERT INTO error_log (level, message, stack, route, method, user_id) VALUES (?, ?, ?, ?, ?, ?)'
).run('client', message, stack, route, kind, req.user.id);
} catch { /* лог не должен ломать ответ */ }
res.json({ ok: true });
}
module.exports = { report };