log: route task/component status output through logging, not print()
AttributeChange (the common base of every ATask and component ABC) now sets self.log = logging.getLogger(type(self).__name__), so components no longer need to hand-type their own name into each message. Wired logging.basicConfig() in server/brewpi.py with a bare "%(name)s: %(message)s" formatter - Tee (see prior commit) still supplies the "<date>T<time>:" prefix, so lines read "<date>T<time>:<component>: <message>" without double-stamping, and third-party loggers (websockets, asyncio) now get the same formatting for free. Converted the print() call sites that were standing in for this in tasks/ and components/ (leaving __main__ demo blocks and explicit debug-dump helpers alone).
This commit is contained in:
+22
-14
@@ -2,6 +2,7 @@
|
||||
import asyncio
|
||||
import functools
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
@@ -20,20 +21,23 @@ from tasks import TaskManager, TempSensorTask, HeaterTask, PotTask, TcTask, Stir
|
||||
|
||||
import argparse as ap
|
||||
|
||||
log = logging.getLogger('brewpi')
|
||||
|
||||
|
||||
class Tee:
|
||||
"""Duplicates writes to multiple streams - used to mirror stdout/stderr
|
||||
(everything the rest of the codebase already reaches via print()) into
|
||||
a log file under logs/ as well as the console, without having to touch
|
||||
every print() call site.
|
||||
into a log file under logs/ as well as the console, without every
|
||||
writer needing to know about either.
|
||||
|
||||
Also stamps every line with a "<date>T<time>:" prefix (existing print()
|
||||
call sites already start their message with "Component: ..." - see e.g.
|
||||
tasks/stirrer.py - so the combined line reads
|
||||
"<date>T<time>:<component>: <message>"), so log entries can be
|
||||
correlated with the JSON sample logs (ServerLogTask/SudLogTask) without
|
||||
relying on journalctl's own timestamps, which aren't present in the
|
||||
mirrored log files themselves."""
|
||||
Also stamps every line with a "<date>T<time>:" prefix. Every task/
|
||||
component logs via logging (see utils/value.py's AttributeChange, which
|
||||
gives self.log to all of them), configured below with a bare
|
||||
"%(name)s:%(message)s" formatter - Tee supplies the timestamp instead,
|
||||
so the combined line reads "<date>T<time>:<component>:<message>" (see
|
||||
logging.basicConfig() call below) without double-stamping. This lets
|
||||
log entries be correlated with the JSON sample logs (ServerLogTask/
|
||||
SudLogTask) without relying on journalctl's own timestamps, which
|
||||
aren't present in the mirrored log files themselves."""
|
||||
|
||||
def __init__(self, *streams):
|
||||
self.streams = streams
|
||||
@@ -92,7 +96,11 @@ if __name__ == '__main__':
|
||||
latest_log_file = open(latest_log_path, "w", buffering=1)
|
||||
sys.stdout = Tee(sys.stdout, log_file, latest_log_file)
|
||||
sys.stderr = Tee(sys.stderr, log_file, latest_log_file)
|
||||
print("Logging to {}".format(log_path))
|
||||
# No "%(asctime)s" here - Tee (above) already stamps every mirrored
|
||||
# line with "<date>T<time>:", so this only contributes the
|
||||
# "<component>:<message>" part (see Tee's own docstring).
|
||||
logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(name)s:%(message)s')
|
||||
log.info("Logging to {}".format(log_path))
|
||||
|
||||
config = json.load(open(args.config))
|
||||
dispatcher = MessageDispatcher()
|
||||
@@ -246,7 +254,7 @@ if __name__ == '__main__':
|
||||
http_handler = functools.partial(SimpleHTTPRequestHandler, directory=web_dir)
|
||||
http_server = ThreadingHTTPServer(("0.0.0.0", args.http_port), http_handler)
|
||||
threading.Thread(target=http_server.serve_forever, daemon=True).start()
|
||||
print("Serving {} on http://0.0.0.0:{}".format(web_dir, args.http_port))
|
||||
log.info("Serving {} on http://0.0.0.0:{}".format(web_dir, args.http_port))
|
||||
|
||||
# systemd's `stop`/`restart` send SIGTERM, whose default disposition is to
|
||||
# kill the process immediately - skipping the finally: block below
|
||||
@@ -259,7 +267,7 @@ if __name__ == '__main__':
|
||||
try:
|
||||
loop.run_forever()
|
||||
except KeyboardInterrupt:
|
||||
print("\nShutting down...")
|
||||
log.info("Shutting down...")
|
||||
finally:
|
||||
# Cancel all tasks so their finally blocks (e.g. HeaterTask's/
|
||||
# StirrerTask's `with device.open()`) get a chance to run before we
|
||||
@@ -278,4 +286,4 @@ if __name__ == '__main__':
|
||||
stirrer.activate(False)
|
||||
http_server.shutdown()
|
||||
loop.close()
|
||||
print("Server stopped.")
|
||||
log.info("Server stopped.")
|
||||
|
||||
Reference in New Issue
Block a user