v1.0.79: file-based log (/tmp/app-autotest.log) for multi-worker gunicorn

This commit is contained in:
2026-07-27 13:57:10 +04:00
parent 07aa2115d4
commit 7d2021a1e4
2 changed files with 37 additions and 8 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ from routes.main import bp as main_bp
from routes.api import bp as api_bp
from routes.api_test import bp as api_test_bp
VERSION = "1.0.78"
VERSION = "1.0.79"
app = Flask(__name__, template_folder="templates", static_folder="static")
app.config["NUBES_API_ENDPOINT"] = os.getenv("NUBES_API_ENDPOINT", "https://lk-api-gateway-dev.ngcloud.ru/api/v1/svc")
+36 -7
View File
@@ -1,6 +1,7 @@
from flask import Blueprint, current_app, jsonify, request
import uuid
import collections
import os
import fcntl
from api.http_client import HttpClient, detect_endpoint
from operations.get_services import get_services, get_service_detail
@@ -12,14 +13,33 @@ bp = Blueprint("api_test", __name__)
AUTOTEST_PREFIX = "autotest-"
# Кольцевой буфер логов (показываются в UI)
_log_lines = collections.deque(maxlen=200)
LOG_FILE = "/tmp/app-autotest.log"
MAX_LOG_SIZE = 512 * 1024 # 512 KB — ротация
MAX_LOG_LINES = 200 # сколько отдавать в /api/log
def _log(msg):
"""Пишет и в stdout (для gunicorn), и в буфер (для UI)."""
"""Пишет в stdout (gunicorn) и в файл (UI-панель, общий для всех воркеров)."""
print(msg, flush=True)
_log_lines.append(msg)
try:
with open(LOG_FILE, "a") as f:
fcntl.flock(f, fcntl.LOCK_EX)
f.write(msg + "\n")
fcntl.flock(f, fcntl.LOCK_UN)
# Ротация если разросся
st = os.stat(LOG_FILE)
if st.st_size > MAX_LOG_SIZE:
with open(LOG_FILE, "r+") as f:
fcntl.flock(f, fcntl.LOCK_EX)
f.seek(st.st_size // 2)
f.readline() # доесть строку
rest = f.read()
f.seek(0)
f.truncate()
f.write(rest)
fcntl.flock(f, fcntl.LOCK_UN)
except Exception:
pass # молча — не ронять запрос из-за лога
def _with_prefix(name):
@@ -338,8 +358,17 @@ def api_test_status(op_uid):
@bp.route("/api/log")
def api_log():
"""Отдать последние строки лога для UI-панели."""
return jsonify(list(_log_lines))
"""Отдать последние MAX_LOG_LINES строк лога для UI-панели."""
try:
with open(LOG_FILE, "r") as f:
fcntl.flock(f, fcntl.LOCK_SH)
lines = f.readlines()
fcntl.flock(f, fcntl.LOCK_UN)
return jsonify([l.rstrip("\n") for l in lines[-MAX_LOG_LINES:]])
except FileNotFoundError:
return jsonify([])
except Exception:
return jsonify([])
def _find_uid(resp):