v1.0.79: file-based log (/tmp/app-autotest.log) for multi-worker gunicorn
This commit is contained in:
+1
-1
@@ -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
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user