Add logging module
This commit is contained in:
parent
ce26e25923
commit
58bd20f882
113
tianshou/utils/logging.py
Normal file
113
tianshou/utils/logging.py
Normal file
@ -0,0 +1,113 @@
|
||||
"""
|
||||
Partial copy of sensai.util.logging
|
||||
"""
|
||||
# ruff: noqa
|
||||
import atexit
|
||||
import logging as lg
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
from datetime import datetime
|
||||
from io import StringIO
|
||||
from logging import *
|
||||
from typing import Any
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
LOG_DEFAULT_FORMAT = "%(levelname)-5s %(asctime)-15s %(name)s:%(funcName)s - %(message)s"
|
||||
_logFormat = LOG_DEFAULT_FORMAT
|
||||
|
||||
|
||||
def remove_log_handlers():
|
||||
"""Removes all current log handlers."""
|
||||
logger = getLogger()
|
||||
while logger.hasHandlers():
|
||||
logger.removeHandler(logger.handlers[0])
|
||||
|
||||
|
||||
def is_log_handler_active(handler):
|
||||
"""Checks whether the given handler is active.
|
||||
|
||||
:param handler: a log handler
|
||||
:return: True if the handler is active, False otherwise
|
||||
"""
|
||||
return handler in getLogger().handlers
|
||||
|
||||
|
||||
# noinspection PyShadowingBuiltins
|
||||
def configure(format=LOG_DEFAULT_FORMAT, level=lg.DEBUG):
|
||||
"""Configures logging to stdout with the given format and log level,
|
||||
also configuring the default log levels of some overly verbose libraries as well as some pandas output options.
|
||||
|
||||
:param format: the log format
|
||||
:param level: the minimum log level
|
||||
"""
|
||||
global _logFormat
|
||||
_logFormat = format
|
||||
remove_log_handlers()
|
||||
basicConfig(level=level, format=format, stream=sys.stdout)
|
||||
|
||||
|
||||
# noinspection PyShadowingBuiltins
|
||||
def run_main(main_fn: Callable[[], Any], format=LOG_DEFAULT_FORMAT, level=lg.DEBUG):
|
||||
"""Configures logging with the given parameters, ensuring that any exceptions that occur during
|
||||
the execution of the given function are logged.
|
||||
Logs two additional messages, one before the execution of the function, and one upon its completion.
|
||||
|
||||
:param main_fn: the function to be executed
|
||||
:param format: the log message format
|
||||
:param level: the minimum log level
|
||||
:return: the result of `main_fn`
|
||||
"""
|
||||
configure(format=format, level=level)
|
||||
log.info("Starting")
|
||||
try:
|
||||
result = main_fn()
|
||||
log.info("Done")
|
||||
return result
|
||||
except Exception as e:
|
||||
log.error("Exception during script execution", exc_info=e)
|
||||
|
||||
|
||||
def datetime_tag() -> str:
|
||||
""":return: a string tag for use in log file names which contains the current date and time (compact but readable)"""
|
||||
return datetime.now().strftime("%Y%m%d-%H%M%S")
|
||||
|
||||
|
||||
_fileLoggerPaths: list[str] = []
|
||||
_isAtExitReportFileLoggerRegistered = False
|
||||
_memoryLogStream: StringIO | None = None
|
||||
|
||||
|
||||
def _at_exit_report_file_logger():
|
||||
for path in _fileLoggerPaths:
|
||||
print(f"A log file was saved to {path}")
|
||||
|
||||
|
||||
def add_file_logger(path):
|
||||
global _isAtExitReportFileLoggerRegistered
|
||||
log.info(f"Logging to {path} ...")
|
||||
handler = FileHandler(path)
|
||||
handler.setFormatter(Formatter(_logFormat))
|
||||
Logger.root.addHandler(handler)
|
||||
_fileLoggerPaths.append(path)
|
||||
if not _isAtExitReportFileLoggerRegistered:
|
||||
atexit.register(_at_exit_report_file_logger)
|
||||
_isAtExitReportFileLoggerRegistered = True
|
||||
|
||||
|
||||
def add_memory_logger() -> None:
|
||||
"""Enables in-memory logging (if it is not already enabled), i.e. all log statements are written to a memory buffer and can later be
|
||||
read via function `get_memory_log()`.
|
||||
"""
|
||||
global _memoryLogStream
|
||||
if _memoryLogStream is not None:
|
||||
return
|
||||
_memoryLogStream = StringIO()
|
||||
handler = StreamHandler(_memoryLogStream)
|
||||
handler.setFormatter(Formatter(_logFormat))
|
||||
Logger.root.addHandler(handler)
|
||||
|
||||
|
||||
def get_memory_log():
|
||||
""":return: the in-memory log (provided that `add_memory_logger` was called beforehand)"""
|
||||
return _memoryLogStream.getvalue()
|
Loading…
x
Reference in New Issue
Block a user