diff --git a/app.py b/app.py index 367477a..721b1e0 100644 --- a/app.py +++ b/app.py @@ -818,8 +818,10 @@ def change_password(): @app.route("/") @login_required def dashboard(): - stats = get_stats() + # Trigger auto-sync first (get_parsed_logs checks _should_auto_sync), + # then compute stats from the now-fresh SQLite data. entries = get_parsed_logs() + stats = get_stats() cfg = get_all_config() # P1-2: surface any active alert rules at the top of the dashboard so # operators see them without having to navigate to /alerts. @@ -1060,10 +1062,14 @@ def logs_import(): @app.route("/logs/live") @login_required def logs_live(): - """Live tail view (auto-refresh).""" + """Live tail view (auto-refresh). Reads directly from file for real-time.""" cfg = get_all_config() n = int(cfg.get("live_tail_lines", 100)) - entries = get_parsed_logs(force=False)[-n:] + # Read directly from file - bypass SQLite cache for true real-time + limit = max(n * 3, 500) + text = read_access_log_tail(max_lines=limit) + entries = log_parser.parse_lines(text) + entries = entries[-n:] entries = list(reversed(entries)) return render_template("logs_live.html", entries=entries, cfg=cfg, n=n, @@ -1264,7 +1270,7 @@ def config_acls(): type=types[i] if i < len(types) else "src", values=vals, comment=cmnt)) struct["acls"] = new_acls - content_preview = msg if ok else "" + ok, msg, content_preview = save_struct(struct) if not ok: flash(msg, "error") return redirect(url_for("config_acls")) @@ -1314,7 +1320,7 @@ def config_rules(): idx = int(request.form.get("index", "-1")) if 0 <= idx < len(struct["rules"]): del struct["rules"][idx] - content_preview = msg if ok else "" + ok, msg, content_preview = save_struct(struct) if not ok: flash(msg, "error") return redirect(url_for("config_rules")) @@ -1364,7 +1370,7 @@ def config_cache(): idx = int(request.form.get("index", "-1")) if 0 <= idx < len(struct["cache_dirs"]): del struct["cache_dirs"][idx] - content_preview = msg if ok else "" + ok, msg, content_preview = save_struct(struct) if not ok: flash(msg, "error") return redirect(url_for("config_cache")) @@ -1415,7 +1421,7 @@ def config_refresh(): idx = int(request.form.get("index", "-1")) if 0 <= idx < len(struct["refresh_patterns"]): del struct["refresh_patterns"][idx] - content_preview = msg if ok else "" + ok, msg, content_preview = save_struct(struct) if not ok: flash(msg, "error") return redirect(url_for("config_refresh")) @@ -1468,7 +1474,7 @@ def config_auth(): idx = int(request.form.get("index", "-1")) if 0 <= idx < len(struct["auth_params"]): del struct["auth_params"][idx] - content_preview = msg if ok else "" + ok, msg, content_preview = save_struct(struct) if not ok: flash(msg, "error") return redirect(url_for("config_auth")) @@ -1521,7 +1527,7 @@ def config_peers(): idx = int(request.form.get("index", "-1")) if 0 <= idx < len(struct["cache_peers"]): del struct["cache_peers"][idx] - content_preview = msg if ok else "" + ok, msg, content_preview = save_struct(struct) if not ok: flash(msg, "error") return redirect(url_for("config_peers"))