[eric] diagnostics: every envelope names the machine that wrote it (OS, version, chip, cores, memory), the fleet is not one M-series Mac

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ciregenz
2026-09-06 17:58:24 -07:00
co-authored by Claude Fable 5.1
parent 5f0ea16c68
commit 2bc9d4eeb9
3 changed files with 71 additions and 0 deletions
+2
View File
@@ -30,6 +30,7 @@ from uuid import uuid4
import httpx
from backend.apps.service import buffer
from backend.apps.service.machine_facts import machine_facts
from backend.apps.service.version import APP_VERSION
logger = logging.getLogger(__name__)
@@ -402,6 +403,7 @@ def submit_diagnostic(diagnostic: dict) -> None:
return
# The build that wrote an envelope is the first thing a field read needs, and it used to be inferred from which fields were present.
diagnostic.setdefault("app_version", APP_VERSION)
diagnostic.setdefault("machine", machine_facts())
try:
from backend.apps.service.ring_buffer import snapshot
diagnostic["recent_log"] = snapshot()
+55
View File
@@ -0,0 +1,55 @@
"""Which kind of machine wrote a diagnostic: OS, chip, cores, memory. Every field report used to come
from "a Mac", and every timing verdict from one developer's M-series; the fleet spans a 2017 iMac and
Windows laptops nobody has measured, so the envelope says what it ran on."""
from __future__ import annotations
import ctypes
import functools
import os
import platform
import sys
def p_memory_bytes() -> int | None:
if sys.platform == "win32":
class MemoryStatus(ctypes.Structure):
_fields_ = [
("dwLength", ctypes.c_ulong),
("dwMemoryLoad", ctypes.c_ulong),
("ullTotalPhys", ctypes.c_ulonglong),
("ullAvailPhys", ctypes.c_ulonglong),
("ullTotalPageFile", ctypes.c_ulonglong),
("ullAvailPageFile", ctypes.c_ulonglong),
("ullTotalVirtual", ctypes.c_ulonglong),
("ullAvailVirtual", ctypes.c_ulonglong),
("ullAvailExtendedVirtual", ctypes.c_ulonglong),
]
status = MemoryStatus()
status.dwLength = ctypes.sizeof(MemoryStatus)
kernel32 = ctypes.windll.kernel32 # type: ignore[attr-defined]
return int(status.ullTotalPhys) if kernel32.GlobalMemoryStatusEx(ctypes.byref(status)) else None
try:
return int(os.sysconf("SC_PAGE_SIZE") * os.sysconf("SC_PHYS_PAGES"))
except (ValueError, OSError, AttributeError):
return None
def p_os_version() -> str:
# Darwin's kernel number (25.6.0) means nothing to a reader; the marketing version does.
if sys.platform == "darwin":
return platform.mac_ver()[0] or platform.release()
if sys.platform == "win32":
return platform.version()
return platform.release()
@functools.lru_cache(maxsize=1)
def machine_facts() -> dict[str, object]:
memory = p_memory_bytes()
return {
"os": platform.system(),
"os_version": p_os_version(),
"arch": platform.machine(),
"cpus": os.cpu_count() or 0,
"memory_gb": round(memory / 1024**3, 1) if memory else None,
}
+14
View File
@@ -224,6 +224,20 @@ def test_every_diagnostic_carries_the_app_version(sink):
assert APP_VERSION and APP_VERSION != "unknown"
def test_every_diagnostic_says_which_machine_wrote_it(sink):
# Every timing verdict came from one developer's M-series Mac; a field envelope now names its own OS, chip, cores and memory.
import platform
from backend.apps.service.client import submit_diagnostic
submit_diagnostic({"kind": "model_error"})
_, body = sink[0]
machine = body["d"]["diagnostic"]["machine"]
assert machine["os"] == platform.system()
assert machine["arch"] == platform.machine()
assert machine["cpus"] >= 1
assert machine["memory_gb"] > 0
assert machine["os_version"]
# --- spool -------------------------------------------------------------------
def test_buffer_enqueue_and_drain(tmp_path):