From 676312e581bb291a80412b901fea63c9732756ec Mon Sep 17 00:00:00 2001 From: KoenigMjr <135820716+KoenigMjr@users.noreply.github.com> Date: Sun, 13 Jul 2025 14:46:42 +0200 Subject: [PATCH 1/2] feat(logging): dynamische Logdateibenennung basierend auf YAML-Datei MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Logdatei wird nun zur Laufzeit anhand des Konfigurationsdateinamens gesetzt, z. B.: client1.yaml → log/client1.log - Ermöglicht parallele Ausführung mehrerer Clients mit getrennten Logs auf derselben Hardware - Der bisher fest codierte client.log entfällt - Argumente (args.config) werden nun vor dem Logging-Setup geparst - logger_client.ini bleibt erhalten; Pfad des TimedRotatingFileHandler wird nachträglich im Code gesetzt - Log-Rotation (Mitternacht, 7 Backups) funktioniert weiterhin wie konfiguriert - `disable_existing_loggers=False` verhindert das Deaktivieren benutzerdefinierter Logger in den BOSWatch-Modulen - Falls die zuvor standardmäßige placeholder-Datei `log/client.log` noch existiert und nicht mehr verwendet wird, wird sie beim Start automatisch gelöscht BREAKING CHANGE: Logging wird nicht mehr standardmäßig nach log/client.log geschrieben --- bw_client.py | 48 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/bw_client.py b/bw_client.py index 5c00d3e..ffe529b 100644 --- a/bw_client.py +++ b/bw_client.py @@ -10,7 +10,7 @@ r"""! by Bastian Schroll @file: bw_client.py -@date: 09.12.2017 +@date: 16.07.2025 @author: Bastian Schroll @description: BOSWatch client application """ @@ -28,7 +28,42 @@ if not paths.makeDirIfNotExist(paths.LOG_PATH): exit(1) import logging.config -logging.config.fileConfig(paths.CONFIG_PATH + "logger_client.ini") +import argparse +import os + +# Argumente zuerst parsen +parser = argparse.ArgumentParser(prog="bw_client.py", + description="""BOSWatch is a Python Script to receive and + decode german BOS information with rtl_fm and multimon-NG""", + epilog="""More options you can find in the extern client.ini + file in the folder /config""") +# With -h or --help you get the Args help +parser.add_argument("-c", "--config", help="Name to configuration File", required=True) +parser.add_argument("-t", "--test", help="Start Client with testdata-set", action="store_true") +args = parser.parse_args() + +# Logging-Konfiguration laden +logging.config.fileConfig(paths.CONFIG_PATH + "logger_client.ini", disable_existing_loggers=False) + +# Dynamischer Logdateiname basierend auf YAML-Datei +yaml_basename = os.path.splitext(args.config)[0] +log_filename = f"{paths.LOG_PATH}{yaml_basename}.log" + +for handler in logging.getLogger().handlers: + if isinstance(handler, logging.handlers.TimedRotatingFileHandler): + handler.baseFilename = os.path.abspath(log_filename) + handler.stream.close() + handler.stream = open(handler.baseFilename, handler.mode) + +# Placeholder-Logdatei löschen, falls dynamisch umgebogen +placeholder_log = os.path.abspath(os.path.join(paths.LOG_PATH, "client.log")) +if os.path.abspath(log_filename) != placeholder_log and os.path.isfile(placeholder_log): + try: + os.remove(placeholder_log) + logging.debug("Überflüssige client.log gelöscht.") + except Exception as e: + logging.warning("Fehler beim Löschen von client.log: %s", e) + logging.debug("") logging.debug("######################## NEW LOG ############################") logging.debug("BOSWatch client has started ...") @@ -56,15 +91,6 @@ from boswatch.decoder.decoder import Decoder # for test mode header.logoToLog() header.infoToLog() -# With -h or --help you get the Args help -parser = argparse.ArgumentParser(prog="bw_client.py", - description="""BOSWatch is a Python Script to receive and - decode german BOS information with rtl_fm and multimon-NG""", - epilog="""More options you can find in the extern client.ini - file in the folder /config""") -parser.add_argument("-c", "--config", help="Name to configuration File", required=True) -parser.add_argument("-t", "--test", help="Start Client with testdata-set", action="store_true") -args = parser.parse_args() bwConfig = ConfigYAML() if not bwConfig.loadConfigFile(paths.CONFIG_PATH + args.config): From 34fd0c2f1067853615c73444a9c16fb157063967 Mon Sep 17 00:00:00 2001 From: KoenigMjr <135820716+KoenigMjr@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:35:16 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Fehlerbehebung:=20Logging-Setup=20f=C3=BCr?= =?UTF-8?q?=20Multi-Client-Betrieb=20korrigiert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Logdateipfad wird vor dem Aufruf von fileConfig() über builtins.log_filename gesetzt - Entfernt manuelles Patchen des Loghandlers (BaseFilename, Stream etc.) nach dem Laden - Logging-Konfiguration (logger_client.ini) wird nur noch einmal geladen - logger_*.ini: Korrektur: interval=midnight ist nicht (mehr) offiziell unterstützt, Änderung auf korrekte Schreibweise (when=midnight, interval=1) - Ändern der Kommentare auf Englisch (stringent zu anderen Kommentaren) --- bw_client.py | 30 +++++++++--------------------- config/logger_client.ini | 10 +++++++--- config/logger_server.ini | 10 +++++++--- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/bw_client.py b/bw_client.py index ffe529b..bc8ea29 100644 --- a/bw_client.py +++ b/bw_client.py @@ -27,11 +27,14 @@ if not paths.makeDirIfNotExist(paths.LOG_PATH): print("cannot find/create log directory: %s", paths.LOG_PATH) exit(1) +import logging import logging.config +import logging.handlers import argparse import os +import builtins -# Argumente zuerst parsen +# parsing arguments first - this is needed to load the logging config file with the correct log filename parser = argparse.ArgumentParser(prog="bw_client.py", description="""BOSWatch is a Python Script to receive and decode german BOS information with rtl_fm and multimon-NG""", @@ -42,28 +45,13 @@ parser.add_argument("-c", "--config", help="Name to configuration File", require parser.add_argument("-t", "--test", help="Start Client with testdata-set", action="store_true") args = parser.parse_args() -# Logging-Konfiguration laden +# set the log filename in the global namespace (mandatory for fileConfig) +basename = os.path.splitext(args.config)[0] +log_filename = f"{paths.LOG_PATH}{basename}.log" +builtins.log_filename = log_filename + logging.config.fileConfig(paths.CONFIG_PATH + "logger_client.ini", disable_existing_loggers=False) -# Dynamischer Logdateiname basierend auf YAML-Datei -yaml_basename = os.path.splitext(args.config)[0] -log_filename = f"{paths.LOG_PATH}{yaml_basename}.log" - -for handler in logging.getLogger().handlers: - if isinstance(handler, logging.handlers.TimedRotatingFileHandler): - handler.baseFilename = os.path.abspath(log_filename) - handler.stream.close() - handler.stream = open(handler.baseFilename, handler.mode) - -# Placeholder-Logdatei löschen, falls dynamisch umgebogen -placeholder_log = os.path.abspath(os.path.join(paths.LOG_PATH, "client.log")) -if os.path.abspath(log_filename) != placeholder_log and os.path.isfile(placeholder_log): - try: - os.remove(placeholder_log) - logging.debug("Überflüssige client.log gelöscht.") - except Exception as e: - logging.warning("Fehler beim Löschen von client.log: %s", e) - logging.debug("") logging.debug("######################## NEW LOG ############################") logging.debug("BOSWatch client has started ...") diff --git a/config/logger_client.ini b/config/logger_client.ini index bdaacbe..3774f53 100644 --- a/config/logger_client.ini +++ b/config/logger_client.ini @@ -13,6 +13,7 @@ keys=root [logger_root] handlers=screen,file level=NOTSET +# NOTSET means: accept all levels (the handlers will filter by their own level) [formatters] keys=simple,complex @@ -30,11 +31,14 @@ keys=file,screen [handler_file] class=handlers.TimedRotatingFileHandler -interval=midnight -backupCount=7 formatter=complex level=ERROR -args=('log/client.log',) +args=(log_filename, 'midnight', 1, 7, 'utf-8') +# explaining args: +# - 'midnight' → rotate daily at midnight, Options: 'S', 'M', 'H', 'D', 'midnight' or 'W0'-'W6' (0=Monday, 6=Sunday) +# - 1 → rotate every 1 "x" (see line above), Options: 1, 2, ..., 31 +# - 7 → keep last 7 logs, Options: 1, 2, ..., 31 +# - 'utf-8' → encoding of the log file, don't change [handler_screen] class=StreamHandler diff --git a/config/logger_server.ini b/config/logger_server.ini index b0c591e..f5c89b5 100644 --- a/config/logger_server.ini +++ b/config/logger_server.ini @@ -13,6 +13,7 @@ keys=root [logger_root] handlers=screen,file level=NOTSET +# NOTSET means: accept all levels (the handlers will filter by their own level) [formatters] keys=simple,complex @@ -30,11 +31,14 @@ keys=file,screen [handler_file] class=handlers.TimedRotatingFileHandler -interval=midnight -backupCount=7 formatter=complex level=ERROR -args=('log/server.log',) +args=('log/server.log', 'midnight', 1, 7, 'utf-8') +# explaining args: +# - 'midnight' → rotate daily at midnight, Options: 'S', 'M', 'H', 'D', 'midnight' or 'W0'-'W6' (0=Monday, 6=Sunday) +# - 1 → rotate every 1 "x" (see line above), Options: 1, 2, ..., 31 +# - 7 → keep last 7 logs, Options: 1, 2, ..., 31 +# - 'utf-8' → encoding of the log file, don't change [handler_screen] class=StreamHandler