feat: periodically checkpoint server/sud logs to disk
Both loggers previously only wrote their JSON log on their end trigger (shutdown / Stop-or-DONE), losing the whole session/run's data on a hard crash or power loss. Add a log_interval (config.json, default 300s) that rewrites the same file whole every N seconds in between. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TvgC7oy9MxaA4ZQxXqkNdS
This commit is contained in:
+10
-1
@@ -16,7 +16,7 @@ class ServerLogTask(ATask):
|
||||
Sud state — useful for verifying controller and heater behaviour
|
||||
outside of a scheduled brew."""
|
||||
|
||||
def __init__(self, tc: APid, heater: AHeater, heater_task, interval, path='./logs', config=None, dt=None):
|
||||
def __init__(self, tc: APid, heater: AHeater, heater_task, interval, path='./logs', config=None, dt=None, log_interval=None):
|
||||
ATask.__init__(self, interval)
|
||||
self.tc = tc
|
||||
self.heater = heater
|
||||
@@ -24,10 +24,12 @@ class ServerLogTask(ATask):
|
||||
self.path = path
|
||||
self.config = config
|
||||
self.dt = dt
|
||||
self.log_interval = log_interval
|
||||
self._samples = []
|
||||
self._param_events = []
|
||||
self._t0 = time.monotonic()
|
||||
self._run_id = time.strftime("%Y%m%dT%H%M%S", time.localtime())
|
||||
self._last_write = self._t0
|
||||
|
||||
def log_plant_params(self, elapsed, params):
|
||||
self._param_events.append({'t': time.monotonic() - self._t0, 'params': params})
|
||||
@@ -36,6 +38,13 @@ class ServerLogTask(ATask):
|
||||
while True:
|
||||
if self._should_sample():
|
||||
self._samples.append(self._take_sample())
|
||||
# Periodically checkpoints to disk (same file, overwritten whole
|
||||
# each time - see write()) so a hard crash/power loss only loses
|
||||
# up to log_interval seconds, not the whole session/run.
|
||||
now = time.monotonic()
|
||||
if self.log_interval and now - self._last_write >= self.log_interval:
|
||||
self.write()
|
||||
self._last_write = now
|
||||
await asyncio.sleep(self.interval)
|
||||
|
||||
def _should_sample(self):
|
||||
|
||||
+3
-2
@@ -14,8 +14,8 @@ class SudLogTask(ServerLogTask):
|
||||
logs/log_{date_time}_{sud_name}.log. A Pause/resume doesn't start a new
|
||||
file - only a fresh Play (from IDLE/DONE) does."""
|
||||
|
||||
def __init__(self, tc: APid, heater: AHeater, heater_task, sud, interval, path='./logs', config=None, dt=None):
|
||||
ServerLogTask.__init__(self, tc, heater, heater_task, interval, path, config, dt)
|
||||
def __init__(self, tc: APid, heater: AHeater, heater_task, sud, interval, path='./logs', config=None, dt=None, log_interval=None):
|
||||
ServerLogTask.__init__(self, tc, heater, heater_task, interval, path, config, dt, log_interval)
|
||||
self.sud = sud
|
||||
self._active = False
|
||||
|
||||
@@ -31,6 +31,7 @@ class SudLogTask(ServerLogTask):
|
||||
return
|
||||
self._samples = []
|
||||
self._t0 = time.monotonic()
|
||||
self._last_write = self._t0
|
||||
self._run_id = time.strftime("%Y%m%dT%H%M%S", time.localtime())
|
||||
self._active = True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user