diff --git a/syng/client.py b/syng/client.py index 17da827..8aa11bf 100644 --- a/syng/client.py +++ b/syng/client.py @@ -13,6 +13,7 @@ be one of: """ from __future__ import annotations +import logging import os import asyncio import datetime @@ -63,6 +64,7 @@ def default_config() -> dict[str, Optional[int | str]]: "qr_box_size": 5, "qr_position": "bottom-right", "show_advanced": False, + "log_level": "info", } @@ -112,6 +114,8 @@ class State: - `bottom-right` * `show_advanced` (`bool`): If the advanced options should be shown in the gui. + * `log_level` (`str`): The log level of the client. One of: `debug`, `info`, `warning`, + `error`, `critical`. Default is `info`. :type config: dict[str, Any]: """ @@ -130,6 +134,7 @@ class Client: config["config"] = default_config() | config["config"] self.is_running = False + self.set_log_level(config["config"]["log_level"]) self.sio = socketio.AsyncClient(json=jsonencoder) self.loop: Optional[asyncio.AbstractEventLoop] = None self.skipped: list[UUID] = [] @@ -145,6 +150,19 @@ class Client: ) self.register_handlers() + def set_log_level(self, level: str) -> None: + match level: + case "debug": + logger.setLevel(logging.DEBUG) + case "info": + logger.setLevel(logging.INFO) + case "warning": + logger.setLevel(logging.WARNING) + case "error": + logger.setLevel(logging.ERROR) + case "critical": + logger.setLevel(logging.CRITICAL) + def register_handlers(self) -> None: self.sio.on("update_config", self.handle_update_config) self.sio.on("skip-current", self.handle_skip_current) @@ -174,12 +192,16 @@ class Client: msg_type = data.get("type", "info") match msg_type: + case "debug": + logger.debug(data["msg"]) case "info": logger.info(data["msg"]) case "warning": logger.warning(data["msg"]) case "error": logger.error(data["msg"]) + case "critical": + logger.critical(data["msg"]) async def handle_update_config(self, data: dict[str, Any]) -> None: """ @@ -427,7 +449,7 @@ class Client: await self.sio.emit("get-first") else: reason = data.get("reason", "Unknown") - logger.warning(f"Registration failed: {reason}") + logger.critical(f"Registration failed: {reason}") await self.sio.disconnect() async def handle_request_config(self, data: dict[str, Any]) -> None: @@ -543,7 +565,7 @@ class Client: except asyncio.CancelledError: pass except ConnectionError: - logger.error("Could not connect to server") + logger.critical("Could not connect to server") finally: self.is_running = False if self.player.mpv is not None: diff --git a/syng/gui.py b/syng/gui.py index 234a4fd..ed2e078 100644 --- a/syng/gui.py +++ b/syng/gui.py @@ -466,6 +466,13 @@ class GeneralConfig(OptionFrame): ["top-left", "top-right", "bottom-left", "bottom-right"], config["qr_position"], ) + self.add_choose_option( + "log_level", + "Log Level", + ["debug", "info", "warning", "error", "critical"], + config["log_level"], + ) + self.add_bool_option("show_advanced", "Show Advanced Options", config["show_advanced"]) self.simple_options = ["server", "room", "secret"] @@ -658,7 +665,6 @@ class SyngGui(QMainWindow): self.syng_client_logging_listener = QueueListener(self.logqueue, self.log_label_handler) self.syng_client_logging_listener.start() - logger.setLevel(logging.DEBUG) self.setCentralWidget(self.central_widget) @@ -787,8 +793,14 @@ class SyngGui(QMainWindow): self.client.quit_callback() self.set_client_button_start() - @pyqtSlot(str) - def print_log(self, log: str) -> None: + @pyqtSlot(str, int) + def print_log(self, log: str, level: int) -> None: + if level == logging.CRITICAL: + log_msg_box = QMessageBox(self) + log_msg_box.setIcon(QMessageBox.Icon.Critical) + log_msg_box.setWindowTitle("Critical Error") + log_msg_box.setText(log) + log_msg_box.exec() self.log_text.append(f"[{datetime.now().strftime('%H:%M:%S')}] {log}") def change_qr(self, data: str) -> None: @@ -816,7 +828,7 @@ class SyngGui(QMainWindow): class LoggingLabelHandler(logging.Handler): class LogSignalEmiter(QObject): - log_signal = pyqtSignal(str) + log_signal = pyqtSignal(str, int) def __init__(self, parent: Optional[QObject] = None): super().__init__(parent) @@ -830,7 +842,7 @@ class LoggingLabelHandler(logging.Handler): if not self._cleanup: # This could race condition, but it's not a big # deal since it only causes a race condition, # when the program ends - self.log_signal_emiter.log_signal.emit(self.format(record)) + self.log_signal_emiter.log_signal.emit(self.format(record), record.levelno) def cleanup(self) -> None: self._cleanup = True