feat: клик по модели — лог всех проверок с ошибками
Build and deploy / build-deploy (push) Has been cancelled
Build and deploy / build-deploy (push) Has been cancelled
Кнопка 📋 Лог открывает /api/checks/{model_id} — все проверки модели
за период (по умолчанию 100 последних, limit через CHECKS_LIMIT) с
ok/latency_ms/checked_at/error. Заполняет history для перерисовки.
This commit is contained in:
+25
@@ -536,6 +536,31 @@ def api_check(model_id: str):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/checks/{model_id:path}")
|
||||||
|
def api_checks(model_id: str):
|
||||||
|
"""Все проверки модели за период — для дропдауна с деталями ошибок."""
|
||||||
|
limit = int(os.environ.get("CHECKS_LIMIT", "100"))
|
||||||
|
db = get_db()
|
||||||
|
rows = db.execute(
|
||||||
|
"SELECT ok, latency_ms, checked_at, error FROM checks "
|
||||||
|
"WHERE model_id=? ORDER BY checked_at DESC LIMIT ?",
|
||||||
|
(model_id, limit),
|
||||||
|
).fetchall()
|
||||||
|
db.close()
|
||||||
|
return {
|
||||||
|
"model_id": model_id,
|
||||||
|
"checks": [
|
||||||
|
{
|
||||||
|
"ok": bool(r["ok"]),
|
||||||
|
"latency_ms": r["latency_ms"],
|
||||||
|
"checked_at": r["checked_at"],
|
||||||
|
"error": r["error"],
|
||||||
|
}
|
||||||
|
for r in rows
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/", response_class=HTMLResponse)
|
@app.get("/", response_class=HTMLResponse)
|
||||||
def index():
|
def index():
|
||||||
with open("/app/app/static/index.html") as f:
|
with open("/app/app/static/index.html") as f:
|
||||||
|
|||||||
@@ -363,6 +363,7 @@ function renderRow(m) {
|
|||||||
<td>${statusCell(m.last_ok)}</td>
|
<td>${statusCell(m.last_ok)}</td>
|
||||||
<td>${uptimeCell(m.uptime_pct, m.history)}</td>
|
<td>${uptimeCell(m.uptime_pct, m.history)}</td>
|
||||||
<td><button class="check-btn" onclick="checkOne('${m.id}', this)">▶ Тест</button></td>
|
<td><button class="check-btn" onclick="checkOne('${m.id}', this)">▶ Тест</button></td>
|
||||||
|
<td><button class="check-btn" onclick="openCheckHistory('${m.id}', this)">📋 Лог</button></td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,6 +488,16 @@ async function checkOne(modelId, btn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function openCheckHistory(modelId, btn) {
|
||||||
|
const res = await fetch(`/api/checks/${encodeURIComponent(modelId)}`);
|
||||||
|
const data = await res.json();
|
||||||
|
const idx = allData.findIndex(m => m.id === modelId);
|
||||||
|
if (idx >= 0) {
|
||||||
|
allData[idx].history = (data.checks || []).map(c => ({ ok: c.ok, latency_ms: c.latency_ms, at: c.checked_at, error: c.error }));
|
||||||
|
}
|
||||||
|
applyFilters();
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('btn-refresh').addEventListener('click', loadData);
|
document.getElementById('btn-refresh').addEventListener('click', loadData);
|
||||||
document.getElementById('btn-sync').addEventListener('click', async () => {
|
document.getElementById('btn-sync').addEventListener('click', async () => {
|
||||||
const btn = document.getElementById('btn-sync');
|
const btn = document.getElementById('btn-sync');
|
||||||
|
|||||||
Reference in New Issue
Block a user