diff --git a/config_loader.py b/config_loader.py index ced4e7f..ed94fa7 100644 --- a/config_loader.py +++ b/config_loader.py @@ -68,6 +68,7 @@ def _load_config_file(path: pathlib.Path): "BRIDGE_PRINTER_NAME": (CONFIG_SECTION_BRIDGE, "printer_name"), "BRIDGE_HOST_IP": (CONFIG_SECTION_BRIDGE, "host_ip"), "POLL_INTERVAL": (CONFIG_SECTION_BRIDGE, "poll_interval"), + "VERBOSE_HTTP_LOG": (CONFIG_SECTION_BRIDGE, "verbose_http_log"), "SPOOLMAN_SERVER": (CONFIG_SECTION_SPOOLMAN, "server"), "SPOOLMAN_SYNC_RATE": (CONFIG_SECTION_SPOOLMAN, "sync_rate"), } @@ -450,3 +451,4 @@ SPOOLMAN_SERVER = get("SPOOLMAN_SERVER", "") SPOOLMAN_SYNC_RATE = int(get("SPOOLMAN_SYNC_RATE", "0")) BRIDGE_HOST_IP = get("BRIDGE_HOST_IP", "") POLL_INTERVAL = int(get("POLL_INTERVAL", "3")) +VERBOSE_HTTP_LOG = int(get("VERBOSE_HTTP_LOG", "0")) diff --git a/kobrax_moonraker_bridge.py b/kobrax_moonraker_bridge.py index 988c07e..ccb8624 100644 --- a/kobrax_moonraker_bridge.py +++ b/kobrax_moonraker_bridge.py @@ -135,10 +135,14 @@ logging.basicConfig(level=logging.INFO, datefmt="%H:%M:%S") log = logging.getLogger("bridge") # aiohttp logs one INFO line per HTTP request (access log) — with 2s frontend -# polling that drowns out the bridge's own logs. Raise its own threshold so -# only WARNING+ (actual problems) surface at the default log level. +# polling that drowns out the bridge's own logs by default. Toggleable at +# runtime via the verbose_http_log setting (see handle_api_settings_post). logging.getLogger("aiohttp.access").setLevel(logging.WARNING) + +def _set_verbose_http_log(enabled: bool): + logging.getLogger("aiohttp.access").setLevel(logging.INFO if enabled else logging.WARNING) + # Web UI: subdirectory under web/themes//index.html _UI_THEME_NAME_RE = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$") # Allowed static theme files under /kx/ui/ @@ -4420,6 +4424,7 @@ class KobraXBridge: "web_upload_warning": getattr(self._args, "web_upload_warning", 1), "print_start_dialog": getattr(self._args, "print_start_dialog", 1), "poll_interval": getattr(self._args, "poll_interval", 3), + "verbose_http_log": getattr(self._args, "verbose_http_log", 0), "filament_profiles": {str(k): v for k, v in self._filament_profiles.items()}, "visible_vendors": self._visible_vendors, "ace_dry_presets": self._ace_dry_presets, @@ -4464,6 +4469,10 @@ class KobraXBridge: cfg.set("bridge", "poll_interval", str(pi)) elif not cfg.has_option("bridge", "poll_interval"): cfg.set("bridge", "poll_interval", "3") + verbose_http_log = int(bool(data.get("verbose_http_log", getattr(self._args, "verbose_http_log", 0)))) + cfg.set("bridge", "verbose_http_log", str(verbose_http_log)) + _set_verbose_http_log(bool(verbose_http_log)) + self._args.verbose_http_log = verbose_http_log printer_name = str(data.get("printer_name", "")).strip() if printer_name: cfg.set("bridge", "printer_name", printer_name) @@ -5449,6 +5458,7 @@ def _build_per_printer_args(base_args, p: dict): async def run_bridge(args): + _set_verbose_http_log(bool(getattr(args, "verbose_http_log", 0))) printers = env_loader.list_printers() multi_mode = bool(printers) if not printers: @@ -5599,6 +5609,8 @@ def main(): help="Mid-print filament sync interval in seconds (0 = only on print end)") parser.add_argument("--poll-interval", type=int, default=env_loader.POLL_INTERVAL, help="Printer poll interval in seconds") + parser.add_argument("--verbose-http-log", type=int, default=env_loader.VERBOSE_HTTP_LOG, + help="Log every HTTP request (aiohttp access log)") parser.add_argument("--host", default="0.0.0.0", help="Bind address for the bridge server") diff --git a/web/themes/default/app.js b/web/themes/default/app.js index 84aa661..7d11be4 100644 --- a/web/themes/default/app.js +++ b/web/themes/default/app.js @@ -408,6 +408,7 @@ function applyLang(){ setText('lbl-set-lang',T.settings_cat_language||'Sprache'); setText('lbl-set-theme',T.settings_cat_theme||'Hell / Dunkel umschalten'); setText('lbl-poll-interval',T.settings_poll||'Poll-Intervall (Sekunden)'); + setText('lbl-verbose-http-log',T.settings_verbose_http_log||'Log every HTTP request (verbose)'); setText('lbl-filament-mapping',T.settings_filament_mapping||'Filament-Profil-Mapping (pro Slot)'); setText('lbl-filament-mapping-save',T.settings_filament_mapping_save||'Mapping speichern'); setText('lbl-visible-vendors',T.settings_visible_vendors||'Sichtbare Hersteller (Profil-Dropdown)'); @@ -1099,6 +1100,7 @@ function openSettings(){ var sec=d.poll_interval||Math.round((parseInt(localStorage.getItem('pollInterval')||'2000'))/1000)||3; pi.value=sec; } + var vhl=document.getElementById('s-verbose-http-log');if(vhl)vhl.checked=!!d.verbose_http_log; renderFilamentMapping(d.filament_profiles||{}); renderSpoolmanSlotCard(); // Spoolman @@ -1861,6 +1863,7 @@ function saveSettings(){ print_start_dialog: parseInt((document.getElementById('s-file-ready-mode')||{}).value||'1',10), web_upload_warning:webUploadWarning, poll_interval: Math.min(60,Math.max(1,parseInt((document.getElementById('s-poll-interval')||{}).value,10)||3)), + verbose_http_log: (document.getElementById('s-verbose-http-log')||{}).checked?1:0, spoolman_server: (document.getElementById('s-spoolman-url')||{}).value||'', spoolman_sync_rate: Math.max(0,parseInt((document.getElementById('s-spoolman-sync-rate')||{}).value||'30',10)), }).then(function(){ diff --git a/web/themes/default/index.html b/web/themes/default/index.html index f9d2140..3df8fcd 100644 --- a/web/themes/default/index.html +++ b/web/themes/default/index.html @@ -554,6 +554,10 @@ Wie oft die Bridge den Drucker-Status abfragt + diff --git a/web/translations/de.json b/web/translations/de.json index 26bff86..348a8a1 100644 --- a/web/translations/de.json +++ b/web/translations/de.json @@ -246,6 +246,7 @@ "settings_password": "MQTT-Passwort", "settings_poll": "Poll-Intervall (Sekunden)", "settings_poll_interval_hint": "Wie oft die Bridge den Druckerstatus abfragt", + "settings_verbose_http_log": "Jede HTTP-Anfrage loggen (ausführlich)", "settings_poll_interval_label": "Poll-Intervall (Sekunden)", "settings_print": "Druckeinstellungen", "settings_printer_ip": "Drucker-IP", diff --git a/web/translations/en.json b/web/translations/en.json index 799023b..20fe26e 100644 --- a/web/translations/en.json +++ b/web/translations/en.json @@ -246,6 +246,7 @@ "settings_password": "MQTT Password", "settings_poll": "Poll Interval (seconds)", "settings_poll_interval_hint": "How often the bridge queries printer status", + "settings_verbose_http_log": "Log every HTTP request (verbose)", "settings_poll_interval_label": "Poll Interval (seconds)", "settings_print": "Print Settings", "settings_printer_ip": "Printer IP", diff --git a/web/translations/es.json b/web/translations/es.json index bc0dae9..71c1b47 100644 --- a/web/translations/es.json +++ b/web/translations/es.json @@ -246,6 +246,7 @@ "settings_password": "Contraseña MQTT", "settings_poll": "Intervalo de sondeo (segundos)", "settings_poll_interval_hint": "Con qué frecuencia el bridge consulta el estado de la impresora", + "settings_verbose_http_log": "Registrar cada solicitud HTTP (detallado)", "settings_poll_interval_label": "Intervalo de sondeo (segundos)", "settings_print": "Ajustes de impresión", "settings_printer_ip": "IP de impresora", diff --git a/web/translations/zh-cn.json b/web/translations/zh-cn.json index ca30435..b75361b 100644 --- a/web/translations/zh-cn.json +++ b/web/translations/zh-cn.json @@ -246,6 +246,7 @@ "settings_password": "MQTT 密码", "settings_poll": "轮询间隔(秒)", "settings_poll_interval_hint": "Bridge 查询打印机状态的频率", + "settings_verbose_http_log": "记录每个 HTTP 请求(详细模式)", "settings_poll_interval_label": "轮询间隔(秒)", "settings_print": "打印设置", "settings_printer_ip": "打印机 IP",