| """Gameplay trace log — console + logs/trace.log. |
| |
| Tags: flow (game events), llm (transport: live/mock/timing), ai (full model |
| payloads), vald (validation rejects with reason), econ (guardrails/economy). |
| """ |
| from __future__ import annotations |
|
|
| import json |
| import logging |
| import pathlib |
|
|
| LOG_PATH = pathlib.Path(__file__).resolve().parent.parent / "logs" / "trace.log" |
|
|
| logger = logging.getLogger("bds") |
| if not logger.handlers: |
| logger.setLevel(logging.INFO) |
| logger.propagate = False |
| fmt = logging.Formatter("%(asctime)s %(message)s", datefmt="%H:%M:%S") |
| stream = logging.StreamHandler() |
| stream.setFormatter(fmt) |
| logger.addHandler(stream) |
| |
| |
| try: |
| LOG_PATH.parent.mkdir(exist_ok=True) |
| filehandler = logging.FileHandler(LOG_PATH, encoding="utf-8") |
| filehandler.setFormatter(fmt) |
| logger.addHandler(filehandler) |
| except OSError: |
| pass |
|
|
|
|
| def trace(tag: str, msg: str) -> None: |
| logger.info(f"[{tag:<4}] {msg}") |
|
|
|
|
| def trace_payload(payload: dict) -> None: |
| try: |
| trace("ai", json.dumps(payload, ensure_ascii=False)) |
| except (TypeError, ValueError): |
| trace("ai", repr(payload)[:800]) |
|
|