docs: update README logging section for logging-module migration

The write-up still described the old print()-mirroring behavior;
recent commits (a1864a5..9f262c4) routed task/component output through
self.log (stdlib logging) instead, added Sud lifecycle/connect-state
log lines, and gave SudForecastEstimator its own silenced logger.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F4oEE99rkKVU8L8tkzXWdG
This commit is contained in:
2026-07-11 12:10:34 +02:00
co-authored by Claude Sonnet 5
parent 9f262c48d0
commit af4e7ea471
+21 -4
View File
@@ -771,10 +771,27 @@ session - don't assume they're a matched pair unless you've just watched a
run finish (`log_latest_sud.json` is only ever current *immediately* after
a `Stop`/`DONE`).
`server/brewpi.py` also mirrors everything it prints (every component's
`print()`-based status/debug output) to a plain text log,
`logs/brewpi.<timestamp>.log`, alongside those JSON logs - useful for
post-mortems without needing to have been watching the console live.
`server/brewpi.py` also mirrors console output to a plain text log,
`logs/brewpi.<timestamp>.log` (plus an always-truncated `logs/brewpi.latest.log`
for tail-style consumers), alongside those JSON logs - useful for post-mortems
without needing to have been watching the console live. Every task/component
logs through the stdlib `logging` module rather than `print()`: `AttributeChange`
(`utils/value.py`, the common base of every `ATask` and component ABC) gives
each one a `self.log = logging.getLogger(type(self).__name__)`, so messages
are automatically tagged with the component's class name with no hand-typing
needed. `server/brewpi.py`'s `Tee` class mirrors `stdout`/`stderr` to both log
files and stamps each line with a `<date>T<time>:` prefix; `logging.basicConfig()`
uses a bare `%(name)s:%(message)s` formatter, so the combined line reads
`<date>T<time>:<component>:<message>` without double-stamping (and third-party
loggers like `websockets`/`asyncio` get the same formatting for free).
`components/sud.py`'s `Sud` logs its own lifecycle (load/start/pause/continue/
stop, each step's `"<descr>(<number>) Heating"`/`"Reached"` transitions,
waiting for user interaction, finished), and `HeaterTask`/`StirrerTask` log
connected/disconnected state. `SudForecastEstimator` drives its own throwaway
`Sud` through an entire schedule with no real waiting to predict duration, so
it's given its own `"SudForecastEstimator"` logger (silenced to `WARNING` by
default in `components/sud_forecast.py`) rather than sharing `Sud`'s, keeping
an instant internal forecast run out of the log next to actual brew activity.
Both JSON logs also carry `dt`, the effective `SimWarpFactor` (already
clamped to `1.0` for real hardware - see above), `Config` (the whole