mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-07-15 23:09:56 +00:00
runtime logger handler selector
This commit is contained in:
@ -30,6 +30,7 @@ from ahriman.application import handlers
|
||||
from ahriman.core.util import enum_values
|
||||
from ahriman.models.action import Action
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
from ahriman.models.log_handler import LogHandler
|
||||
from ahriman.models.package_source import PackageSource
|
||||
from ahriman.models.sign_settings import SignSettings
|
||||
from ahriman.models.user_access import UserAccess
|
||||
@ -58,6 +59,7 @@ def _formatter(prog: str) -> argparse.HelpFormatter:
|
||||
return argparse.ArgumentDefaultsHelpFormatter(prog, width=120)
|
||||
|
||||
|
||||
# pylint: disable=too-many-statements
|
||||
def _parser() -> argparse.ArgumentParser:
|
||||
"""
|
||||
command line parser generator
|
||||
@ -75,6 +77,9 @@ def _parser() -> argparse.ArgumentParser:
|
||||
parser.add_argument("--force", help="force run, remove file lock", action="store_true")
|
||||
parser.add_argument("-l", "--lock", help="lock file", type=Path,
|
||||
default=Path(tempfile.gettempdir()) / "ahriman.lock")
|
||||
parser.add_argument("--log-handler", help="explicit log handler specification. If none set, the handler will be "
|
||||
"guessed from environment",
|
||||
type=LogHandler, choices=enum_values(LogHandler))
|
||||
parser.add_argument("--report", help="force enable or disable reporting to web service",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
||||
|
@ -94,7 +94,8 @@ class Handler:
|
||||
"""
|
||||
try:
|
||||
configuration = Configuration.from_path(args.configuration, architecture)
|
||||
Log.load(configuration, quiet=args.quiet, report=args.report)
|
||||
log_handler = Log.handler(args.log_handler)
|
||||
Log.load(configuration, log_handler, quiet=args.quiet, report=args.report)
|
||||
with Lock(args, architecture, configuration):
|
||||
cls.run(args, architecture, configuration, report=args.report, unsafe=args.unsafe)
|
||||
return True
|
||||
|
47
src/ahriman/core/log/journal_handler.py
Normal file
47
src/ahriman/core/log/journal_handler.py
Normal file
@ -0,0 +1,47 @@
|
||||
#
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from logging import NullHandler
|
||||
from typing import Any
|
||||
|
||||
|
||||
__all__ = ["JournalHandler"]
|
||||
|
||||
|
||||
class _JournalHandler(NullHandler):
|
||||
"""
|
||||
wrapper for unexpected args and kwargs
|
||||
"""
|
||||
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
*args(Any): positional arguments
|
||||
**kwargs(Any): keyword arguments
|
||||
"""
|
||||
NullHandler.__init__(self)
|
||||
del args, kwargs
|
||||
|
||||
|
||||
try:
|
||||
from systemd.journal import JournalHandler # type: ignore[import]
|
||||
except ImportError:
|
||||
JournalHandler = _JournalHandler
|
@ -20,9 +20,11 @@
|
||||
import logging
|
||||
|
||||
from logging.config import fileConfig
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.log.http_log_handler import HttpLogHandler
|
||||
from ahriman.models.log_handler import LogHandler
|
||||
|
||||
|
||||
class Log:
|
||||
@ -32,24 +34,65 @@ class Log:
|
||||
Attributes:
|
||||
DEFAULT_LOG_FORMAT(str): (class attribute) default log format (in case of fallback)
|
||||
DEFAULT_LOG_LEVEL(int): (class attribute) default log level (in case of fallback)
|
||||
DEFAULT_SYSLOG_DEVICE(Path): (class attribute) default path to syslog device
|
||||
"""
|
||||
|
||||
DEFAULT_LOG_FORMAT = "[%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s"
|
||||
DEFAULT_LOG_LEVEL = logging.DEBUG
|
||||
DEFAULT_SYSLOG_DEVICE = Path("/dev") / "log"
|
||||
|
||||
@staticmethod
|
||||
def load(configuration: Configuration, *, quiet: bool, report: bool) -> None:
|
||||
def handler(selected: LogHandler | None) -> LogHandler:
|
||||
"""
|
||||
try to guess default log handler. In case if ``selected`` is set, it will return specified value with appended
|
||||
_handler suffix. Otherwise, it will try to import journald handler and returns ``journald_handler`` if library
|
||||
is available. Otherwise, it will check if there is ``/dev/log`` device and returns ``syslog_handler`` in this
|
||||
case. And, finally, it will fall back to ``console_handler`` if none were found
|
||||
|
||||
Args:
|
||||
selected(LogHandler | None): user specified handler if any
|
||||
|
||||
Returns:
|
||||
LogHandler: selected log handler
|
||||
"""
|
||||
if selected is not None:
|
||||
return selected
|
||||
|
||||
try:
|
||||
from systemd.journal import JournalHandler # type: ignore[import]
|
||||
del JournalHandler
|
||||
return LogHandler.Journald # journald import was found
|
||||
except ImportError:
|
||||
if Log.DEFAULT_SYSLOG_DEVICE.exists():
|
||||
return LogHandler.Syslog
|
||||
return LogHandler.Console
|
||||
|
||||
@staticmethod
|
||||
def load(configuration: Configuration, handler: LogHandler, *, quiet: bool, report: bool) -> None:
|
||||
"""
|
||||
setup logging settings from configuration
|
||||
|
||||
Args:
|
||||
configuration(Configuration): configuration instance
|
||||
handler(LogHandler): selected default log handler, which will be used if no handlers were set
|
||||
quiet(bool): force disable any log messages
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
default_handler = f"{handler.value}_handler"
|
||||
|
||||
try:
|
||||
path = configuration.logging_path
|
||||
fileConfig(path)
|
||||
log_configuration = Configuration()
|
||||
log_configuration.read(configuration.logging_path)
|
||||
|
||||
# set handlers if they are not set
|
||||
for section in filter(lambda s: s.startswith("logger_"), log_configuration.sections()):
|
||||
if "handlers" in log_configuration[section]:
|
||||
continue
|
||||
log_configuration.set_option(section, "handlers", default_handler)
|
||||
|
||||
# load logging configuration
|
||||
fileConfig(log_configuration, disable_existing_loggers=True)
|
||||
logging.debug("using %s logger", default_handler)
|
||||
except Exception:
|
||||
logging.basicConfig(filename=None, format=Log.DEFAULT_LOG_FORMAT,
|
||||
level=Log.DEFAULT_LOG_LEVEL)
|
||||
|
35
src/ahriman/models/log_handler.py
Normal file
35
src/ahriman/models/log_handler.py
Normal file
@ -0,0 +1,35 @@
|
||||
#
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class LogHandler(str, Enum):
|
||||
"""
|
||||
log handler as described by default configuration
|
||||
|
||||
Attributes:
|
||||
Console(LogHandler): (class attribute) write logs to console
|
||||
Syslog(LogHandler): (class attribute) write logs to syslog device /dev/null
|
||||
Journald(LogHandler): (class attribute) write logs to journald directly
|
||||
"""
|
||||
|
||||
Console = "console"
|
||||
Syslog = "syslog"
|
||||
Journald = "journald"
|
Reference in New Issue
Block a user