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_ID: str | None = None
|
||||||
_SESSION_STARTED: bool = False
|
_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:
|
def audit_log_dir() -> Path:
|
||||||
"""Return the directory where audit logs are written.
|
"""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
|
Failures are swallowed silently — a broken audit log must not
|
||||||
take the GUI down.
|
take the GUI down.
|
||||||
"""
|
"""
|
||||||
|
if _DISABLED:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
event = {
|
event = {
|
||||||
"ts": datetime.now(tz=timezone.utc).isoformat(timespec="milliseconds"),
|
"ts": datetime.now(tz=timezone.utc).isoformat(timespec="milliseconds"),
|
||||||
@@ -172,6 +183,8 @@ def log_event(
|
|||||||
|
|
||||||
def log_session_start() -> None:
|
def log_session_start() -> None:
|
||||||
"""Write the session-start banner. Idempotent within one process."""
|
"""Write the session-start banner. Idempotent within one process."""
|
||||||
|
if _DISABLED:
|
||||||
|
return
|
||||||
global _SESSION_STARTED
|
global _SESSION_STARTED
|
||||||
with _LOCK:
|
with _LOCK:
|
||||||
if _SESSION_STARTED:
|
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-
|
Whole body is wrapped in try/except — the audit log is best-
|
||||||
effort and MUST NOT crash the page that called it.
|
effort and MUST NOT crash the page that called it.
|
||||||
"""
|
"""
|
||||||
|
if _DISABLED:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
import streamlit as st
|
import streamlit as st
|
||||||
|
|||||||
Reference in New Issue
Block a user