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 sqlalchemy import (
Numeric, String, Text, UniqueConstraint, func,
)
from web.database import Base
@@ -175,3 +176,23 @@ class CachedProduct(Base):
UniqueConstraint("user_id", "evotor_id", name="uq_cached_products_user_evotor"),
Index("ix_cached_products_user_store_group", "user_id", "store_evotor_id", "group_evotor_id"),
)
class ApiLog(Base):
__tablename__ = "api_logs"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
service = Column(String(20), nullable=False) # "evotor" | "vk"
method = Column(String(10), nullable=False) # "GET" | "POST"
url = Column(String(1024), nullable=False)
request_body = Column(Text, nullable=True)
response_status = Column(Integer, nullable=True)
response_body = Column(Text, nullable=True)
duration_ms = Column(Integer, nullable=True)
created_at = Column(DateTime, nullable=False, server_default=func.now())
__table_args__ = (
Index("ix_api_logs_user_service", "user_id", "service"),
Index("ix_api_logs_created_at", "created_at"),
)