feat: add log_config generator

This commit is contained in:
Matthias
2025-03-08 13:09:55 +01:00
parent 9afd572948
commit 41418784e3
+76 -47
View File
@@ -72,13 +72,13 @@ logging_config = {
# "formatter": "standard", # "formatter": "standard",
# "stream": "ext://sys.stdout", # "stream": "ext://sys.stdout",
}, },
"file": { # "file": {
"class": "logging.handlers.RotatingFileHandler", # "class": "logging.handlers.RotatingFileHandler",
"formatter": "standard", # "formatter": "standard",
"filename": "whatever.log", # "filename": "whatever.log",
"maxBytes": 1024 * 1024 * 10, # 10Mb # "maxBytes": 1024 * 1024 * 10, # 10Mb
"backupCount": 10, # "backupCount": 10,
}, # },
}, },
"loggers": { "loggers": {
"freqtrade": { "freqtrade": {
@@ -88,7 +88,10 @@ logging_config = {
}, },
}, },
"root": { "root": {
"handlers": ["console", "file"], "handlers": [
"console",
# "file",
],
"level": "INFO", "level": "INFO",
}, },
} }
@@ -101,60 +104,75 @@ def setup_logging(config: Config) -> None:
# Log level # Log level
verbosity = config["verbosity"] verbosity = config["verbosity"]
logging.config.dictConfig(logging_config) # Get log_config from user config or use default
log_config = config.get("log_config", logging_config.copy())
logging.root.addHandler(bufferHandler)
if config.get("print_colorized", True):
logger.info("Enabling colorized output.")
error_console._color_system = error_console._detect_color_system()
logfile = config.get("logfile") logfile = config.get("logfile")
logging.info("Logfile configured")
if logfile: if logfile:
s = logfile.split(":") s = logfile.split(":")
if s[0] == "syslog": if s[0] == "syslog":
# Address can be either a string (socket filename) for Unix domain socket or # Add syslog handler to the config
# a tuple (hostname, port) for UDP socket. log_config["handlers"]["syslog"] = {
# Address can be omitted (i.e. simple 'syslog' used as the value of "class": "logging.handlers.SysLogHandler",
# config['logfilename']), which defaults to '/dev/log', applicable for most "formatter": "syslog_format",
# of the systems. "address": (s[1], int(s[2])) if len(s) > 2 else s[1] if len(s) > 1 else "/dev/log",
address = (s[1], int(s[2])) if len(s) > 2 else s[1] if len(s) > 1 else "/dev/log" }
if handler_sl := get_existing_handlers(SysLogHandler): # Add the syslog formatter if not already present
logging.root.removeHandler(handler_sl) if "syslog_format" not in log_config["formatters"]:
handler_sl = SysLogHandler(address=address) log_config["formatters"]["syslog_format"] = {
# No datetime field for logging into syslog, to allow syslog "format": "%(name)s - %(levelname)s - %(message)s"
# to perform reduction of repeating messages if this is set in the }
# syslog config. The messages should be equal for this. # Add handler to root
handler_sl.setFormatter(Formatter("%(name)s - %(levelname)s - %(message)s")) if "syslog" not in log_config["root"]["handlers"]:
logging.root.addHandler(handler_sl) log_config["root"]["handlers"].append("syslog")
elif s[0] == "journald": # pragma: no cover elif s[0] == "journald": # pragma: no cover
# Check if we have the module available
try: try:
from cysystemd.journal import JournaldLogHandler from cysystemd.journal import JournaldLogHandler # noqa: F401
except ImportError: except ImportError:
raise OperationalException( raise OperationalException(
"You need the cysystemd python package be installed in " "You need the cysystemd python package be installed in "
"order to use logging to journald." "order to use logging to journald."
) )
if handler_jd := get_existing_handlers(JournaldLogHandler):
logging.root.removeHandler(handler_jd) # Add journald handler to the config
handler_jd = JournaldLogHandler() log_config["handlers"]["journald"] = {
# No datetime field for logging into journald, to allow syslog "class": "cysystemd.journal.JournaldLogHandler",
# to perform reduction of repeating messages if this is set in the "formatter": "journald_format",
# syslog config. The messages should be equal for this. }
handler_jd.setFormatter(Formatter("%(name)s - %(levelname)s - %(message)s")) # Add the journald formatter if not already present
logging.root.addHandler(handler_jd) if "journald_format" not in log_config["formatters"]:
log_config["formatters"]["journald_format"] = {
"format": "%(name)s - %(levelname)s - %(message)s"
}
# Add handler to root
if "journald" not in log_config["root"]["handlers"]:
log_config["root"]["handlers"].append("journald")
else: else:
if handler_rf := get_existing_handlers(RotatingFileHandler): # Regular file logging
logging.root.removeHandler(handler_rf)
try: try:
logfile_path = Path(logfile) logfile_path = Path(logfile)
logfile_path.parent.mkdir(parents=True, exist_ok=True) logfile_path.parent.mkdir(parents=True, exist_ok=True)
handler_rf = RotatingFileHandler(
logfile_path, # Update file handler configuration
maxBytes=1024 * 1024 * 10, # 10Mb if "file" in log_config["handlers"]:
backupCount=10, log_config["handlers"]["file"]["filename"] = str(logfile_path)
) else:
log_config["handlers"]["file"] = {
"class": "logging.handlers.RotatingFileHandler",
"formatter": "standard",
"filename": str(logfile_path),
"maxBytes": 1024 * 1024 * 10, # 10Mb
"backupCount": 10,
}
# Ensure file handler is in root handlers
if "file" not in log_config["root"]["handlers"]:
log_config["root"]["handlers"].append("file")
except PermissionError: except PermissionError:
raise OperationalException( raise OperationalException(
f'Failed to create or access log file "{logfile_path.absolute()}". ' f'Failed to create or access log file "{logfile_path.absolute()}". '
@@ -164,9 +182,20 @@ def setup_logging(config: Config) -> None:
"non-root user, delete and recreate the directories you need, and then try " "non-root user, delete and recreate the directories you need, and then try "
"again." "again."
) )
handler_rf.setFormatter(Formatter(LOGFORMAT))
logging.root.addHandler(handler_rf)
# Apply the configuration
logging.config.dictConfig(log_config)
# Add buffer handler to root logger
logging.root.addHandler(bufferHandler)
# Set color system for console output
if config.get("print_colorized", True):
logger.info("Enabling colorized output.")
error_console._color_system = error_console._detect_color_system()
logging.info("Logfile configured")
# Set verbosity levels
logging.root.setLevel(logging.INFO if verbosity < 1 else logging.DEBUG) logging.root.setLevel(logging.INFO if verbosity < 1 else logging.DEBUG)
set_loggers(verbosity, config.get("api_server", {}).get("verbosity", "info")) set_loggers(verbosity, config.get("api_server", {}).get("verbosity", "info"))