""" app_devlog.py — endpoint /devlog для удалённого сбора логов dev-сессии студии. Подключается к Flask из app.py через blueprint. Эндпоинты: POST /devlog — приём batch'а событий из браузера GET /devlog/recent — последние N событий (для меня) GET /devlog/clear — очистить лог Хранение: append-only файл /opt/rbxl-importer/devlog.jsonl. CORS открыт для localhost:* (dev режим). """ import os import json import time from flask import Blueprint, request, jsonify devlog_bp = Blueprint('devlog', __name__) DEVLOG_PATH = os.environ.get('DEVLOG_PATH', '/opt/rbxl-importer/devlog.jsonl') @devlog_bp.post('/devlog') def post_devlog(): """Принимает массив событий из браузера. Каждое событие: {ts, kind, url?, status?, body?, message?, stack?, extra?} """ data = request.get_json(silent=True) or {} events = data.get('events') or [] if not isinstance(events, list): return jsonify({'error': 'events must be list'}), 400 received_at = time.time() with open(DEVLOG_PATH, 'a', encoding='utf-8') as f: for ev in events: if not isinstance(ev, dict): continue ev['received_at'] = received_at f.write(json.dumps(ev, ensure_ascii=False, default=str) + '\n') return jsonify({'ok': True, 'count': len(events)}) @devlog_bp.get('/devlog/recent') def get_recent(): """Последние N событий (по умолчанию 200).""" n = int(request.args.get('n', 200)) out = [] if os.path.exists(DEVLOG_PATH): with open(DEVLOG_PATH, 'r', encoding='utf-8') as f: lines = f.readlines()[-n:] for line in lines: try: out.append(json.loads(line)) except Exception: pass return jsonify({'events': out, 'total': len(out)}) @devlog_bp.get('/devlog/clear') def clear(): if os.path.exists(DEVLOG_PATH): os.unlink(DEVLOG_PATH) return jsonify({'ok': True})