feat: API request/response logging with admin log viewer

- Add api_logs table (migration 0007) and ApiLog model
- Add web/lib/api_logger.py — httpx wrapper that records every outbound call
- Wire api_logger into vk_sync, vk_catalog, and connections test endpoints
- Add /admin/logs page with filters (service, method, status, time range, URL search) and expandable request/response detail
- Add "Логи" nav link for admin users

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mguschin
2026-05-12 22:00:14 +03:00
parent cad0b10fbb
commit 9960d760a0
10 changed files with 392 additions and 21 deletions

View File

@@ -3,6 +3,7 @@ from datetime import datetime, timedelta, timezone
from urllib.parse import urlencode
import httpx
import web.lib.api_logger as api_logger
from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
from sqlalchemy.orm import Session
@@ -306,8 +307,9 @@ async def connections_evotor_test(request: Request, db: Session = Depends(get_db
return JSONResponse({"ok": False, "message": "Подключение не настроено"})
try:
r = httpx.get(
r = api_logger.get(
"https://api.evotor.ru/stores",
user_id=user.id,
headers={
"Authorization": f"Bearer {conn.access_token}",
"Accept": "application/vnd.evotor.v2+json",
@@ -344,8 +346,9 @@ async def connections_vk_test(request: Request, db: Session = Depends(get_db)):
if not conn.vk_user_id:
return JSONResponse({"ok": False, "message": "Укажите ID сообщества для проверки подключения."})
r = httpx.get(
r = api_logger.get(
"https://api.vk.com/method/groups.getById",
user_id=user.id,
params={
"group_id": conn.vk_user_id,
"fields": "market",