diff --git a/pypots/gungnir/client.py b/pypots/gungnir/client.py index a81f8e60..8bfd2cd5 100644 --- a/pypots/gungnir/client.py +++ b/pypots/gungnir/client.py @@ -1,3 +1,5 @@ +# coding=utf-8 + """ """ @@ -5,10 +7,24 @@ # Created by Wenjie Du # License: BSD-3-Clause -from ai4ts.client import TimeSeriesAI - from ..utils.logging import logger +logger.info( + """\u001b[34m +████████╗██╗███╗ ███╗███████╗ ███████╗███████╗██████╗ ██╗███████╗███████╗ █████╗ ██╗ +╚══██╔══╝██║████╗ ████║██╔════╝ ██╔════╝██╔════╝██╔══██╗██║██╔════╝██╔════╝ ██╔══██╗██║ + ██║ ██║██╔████╔██║█████╗█████╗███████╗█████╗ ██████╔╝██║█████╗ ███████╗ ███████║██║ + ██║ ██║██║╚██╔╝██║██╔══╝╚════╝╚════██║██╔══╝ ██╔══██╗██║██╔══╝ ╚════██║ ██╔══██║██║ + ██║ ██║██║ ╚═╝ ██║███████╗ ███████║███████╗██║ ██║██║███████╗███████║██╗██║ ██║██║ + ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝╚═╝ + +v{0.1} - building AI for unified time-series analysis, https://time-series.ai +\u001b[0m +""" +) + +from ai4ts.client import TimeSeriesAI + class Gungnir(TimeSeriesAI): def __init__(self): diff --git a/pypots/utils/logging.py b/pypots/utils/logging.py index 13c0c198..ac321619 100644 --- a/pypots/utils/logging.py +++ b/pypots/utils/logging.py @@ -5,8 +5,111 @@ # Created by Wenjie Du # License: BSD-3-Clause -from tsdb.utils.logging import Logger +import logging +import os +import sys -# initialize a logger for PyPOTS logging -logger_creator = Logger(name="PyPOTS running log") +print(f"default encoding: {sys.getdefaultencoding()}") +if os.getenv("PYTHONIOENCODING") != "UTF-8": + cmd = [sys.executable, *sys.argv] + os.execvpe(cmd[0], cmd, {**os.environ, "PYTHONIOENCODING": "UTF-8"}) +logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) + +LEVELS = { + "debug": logging.DEBUG, + "info": logging.INFO, + "warning": logging.WARNING, + "error": logging.ERROR, +} + + +class Logger: + """Logging class for TSDB logger initialization and control.""" + + def __init__( + self, + name: str = "TSDB running log", + logging_level: str = "debug", + logging_format: str = "%(asctime)s [%(levelname)s]: %(message)s", + ): + """ + Parameters + ---------- + name : + The name for the logger to be initialized. + + logging_level : + The logging level of the logger, should be debug/info/warning/error. + + logging_format : + Logging format of the logger. + + """ + + assert logging_level in LEVELS.keys(), f"logging_level should be {list(LEVELS.keys())}, but got {logging_level}" + + self.logger = logging.getLogger(name) + self.logging_level = LEVELS[logging_level] + + self.stream_handler = logging.StreamHandler() + self.formatter = None + self.file_handler = None + + self.set_level(logging_level) + self.set_logging_format(logging_format) + self.logger.propagate = False + + def set_logging_format(self, logging_format: str) -> None: + self.formatter = logging.Formatter(logging_format, datefmt="%Y-%m-%d %H:%M:%S") + self.stream_handler.setFormatter(self.formatter) + self.stream_handler.encoding = "utf-8" + self.logger.addHandler(self.stream_handler) + if self.file_handler is not None: + self.file_handler.setFormatter(self.formatter) + self.logger.addHandler(self.file_handler) + + def set_saving_path(self, saving_dir: str, name: str, mode: str = "a") -> None: + """Set the logger's saving path. This function will enable saving logs to the specified path. + + Parameters + ---------- + saving_dir : + The path to the directory for logging file saving. + + name : + The name of the logging file to be saved. + + mode : + Logging file writing mode. + + """ + if not os.path.exists(saving_dir): + self.logger.warning(f"{saving_dir} does not exist. Creating it now...") + os.makedirs(saving_dir) + path = os.path.join(saving_dir, name) + self.file_handler = logging.FileHandler(path, mode=mode, encoding="utf-8") + self.file_handler.setLevel(self.logging_level) + self.file_handler.setFormatter(self.formatter) + self.logger.addHandler(self.file_handler) + self.logger.info(f"Log will be saved to {path}") + + def set_level(self, level: str) -> None: + """Set the logger's logging level. + + Parameters + ---------- + level : + The logging level of the logger, should be debug/info/warning/error. + + """ + self.logging_level = LEVELS[level] + self.logger.setLevel(self.logging_level) + if self.stream_handler is not None: + self.stream_handler.setLevel(self.logging_level) + if self.file_handler is not None: + self.file_handler.setLevel(self.logging_level) + + +# initialize a logger for TSDB logging +logger_creator = Logger() logger = logger_creator.logger