feat: страница логов /ui/logs с SSE real-time потоком
- log_buffer: RingBufferHandler, кольцевой буфер 600 записей, fan-out SSE - ui_logs: GET /ui/logs (HTML), GET /ui/logs/stream (EventSource) - main: install_log_handler при старте, подключён router логов - nav_rail: ссылка Логи, root_html: кнопка-ссылка Логи - Исправлено: NaN/Inf/NUL в теле вебхука → 500 от PostgreSQL jsonb - Тесты: test_log_buffer, test_json_sanitize; 51 passed Made-with: Cursor
This commit is contained in:
45
tests/test_log_buffer.py
Normal file
45
tests/test_log_buffer.py
Normal file
@ -0,0 +1,45 @@
|
||||
"""Кольцевой буфер логов и SSE-страница."""
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from onguard24 import log_buffer
|
||||
|
||||
|
||||
def test_ring_buffer_captures_log_records() -> None:
|
||||
log_buffer._ring.clear()
|
||||
handler = log_buffer.RingBufferHandler()
|
||||
handler.setFormatter(logging.Formatter("%(name)s %(message)s"))
|
||||
logger = logging.getLogger("test.ring")
|
||||
logger.addHandler(handler)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
try:
|
||||
logger.info("hello ring")
|
||||
history = log_buffer.get_history()
|
||||
assert any("hello ring" in e["msg"] for e in history)
|
||||
finally:
|
||||
logger.removeHandler(handler)
|
||||
log_buffer._ring.clear()
|
||||
|
||||
|
||||
def test_logs_page_returns_html(client: TestClient) -> None:
|
||||
r = client.get("/ui/logs")
|
||||
assert r.status_code == 200
|
||||
assert "text/html" in r.headers.get("content-type", "")
|
||||
assert "Логи" in r.text
|
||||
assert "log-wrap" in r.text
|
||||
assert "EventSource" in r.text or "event-stream" in r.text or "ui/logs/stream" in r.text
|
||||
|
||||
|
||||
def test_logs_page_in_nav_rail(client: TestClient) -> None:
|
||||
r = client.get("/ui/logs")
|
||||
assert r.status_code == 200
|
||||
assert "/ui/logs" in r.text
|
||||
|
||||
|
||||
def test_root_has_logs_link(client: TestClient) -> None:
|
||||
r = client.get("/")
|
||||
assert r.status_code == 200
|
||||
assert "/ui/logs" in r.text
|
||||
Reference in New Issue
Block a user