"""Log Center integration — runtime error reporting.""" import os import json import traceback import threading from urllib.request import Request, urlopen from urllib.error import URLError LOG_CENTER_URL = os.getenv('LOG_CENTER_URL', 'https://qiyuan-log-center-api.airlabs.art') LOG_CENTER_ENABLED = os.getenv('LOG_CENTER_ENABLED', 'false').lower() in ('true', '1', 'yes') PROJECT_ID = 'video_backend' ENVIRONMENT = os.getenv('ENVIRONMENT', 'development') def report_error(exc, context=None): """Report a runtime error to Log Center (async, non-blocking).""" if not LOG_CENTER_ENABLED: return tb = traceback.extract_tb(exc.__traceback__) last_frame = tb[-1] if tb else None payload = { 'project_id': PROJECT_ID, 'environment': ENVIRONMENT, 'level': 'ERROR', 'error': { 'type': type(exc).__name__, 'message': str(exc), 'file_path': last_frame.filename if last_frame else 'unknown', 'line_number': last_frame.lineno if last_frame else 0, 'stack_trace': ''.join(traceback.format_exception(exc)), }, 'context': context or {}, } # Fire-and-forget in background thread threading.Thread(target=_send, args=(payload,), daemon=True).start() def _send(payload): """Send payload to Log Center API.""" try: data = json.dumps(payload).encode('utf-8') req = Request( f'{LOG_CENTER_URL}/api/v1/logs/report', data=data, headers={'Content-Type': 'application/json'}, method='POST', ) urlopen(req, timeout=3) except (URLError, Exception): pass # Silent failure — never affect main business def custom_exception_handler(exc, context): """DRF custom exception handler with Log Center reporting.""" from rest_framework.views import exception_handler # Report to Log Center request = context.get('request') report_error(exc, { 'view': str(context.get('view', '')), 'request_path': getattr(request, 'path', None), 'request_method': getattr(request, 'method', None), 'user': str(getattr(request, 'user', 'anonymous')), }) # Default DRF handling response = exception_handler(exc, context) return response