| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- """Bug report endpoint for submitting user bug reports to GitHub."""
- import asyncio
- import logging
- from fastapi import APIRouter
- from pydantic import BaseModel
- from backend.app.api.routes.support import (
- _apply_log_level,
- _collect_support_info,
- _get_debug_setting,
- _get_recent_sanitized_logs,
- _set_debug_setting,
- )
- from backend.app.core.database import async_session
- from backend.app.services.bug_report import submit_report
- from backend.app.services.printer_manager import printer_manager
- router = APIRouter(prefix="/bug-report", tags=["bug-report"])
- logger = logging.getLogger(__name__)
- LOG_COLLECTION_SECONDS = 30
- class BugReportRequest(BaseModel):
- description: str
- email: str | None = None
- screenshot_base64: str | None = None
- include_support_info: bool = True
- class BugReportResponse(BaseModel):
- success: bool
- message: str
- issue_url: str | None = None
- issue_number: int | None = None
- async def _collect_debug_logs() -> str:
- """Enable debug logging, push all printers, wait, then collect logs."""
- # Check if debug was already enabled
- async with async_session() as db:
- was_debug, _ = await _get_debug_setting(db)
- # Enable debug logging
- if not was_debug:
- async with async_session() as db:
- await _set_debug_setting(db, True)
- _apply_log_level(True)
- logger.info("Bug report: temporarily enabled debug logging")
- # Send push_all to all connected printers
- for printer_id in list(printer_manager._clients.keys()):
- try:
- printer_manager.request_status_update(printer_id)
- except Exception:
- logger.debug("Failed to push_all for printer %s", printer_id)
- # Wait for logs to accumulate
- await asyncio.sleep(LOG_COLLECTION_SECONDS)
- # Collect logs
- logs = await _get_recent_sanitized_logs()
- # Restore previous log level if it wasn't debug before
- if not was_debug:
- async with async_session() as db:
- await _set_debug_setting(db, False)
- _apply_log_level(False)
- logger.info("Bug report: restored normal logging")
- return logs
- @router.post("/submit", response_model=BugReportResponse)
- async def submit_bug_report(report: BugReportRequest):
- """Submit a bug report. No auth required — anyone should be able to report bugs."""
- support_info = None
- if report.include_support_info:
- try:
- support_info = await _collect_support_info()
- logs = await _collect_debug_logs()
- if logs:
- support_info["recent_logs"] = logs
- except Exception:
- logger.exception("Failed to collect support info for bug report")
- result = await submit_report(
- description=report.description,
- reporter_email=report.email,
- screenshot_base64=report.screenshot_base64,
- support_info=support_info,
- )
- return BugReportResponse(**result)
|