bisect: kill-switch every audit-log write
Reported: bisection commitc0bfd4dthat disabled the sticky footer, diagnostics sidebar, and compact-CSS didn't fix the blank-page symptom. User adds that Ctrl+C also can't kill the launcher. Ctrl+C-doesn't-work + every-page-blank together points at a hang in the Python process, not an exception. The most likely hang point in the chrome path is the audit log's file I/O — ``open()`` inside the ``with`` block in ``log_event`` blocks on a stuck filesystem (Windows antivirus quarantining ``~/.datatools/logs/datatools-*.jsonl`` on every write is a plausible culprit on the user's machine). A blocking ``open`` call does NOT raise — try/except can't recover from it — which is why our prior defensive wrap didn't help. Add a module-level ``_DISABLED = True`` kill switch. ``log_event``, ``log_session_start``, and ``log_page_open`` each early-return at the very top of the function when the flag is set, before any file-system call. Path resolution (``audit_log_path``) still works since it's needed for the diagnostics sidebar (still disabled inc0bfd4d, but kept harmless). If pages render after this commit, file I/O from the audit log is confirmed as the culprit; we'll redesign with an async writer queue and a tighter timeout. If they still don't, the cause is somewhere we haven't bisected yet and we move to a hard revert. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
15
src/audit.py
15
src/audit.py
@@ -57,6 +57,15 @@ _LOG_PATH: Path | None = None
|
||||
_SESSION_ID: str | None = None
|
||||
_SESSION_STARTED: bool = False
|
||||
|
||||
# Kill switch — when True, every log_* function is a no-op. Set to
|
||||
# True while bisecting a "blank pages" report where ``open()`` inside
|
||||
# the log writer was suspected of blocking on the user's filesystem
|
||||
# (Windows + antivirus + ``~/.datatools/logs/``). A blocking ``open``
|
||||
# call doesn't raise so try/except can't recover it; the only safe
|
||||
# bisect is "don't touch the disk at all." Toggle back to False once
|
||||
# the user confirms pages render.
|
||||
_DISABLED: bool = True
|
||||
|
||||
|
||||
def audit_log_dir() -> Path:
|
||||
"""Return the directory where audit logs are written.
|
||||
@@ -147,6 +156,8 @@ def log_event(
|
||||
Failures are swallowed silently — a broken audit log must not
|
||||
take the GUI down.
|
||||
"""
|
||||
if _DISABLED:
|
||||
return
|
||||
try:
|
||||
event = {
|
||||
"ts": datetime.now(tz=timezone.utc).isoformat(timespec="milliseconds"),
|
||||
@@ -172,6 +183,8 @@ def log_event(
|
||||
|
||||
def log_session_start() -> None:
|
||||
"""Write the session-start banner. Idempotent within one process."""
|
||||
if _DISABLED:
|
||||
return
|
||||
global _SESSION_STARTED
|
||||
with _LOCK:
|
||||
if _SESSION_STARTED:
|
||||
@@ -222,6 +235,8 @@ def log_page_open(slug: str) -> None:
|
||||
Whole body is wrapped in try/except — the audit log is best-
|
||||
effort and MUST NOT crash the page that called it.
|
||||
"""
|
||||
if _DISABLED:
|
||||
return
|
||||
try:
|
||||
try:
|
||||
import streamlit as st
|
||||
|
||||
Reference in New Issue
Block a user