ZaStoGram/Tools/check_app_log_cleanup.py
2026-07-20 20:10:42 +03:00

119 lines
4 KiB
Python

#!/usr/bin/env python3
from pathlib import Path
import sys
ROOT = Path(__file__).resolve().parents[1]
FILE_LOG = ROOT / "TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java"
APPLICATION_LOADER = ROOT / "TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java"
NATIVE_FILE_LOG_CPP = ROOT / "TMessagesProj/jni/tgnet/FileLog.cpp"
NATIVE_FILE_LOG_H = ROOT / "TMessagesProj/jni/tgnet/FileLog.h"
def read(path: Path) -> str:
return path.read_text(encoding="utf-8", errors="replace")
def require(condition: bool, message: str, failures: list[str]) -> None:
if not condition:
failures.append(message)
def extract_method(text: str, signature: str) -> str:
start = text.find(signature)
if start < 0:
return ""
brace = text.find("{", start)
if brace < 0:
return ""
depth = 0
for index in range(brace, len(text)):
char = text[index]
if char == "{":
depth += 1
elif char == "}":
depth -= 1
if depth == 0:
return text[start:index + 1]
return ""
def main() -> int:
failures: list[str] = []
file_log = read(FILE_LOG)
application_loader = read(APPLICATION_LOADER)
on_create = extract_method(application_loader, "public void onCreate()")
cleanup_logs = extract_method(file_log, "public static void cleanupLogs()")
require(cleanup_logs, "FileLog.cleanupLogs() must exist", failures)
require(on_create, "ApplicationLoader.onCreate() must exist", failures)
require(
"FileLog.cleanupLogs();" in on_create,
"ApplicationLoader.onCreate() must prune app log files on every process start",
failures,
)
if "FileLog.cleanupLogs();" in on_create and 'FileLog.d("app start time' in on_create:
require(
on_create.index("FileLog.cleanupLogs();") < on_create.index('FileLog.d("app start time'),
"app log cleanup must happen before the first FileLog.d() creates fresh session files",
failures,
)
require(
"ensureInitied();" not in cleanup_logs,
"cleanupLogs() must not initialize FileLog before pruning stale files",
failures,
)
require(
"pruneOldLogs(getMaxLogFiles());" in cleanup_logs,
"cleanupLogs() must retain recent sessions through the bounded log pruner",
failures,
)
require(
".delete()" not in cleanup_logs,
"startup cleanup must not erase the previous crash session",
failures,
)
require(
"getCurrentLogFile()" in file_log and "f.getName().startsWith(prefix)" in file_log,
"bounded pruning must preserve every file in the current log session",
failures,
)
native_log_cpp = read(NATIVE_FILE_LOG_CPP)
native_log_h = read(NATIVE_FILE_LOG_H)
require(
"MAX_NATIVE_LOG_BYTES" in native_log_cpp
and "rotateNativeLogIfNeededLocked" in native_log_cpp
and "rotateNativeLogIfNeededLocked" in native_log_h,
"native _net log must stay size-capped with ring rotation",
failures,
)
require(
"NATIVE_LOG_FLUSH_INTERVAL_MS" in native_log_cpp
and "androidPriority >= ANDROID_LOG_ERROR" in native_log_cpp
and "lastFlushMs" in native_log_h,
"native log must flush errors immediately but batch debug flushes "
"(per-line fflush turned reconnect storms into a syscall-per-line firehose)",
failures,
)
write_locked = extract_method(file_log, "private static synchronized void writeLogLineLocked")
require(
write_locked != ""
and "lastStreamFlushMs" in write_locked
and '"E".equals(level)' in write_locked,
"Java FileLog must flush errors immediately but batch debug flushes",
failures,
)
if failures:
print("app log cleanup guard failed:", file=sys.stderr)
for failure in failures:
print(f" - {failure}", file=sys.stderr)
return 1
print("app log cleanup guard passed.")
return 0
if __name__ == "__main__":
raise SystemExit(main())