feat(admin/health): System Health Level 4 — диагностика + последние ошибки
adminController.getHealth: активные health-проверки — отклик БД (ping, мс) и
тест записи на диск рядом с БД; вердикт уходит в critical при недоступной БД
или диске, warning при медленном отклике БД (>100мс). Плюс recentErrorList —
последние 8 записей error_log (level/route/method/message/время).
admin.js: панель «Диагностика» — индикаторы БД/диска (зелёный/красный) +
лента последних ошибок с цветом по уровню.
Проверено: checks {dbOk,dbPingMs,diskWritable}, список ошибок отдаётся.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -388,6 +388,30 @@
|
||||
</div></div>`;
|
||||
}
|
||||
|
||||
// ── панель диагностики (Level 4): health-чеки + последние ошибки ──
|
||||
let diagHtml = '';
|
||||
{
|
||||
const ch = h.checks || {};
|
||||
const okCol = '#4ade80', badCol = 'var(--pink)';
|
||||
const chip = (label, ok, extra) => `<div style="display:flex;align-items:center;gap:6px;font-size:.82rem"><span style="width:9px;height:9px;border-radius:50%;background:${ok?okCol:badCol}"></span>${label}${extra?` <span style="color:var(--text-3)">${extra}</span>`:''}</div>`;
|
||||
const errs = h.recentErrorList || [];
|
||||
const lvlCol = l => l==='error'||l==='fatal'?'var(--pink)':l==='warn'?'#facc15':'var(--text-3)';
|
||||
diagHtml = `<div class="adm-panel" style="margin:14px 0 0">
|
||||
<div class="adm-panel-title">Диагностика</div>
|
||||
<div style="display:flex;gap:20px;flex-wrap:wrap;margin:6px 0 14px">
|
||||
${chip('База данных', !!ch.dbOk, ch.dbPingMs!=null?ch.dbPingMs.toFixed(2)+' мс':'')}
|
||||
${chip('Запись на диск', !!ch.diskWritable, ch.diskWritable?'доступна':'НЕДОСТУПНА')}
|
||||
</div>
|
||||
<div style="font-size:.72rem;color:var(--text-3);font-weight:700;text-transform:uppercase;margin-bottom:5px">Последние ошибки</div>
|
||||
${errs.length ? errs.map(e=>`<div style="display:flex;align-items:baseline;gap:8px;font-size:.78rem;padding:3px 0;border-bottom:1px solid rgba(255,255,255,.04)">
|
||||
<span style="color:var(--text-3);white-space:nowrap;font-size:.72rem">${esc((e.created_at||'').replace('T',' ').slice(5,16))}</span>
|
||||
<span style="color:${lvlCol(e.level)};font-weight:700;white-space:nowrap">${esc(e.level||'')}</span>
|
||||
${e.route?`<span style="color:var(--text-3);white-space:nowrap">${esc(e.method||'')} ${esc(e.route)}</span>`:''}
|
||||
<span style="flex:1;color:var(--text-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${esc(e.message||'')}</span>
|
||||
</div>`).join('') : `<div style="color:var(--green);font-size:.82rem">Ошибок нет</div>`}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
el.innerHTML = `
|
||||
<div class="adm-panel" style="margin:0 0 16px;padding:14px 18px;display:flex;align-items:center;gap:14px;border-left:4px solid ${stColor}">
|
||||
<div style="width:13px;height:13px;border-radius:50%;background:${stColor};box-shadow:0 0 12px ${stColor};flex-shrink:0"></div>
|
||||
@@ -440,6 +464,8 @@
|
||||
|
||||
${trendsHtml}
|
||||
|
||||
${diagHtml}
|
||||
|
||||
<div class="adm-panel" style="margin:14px 0 0">
|
||||
<div class="adm-panel-title">Крупнейшие таблицы БД</div>
|
||||
${(h.db.tables||[]).map(t=>`<div style="display:flex;align-items:center;gap:10px;margin:4px 0">
|
||||
|
||||
Reference in New Issue
Block a user