mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
runtime logger handler selector
This commit is contained in:
parent
01a4d68ce6
commit
8731cee8ea
@ -6,7 +6,7 @@ ENV AHRIMAN_DEBUG=""
|
|||||||
ENV AHRIMAN_FORCE_ROOT=""
|
ENV AHRIMAN_FORCE_ROOT=""
|
||||||
ENV AHRIMAN_HOST="0.0.0.0"
|
ENV AHRIMAN_HOST="0.0.0.0"
|
||||||
ENV AHRIMAN_MULTILIB="yes"
|
ENV AHRIMAN_MULTILIB="yes"
|
||||||
ENV AHRIMAN_OUTPUT="journald"
|
ENV AHRIMAN_OUTPUT=""
|
||||||
ENV AHRIMAN_PACKAGER="ahriman bot <ahriman@example.com>"
|
ENV AHRIMAN_PACKAGER="ahriman bot <ahriman@example.com>"
|
||||||
ENV AHRIMAN_PACMAN_MIRROR=""
|
ENV AHRIMAN_PACMAN_MIRROR=""
|
||||||
ENV AHRIMAN_PORT=""
|
ENV AHRIMAN_PORT=""
|
||||||
@ -28,9 +28,9 @@ RUN useradd -m -d "/home/build" -s "/usr/bin/nologin" build && \
|
|||||||
COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
|
COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
|
||||||
## install package dependencies
|
## install package dependencies
|
||||||
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
|
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
|
||||||
RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo python-systemd && \
|
RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo && \
|
||||||
pacman -Sy --noconfirm --asdeps python-build python-installer python-wheel && \
|
pacman -Sy --noconfirm --asdeps python-build python-installer python-wheel && \
|
||||||
pacman -Sy --noconfirm breezy mercurial python-aiohttp python-aiohttp-cors python-boto3 python-cryptography python-jinja python-requests-unixsocket rsync subversion && \
|
pacman -Sy --noconfirm --asdeps breezy mercurial python-aiohttp python-aiohttp-cors python-boto3 python-cryptography python-jinja python-requests-unixsocket python-systemd rsync subversion && \
|
||||||
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-apispec-git python-aiohttp-jinja2 \
|
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-apispec-git python-aiohttp-jinja2 \
|
||||||
python-aiohttp-debugtoolbar python-aiohttp-session python-aiohttp-security
|
python-aiohttp-debugtoolbar python-aiohttp-session python-aiohttp-security
|
||||||
|
|
||||||
|
@ -15,15 +15,10 @@ database = $AHRIMAN_REPOSITORY_ROOT/ahriman.db
|
|||||||
host = $AHRIMAN_HOST
|
host = $AHRIMAN_HOST
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
sed -i "s|handlers = journald_handler|handlers = ${AHRIMAN_OUTPUT}_handler|g" "/etc/ahriman.ini.d/logging.ini"
|
|
||||||
|
|
||||||
AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE")
|
AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE")
|
||||||
if [[ "$AHRIMAN_OUTPUT" == "syslog" ]]; then
|
if [ -n "$AHRIMAN_OUTPUT" ]; then
|
||||||
if [ ! -e "/dev/log" ]; then
|
AHRIMAN_DEFAULT_ARGS+=("--log-handler" "$AHRIMAN_OUTPUT")
|
||||||
# by default ahriman uses syslog which is not available inside container
|
|
||||||
# to make noise less we force quiet mode in case if /dev/log was not mounted
|
|
||||||
AHRIMAN_DEFAULT_ARGS+=("--quiet")
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# create repository root inside the [[mounted]] directory and set correct ownership
|
# create repository root inside the [[mounted]] directory and set correct ownership
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
.TH AHRIMAN "1" "2023\-05\-25" "ahriman" "Generated Python Manual"
|
.TH AHRIMAN "1" "2023\-05\-28" "ahriman" "Generated Python Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ahriman
|
ahriman
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B ahriman
|
.B ahriman
|
||||||
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--report | --no-report] [-q] [--unsafe] [-V] {aur-search,search,help,help-commands-unsafe,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-create-keyring,repo-create-mirrorlist,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,user-add,user-list,user-remove,web} ...
|
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--log-handler {console,syslog,journald}] [--report | --no-report] [-q] [--unsafe] [-V] {aur-search,search,help,help-commands-unsafe,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-create-keyring,repo-create-mirrorlist,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,user-add,user-list,user-remove,web} ...
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
ArcH linux ReposItory MANager
|
ArcH linux ReposItory MANager
|
||||||
|
|
||||||
@ -24,6 +24,10 @@ force run, remove file lock
|
|||||||
\fB\-l\fR \fI\,LOCK\/\fR, \fB\-\-lock\fR \fI\,LOCK\/\fR
|
\fB\-l\fR \fI\,LOCK\/\fR, \fB\-\-lock\fR \fI\,LOCK\/\fR
|
||||||
lock file
|
lock file
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fB\-\-log\-handler\fR \fI\,{console,syslog,journald}\/\fR
|
||||||
|
explicit log handler specification. If none set, the handler will be guessed from environment
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-report\fR, \fB\-\-no\-report\fR
|
\fB\-\-report\fR, \fB\-\-no\-report\fR
|
||||||
force enable or disable reporting to web service
|
force enable or disable reporting to web service
|
||||||
|
@ -20,6 +20,14 @@ ahriman.core.log.http\_log\_handler module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.core.log.journal\_handler module
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.core.log.journal_handler
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.core.log.lazy\_logging module
|
ahriman.core.log.lazy\_logging module
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
@ -60,6 +60,14 @@ ahriman.models.internal\_status module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.models.log\_handler module
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.models.log_handler
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.models.log\_record\_id module
|
ahriman.models.log\_record\_id module
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
_shtab_ahriman_subparsers=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
|
_shtab_ahriman_subparsers=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
|
||||||
|
|
||||||
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--report' '--no-report' '-q' '--quiet' '--unsafe' '-V' '--version')
|
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '--report' '--no-report' '-q' '--quiet' '--unsafe' '-V' '--version')
|
||||||
_shtab_ahriman_aur_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
_shtab_ahriman_aur_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
||||||
_shtab_ahriman_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
_shtab_ahriman_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
||||||
_shtab_ahriman_help_option_strings=('-h' '--help')
|
_shtab_ahriman_help_option_strings=('-h' '--help')
|
||||||
@ -73,6 +73,7 @@ _shtab_ahriman_web_option_strings=('-h' '--help')
|
|||||||
|
|
||||||
|
|
||||||
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
|
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
|
||||||
|
_shtab_ahriman___log_handler_choices=('console' 'syslog' 'journald')
|
||||||
_shtab_ahriman_aur_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
_shtab_ahriman_aur_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
||||||
_shtab_ahriman_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
_shtab_ahriman_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
||||||
_shtab_ahriman_package_add__s_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
|
_shtab_ahriman_package_add__s_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
|
||||||
|
@ -81,6 +81,7 @@ _shtab_ahriman_options=(
|
|||||||
{-c,--configuration}"[configuration path]:configuration:"
|
{-c,--configuration}"[configuration path]:configuration:"
|
||||||
"--force[force run, remove file lock]"
|
"--force[force run, remove file lock]"
|
||||||
{-l,--lock}"[lock file]:lock:"
|
{-l,--lock}"[lock file]:lock:"
|
||||||
|
"--log-handler[explicit log handler specification. If none set, the handler will be guessed from environment]:log_handler:(console syslog journald)"
|
||||||
{--report,--no-report}"[force enable or disable reporting to web service]:report:"
|
{--report,--no-report}"[force enable or disable reporting to web service]:report:"
|
||||||
{-q,--quiet}"[force disable any logging]"
|
{-q,--quiet}"[force disable any logging]"
|
||||||
"--unsafe[allow to run ahriman as non-ahriman user. Some actions might be unavailable]"
|
"--unsafe[allow to run ahriman as non-ahriman user. Some actions might be unavailable]"
|
||||||
|
20
docs/faq.rst
20
docs/faq.rst
@ -391,7 +391,7 @@ The following environment variables are supported:
|
|||||||
* ``AHRIMAN_FORCE_ROOT`` - force run ahriman as root instead of guessing by subcommand.
|
* ``AHRIMAN_FORCE_ROOT`` - force run ahriman as root instead of guessing by subcommand.
|
||||||
* ``AHRIMAN_HOST`` - host for the web interface, default is ``0.0.0.0``.
|
* ``AHRIMAN_HOST`` - host for the web interface, default is ``0.0.0.0``.
|
||||||
* ``AHRIMAN_MULTILIB`` - if set (default) multilib repository will be used, disabled otherwise.
|
* ``AHRIMAN_MULTILIB`` - if set (default) multilib repository will be used, disabled otherwise.
|
||||||
* ``AHRIMAN_OUTPUT`` - controls logging handler, e.g. ``syslog``, ``console``. The name must be found in logging configuration. Note that if ``syslog`` (the default) handler is used you will need to mount ``/dev/log`` inside container because it is not available there.
|
* ``AHRIMAN_OUTPUT`` - controls logging handler, e.g. ``syslog``, ``console``. The name must be found in logging configuration. Note that if ``syslog`` handler is used you will need to mount ``/dev/log`` inside container because it is not available there.
|
||||||
* ``AHRIMAN_PACKAGER`` - packager name from which packages will be built, default is ``ahriman bot <ahriman@example.com>``.
|
* ``AHRIMAN_PACKAGER`` - packager name from which packages will be built, default is ``ahriman bot <ahriman@example.com>``.
|
||||||
* ``AHRIMAN_PACMAN_MIRROR`` - override pacman mirror server if set.
|
* ``AHRIMAN_PACMAN_MIRROR`` - override pacman mirror server if set.
|
||||||
* ``AHRIMAN_PORT`` - HTTP server port if any, default is empty.
|
* ``AHRIMAN_PORT`` - HTTP server port if any, default is empty.
|
||||||
@ -663,7 +663,7 @@ How to report by email
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
yay -S python-jinja
|
yay -S --asdeps python-jinja
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Configure the service:
|
Configure the service:
|
||||||
@ -690,7 +690,7 @@ How to generate index page for S3
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
yay -S python-jinja
|
yay -S --asdeps python-jinja
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Configure the service:
|
Configure the service:
|
||||||
@ -714,7 +714,7 @@ How to post build report to telegram
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
yay -S python-jinja
|
yay -S --asdeps python-jinja
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Register bot in telegram. You can do it by talking with `@BotFather <https://t.me/botfather>`_. For more details please refer to `official documentation <https://core.telegram.org/bots>`_.
|
Register bot in telegram. You can do it by talking with `@BotFather <https://t.me/botfather>`_. For more details please refer to `official documentation <https://core.telegram.org/bots>`_.
|
||||||
@ -838,7 +838,7 @@ How to setup web service
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
yay -S python-aiohttp python-aiohttp-jinja2 python-aiohttp-apispec>=3.0.0 python-aiohttp-cors
|
yay -S --asdeps python-aiohttp python-aiohttp-jinja2 python-aiohttp-apispec>=3.0.0 python-aiohttp-cors
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Configure service:
|
Configure service:
|
||||||
@ -859,7 +859,7 @@ How to enable basic authorization
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
yay -S python-aiohttp-security python-aiohttp-session python-cryptography
|
yay -S --asdeps python-aiohttp-security python-aiohttp-session python-cryptography
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Configure the service to enable authorization:
|
Configure the service to enable authorization:
|
||||||
@ -915,7 +915,7 @@ How to enable OAuth authorization
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
yay -S python-aiohttp-security python-aiohttp-session python-cryptography python-aioauth-client
|
yay -S --asdeps python-aiohttp-security python-aiohttp-session python-cryptography python-aioauth-client
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Configure the service:
|
Configure the service:
|
||||||
@ -1053,17 +1053,17 @@ It is automation tools for ``repoctl`` mentioned above. Except for using shell i
|
|||||||
How to check service logs
|
How to check service logs
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
By default, the service writes logs to ``/dev/log`` which can be accessed by using ``journalctl`` command (logs are written to the journal of the user under which command is run). In order to retrieve logs for the process you can use the following command:
|
By default, the service writes logs to ``journald`` which can be accessed by using ``journalctl`` command (logs are written to the journal of the user under which command is run). In order to retrieve logs for the process you can use the following command:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
sudo journalctl SYSLOG_IDENTIFIER=ahriman
|
sudo journalctl SYSLOG_IDENTIFIER=ahriman
|
||||||
|
|
||||||
You can also edit configuration and forward logs to ``stderr``, just change ``handlers`` value, e.g.:
|
You can also ask to forward logs to ``stderr``, just set ``--log-handler`` flag, e.g.:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
sed -i 's/handlers = journald_handler/handlers = console_handler/g' /etc/ahriman.ini.d/logging.ini
|
ahriman --log-handler console ...
|
||||||
|
|
||||||
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_. The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).
|
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_. The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).
|
||||||
|
|
||||||
|
@ -7,8 +7,7 @@ pkgdesc="ArcH linux ReposItory MANager"
|
|||||||
arch=('any')
|
arch=('any')
|
||||||
url="https://github.com/arcan1s/ahriman"
|
url="https://github.com/arcan1s/ahriman"
|
||||||
license=('GPL3')
|
license=('GPL3')
|
||||||
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-cerberus' 'python-inflection' 'python-passlib' 'python-requests'
|
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-cerberus' 'python-inflection' 'python-passlib' 'python-requests' 'python-srcinfo')
|
||||||
'python-srcinfo' 'python-systemd')
|
|
||||||
makedepends=('python-build' 'python-installer' 'python-wheel')
|
makedepends=('python-build' 'python-installer' 'python-wheel')
|
||||||
optdepends=('breezy: -bzr packages support'
|
optdepends=('breezy: -bzr packages support'
|
||||||
'darcs: -darcs packages support'
|
'darcs: -darcs packages support'
|
||||||
@ -25,6 +24,7 @@ optdepends=('breezy: -bzr packages support'
|
|||||||
'python-cryptography: web server with authorization'
|
'python-cryptography: web server with authorization'
|
||||||
'python-requests-unixsocket: client report to web server by unix socket'
|
'python-requests-unixsocket: client report to web server by unix socket'
|
||||||
'python-jinja: html report generation'
|
'python-jinja: html report generation'
|
||||||
|
'python-systemd: journal support'
|
||||||
'rsync: sync by using rsync'
|
'rsync: sync by using rsync'
|
||||||
'subversion: -svn packages support')
|
'subversion: -svn packages support')
|
||||||
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver-src.tar.xz"
|
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver-src.tar.xz"
|
||||||
|
@ -1,2 +1 @@
|
|||||||
d /var/lib/ahriman 0755 ahriman ahriman
|
d /var/lib/ahriman 0755 ahriman ahriman
|
||||||
d /var/log/ahriman 0755 ahriman ahriman
|
|
@ -8,13 +8,13 @@ keys = console_handler,journald_handler,syslog_handler
|
|||||||
keys = generic_format,syslog_format
|
keys = generic_format,syslog_format
|
||||||
|
|
||||||
[handler_console_handler]
|
[handler_console_handler]
|
||||||
class = StreamHandler
|
class = logging.StreamHandler
|
||||||
level = DEBUG
|
level = DEBUG
|
||||||
formatter = generic_format
|
formatter = generic_format
|
||||||
args = (sys.stderr,)
|
args = (sys.stderr,)
|
||||||
|
|
||||||
[handler_journald_handler]
|
[handler_journald_handler]
|
||||||
class = systemd.journal.JournalHandler
|
class = ahriman.core.log.journal_handler.JournalHandler
|
||||||
level = DEBUG
|
level = DEBUG
|
||||||
formatter = syslog_format
|
formatter = syslog_format
|
||||||
kwargs = {"SYSLOG_IDENTIFIER": "ahriman"}
|
kwargs = {"SYSLOG_IDENTIFIER": "ahriman"}
|
||||||
@ -27,20 +27,16 @@ args = ("/dev/log",)
|
|||||||
|
|
||||||
[formatter_generic_format]
|
[formatter_generic_format]
|
||||||
format = [%(levelname)s %(asctime)s] [%(name)s]: %(message)s
|
format = [%(levelname)s %(asctime)s] [%(name)s]: %(message)s
|
||||||
datefmt =
|
|
||||||
|
|
||||||
[formatter_syslog_format]
|
[formatter_syslog_format]
|
||||||
format = [%(levelname)s] [%(name)s]: %(message)s
|
format = [%(levelname)s] [%(name)s]: %(message)s
|
||||||
datefmt =
|
|
||||||
|
|
||||||
[logger_root]
|
[logger_root]
|
||||||
level = DEBUG
|
level = DEBUG
|
||||||
handlers = journald_handler
|
|
||||||
qualname = root
|
qualname = root
|
||||||
|
|
||||||
[logger_http]
|
[logger_http]
|
||||||
level = DEBUG
|
level = DEBUG
|
||||||
handlers = journald_handler
|
|
||||||
qualname = http
|
qualname = http
|
||||||
propagate = 0
|
propagate = 0
|
||||||
|
|
||||||
@ -51,24 +47,20 @@ qualname = stderr
|
|||||||
|
|
||||||
[logger_boto3]
|
[logger_boto3]
|
||||||
level = INFO
|
level = INFO
|
||||||
handlers = journald_handler
|
|
||||||
qualname = boto3
|
qualname = boto3
|
||||||
propagate = 0
|
propagate = 0
|
||||||
|
|
||||||
[logger_botocore]
|
[logger_botocore]
|
||||||
level = INFO
|
level = INFO
|
||||||
handlers = journald_handler
|
|
||||||
qualname = botocore
|
qualname = botocore
|
||||||
propagate = 0
|
propagate = 0
|
||||||
|
|
||||||
[logger_nose]
|
[logger_nose]
|
||||||
level = INFO
|
level = INFO
|
||||||
handlers = journald_handler
|
|
||||||
qualname = nose
|
qualname = nose
|
||||||
propagate = 0
|
propagate = 0
|
||||||
|
|
||||||
[logger_s3transfer]
|
[logger_s3transfer]
|
||||||
level = INFO
|
level = INFO
|
||||||
handlers = journald_handler
|
|
||||||
qualname = s3transfer
|
qualname = s3transfer
|
||||||
propagate = 0
|
propagate = 0
|
||||||
|
3
setup.py
3
setup.py
@ -121,6 +121,9 @@ setup(
|
|||||||
"sphinx-rtd-theme>=1.1.1", # https://stackoverflow.com/a/74355734
|
"sphinx-rtd-theme>=1.1.1", # https://stackoverflow.com/a/74355734
|
||||||
"sphinxcontrib-napoleon",
|
"sphinxcontrib-napoleon",
|
||||||
],
|
],
|
||||||
|
"journald": [
|
||||||
|
"systemd-python",
|
||||||
|
],
|
||||||
# FIXME technically this dependency is required, but in some cases we do not have access to
|
# FIXME technically this dependency is required, but in some cases we do not have access to
|
||||||
# the libalpm which is required in order to install the package. Thus in case if we do not
|
# the libalpm which is required in order to install the package. Thus in case if we do not
|
||||||
# really need to run the application we can move it to "optional" dependencies
|
# really need to run the application we can move it to "optional" dependencies
|
||||||
|
@ -30,6 +30,7 @@ from ahriman.application import handlers
|
|||||||
from ahriman.core.util import enum_values
|
from ahriman.core.util import enum_values
|
||||||
from ahriman.models.action import Action
|
from ahriman.models.action import Action
|
||||||
from ahriman.models.build_status import BuildStatusEnum
|
from ahriman.models.build_status import BuildStatusEnum
|
||||||
|
from ahriman.models.log_handler import LogHandler
|
||||||
from ahriman.models.package_source import PackageSource
|
from ahriman.models.package_source import PackageSource
|
||||||
from ahriman.models.sign_settings import SignSettings
|
from ahriman.models.sign_settings import SignSettings
|
||||||
from ahriman.models.user_access import UserAccess
|
from ahriman.models.user_access import UserAccess
|
||||||
@ -58,6 +59,7 @@ def _formatter(prog: str) -> argparse.HelpFormatter:
|
|||||||
return argparse.ArgumentDefaultsHelpFormatter(prog, width=120)
|
return argparse.ArgumentDefaultsHelpFormatter(prog, width=120)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
def _parser() -> argparse.ArgumentParser:
|
def _parser() -> argparse.ArgumentParser:
|
||||||
"""
|
"""
|
||||||
command line parser generator
|
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("--force", help="force run, remove file lock", action="store_true")
|
||||||
parser.add_argument("-l", "--lock", help="lock file", type=Path,
|
parser.add_argument("-l", "--lock", help="lock file", type=Path,
|
||||||
default=Path(tempfile.gettempdir()) / "ahriman.lock")
|
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",
|
parser.add_argument("--report", help="force enable or disable reporting to web service",
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
||||||
|
@ -94,7 +94,8 @@ class Handler:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
configuration = Configuration.from_path(args.configuration, architecture)
|
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):
|
with Lock(args, architecture, configuration):
|
||||||
cls.run(args, architecture, configuration, report=args.report, unsafe=args.unsafe)
|
cls.run(args, architecture, configuration, report=args.report, unsafe=args.unsafe)
|
||||||
return True
|
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
|
import logging
|
||||||
|
|
||||||
from logging.config import fileConfig
|
from logging.config import fileConfig
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.log.http_log_handler import HttpLogHandler
|
from ahriman.core.log.http_log_handler import HttpLogHandler
|
||||||
|
from ahriman.models.log_handler import LogHandler
|
||||||
|
|
||||||
|
|
||||||
class Log:
|
class Log:
|
||||||
@ -32,24 +34,65 @@ class Log:
|
|||||||
Attributes:
|
Attributes:
|
||||||
DEFAULT_LOG_FORMAT(str): (class attribute) default log format (in case of fallback)
|
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_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_FORMAT = "[%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s"
|
||||||
DEFAULT_LOG_LEVEL = logging.DEBUG
|
DEFAULT_LOG_LEVEL = logging.DEBUG
|
||||||
|
DEFAULT_SYSLOG_DEVICE = Path("/dev") / "log"
|
||||||
|
|
||||||
@staticmethod
|
@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
|
setup logging settings from configuration
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
configuration(Configuration): configuration instance
|
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
|
quiet(bool): force disable any log messages
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
|
default_handler = f"{handler.value}_handler"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
path = configuration.logging_path
|
log_configuration = Configuration()
|
||||||
fileConfig(path)
|
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:
|
except Exception:
|
||||||
logging.basicConfig(filename=None, format=Log.DEFAULT_LOG_FORMAT,
|
logging.basicConfig(filename=None, format=Log.DEFAULT_LOG_FORMAT,
|
||||||
level=Log.DEFAULT_LOG_LEVEL)
|
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"
|
@ -7,6 +7,7 @@ from pytest_mock import MockerFixture
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
|
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
|
||||||
|
from ahriman.models.log_handler import LogHandler
|
||||||
|
|
||||||
|
|
||||||
def test_architectures_extract(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_architectures_extract(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
@ -56,17 +57,20 @@ def test_call(args: argparse.Namespace, configuration: Configuration, mocker: Mo
|
|||||||
must call inside lock
|
must call inside lock
|
||||||
"""
|
"""
|
||||||
args.configuration = Path("")
|
args.configuration = Path("")
|
||||||
|
args.log_handler = LogHandler.Console
|
||||||
args.quiet = False
|
args.quiet = False
|
||||||
args.report = False
|
args.report = False
|
||||||
mocker.patch("ahriman.application.handlers.Handler.run")
|
mocker.patch("ahriman.application.handlers.Handler.run")
|
||||||
configuration_mock = mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
|
configuration_mock = mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
|
||||||
|
log_handler_mock = mocker.patch("ahriman.core.log.Log.handler", return_value=args.log_handler)
|
||||||
log_load_mock = mocker.patch("ahriman.core.log.Log.load")
|
log_load_mock = mocker.patch("ahriman.core.log.Log.load")
|
||||||
enter_mock = mocker.patch("ahriman.application.lock.Lock.__enter__")
|
enter_mock = mocker.patch("ahriman.application.lock.Lock.__enter__")
|
||||||
exit_mock = mocker.patch("ahriman.application.lock.Lock.__exit__")
|
exit_mock = mocker.patch("ahriman.application.lock.Lock.__exit__")
|
||||||
|
|
||||||
assert Handler.call(args, "x86_64")
|
assert Handler.call(args, "x86_64")
|
||||||
configuration_mock.assert_called_once_with(args.configuration, "x86_64")
|
configuration_mock.assert_called_once_with(args.configuration, "x86_64")
|
||||||
log_load_mock.assert_called_once_with(configuration, quiet=args.quiet, report=args.report)
|
log_handler_mock.assert_called_once_with(args.log_handler)
|
||||||
|
log_load_mock.assert_called_once_with(configuration, args.log_handler, quiet=args.quiet, report=args.report)
|
||||||
enter_mock.assert_called_once_with()
|
enter_mock.assert_called_once_with()
|
||||||
exit_mock.assert_called_once_with(None, None, None)
|
exit_mock.assert_called_once_with(None, None, None)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ from pytest_mock import MockerFixture
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.models.action import Action
|
from ahriman.models.action import Action
|
||||||
from ahriman.models.build_status import BuildStatusEnum
|
from ahriman.models.build_status import BuildStatusEnum
|
||||||
|
from ahriman.models.log_handler import LogHandler
|
||||||
from ahriman.models.sign_settings import SignSettings
|
from ahriman.models.sign_settings import SignSettings
|
||||||
from ahriman.models.user_access import UserAccess
|
from ahriman.models.user_access import UserAccess
|
||||||
|
|
||||||
@ -37,6 +38,14 @@ def test_parser_option_lock(parser: argparse.ArgumentParser) -> None:
|
|||||||
assert isinstance(args.lock, Path)
|
assert isinstance(args.lock, Path)
|
||||||
|
|
||||||
|
|
||||||
|
def test_parser_option_log_handler(parser: argparse.ArgumentParser) -> None:
|
||||||
|
"""
|
||||||
|
must convert log-handler option to LogHandler instance
|
||||||
|
"""
|
||||||
|
args = parser.parse_args(["--log-handler", "console", "service-config"])
|
||||||
|
assert isinstance(args.log_handler, LogHandler)
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_architectures(parser: argparse.ArgumentParser) -> None:
|
def test_multiple_architectures(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
must accept multiple architectures
|
must accept multiple architectures
|
||||||
|
31
tests/ahriman/core/log/test_journal_handler.py
Normal file
31
tests/ahriman/core/log/test_journal_handler.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
|
||||||
|
# because of how imports work it must be first test
|
||||||
|
def test_dummy_journal_handler(mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must import dummy journal handler if upstream systemd was not found
|
||||||
|
"""
|
||||||
|
mocker.patch.dict(sys.modules, {"systemd.journal": None})
|
||||||
|
from logging import NullHandler
|
||||||
|
from ahriman.core.log.journal_handler import JournalHandler
|
||||||
|
assert issubclass(JournalHandler, NullHandler)
|
||||||
|
|
||||||
|
|
||||||
|
def test_init() -> None:
|
||||||
|
"""
|
||||||
|
must init dummy handler
|
||||||
|
"""
|
||||||
|
from ahriman.core.log.journal_handler import _JournalHandler
|
||||||
|
assert _JournalHandler(42, answer=42)
|
||||||
|
|
||||||
|
|
||||||
|
def test_journal_handler() -> None:
|
||||||
|
"""
|
||||||
|
must import journal handler
|
||||||
|
"""
|
||||||
|
from systemd.journal import JournalHandler as UpstreamJournalHandler
|
||||||
|
from ahriman.core.log.journal_handler import JournalHandler
|
||||||
|
assert JournalHandler is UpstreamJournalHandler
|
@ -1,21 +1,59 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import pytest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from logging.config import fileConfig
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
from systemd.journal import JournalHandler
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.log import Log
|
from ahriman.core.log import Log
|
||||||
|
from ahriman.models.log_handler import LogHandler
|
||||||
|
|
||||||
|
|
||||||
|
def test_handler() -> None:
|
||||||
|
"""
|
||||||
|
must extract journald handler if available
|
||||||
|
"""
|
||||||
|
assert Log.handler(None) == LogHandler.Journald
|
||||||
|
|
||||||
|
|
||||||
|
def test_handler_selected() -> None:
|
||||||
|
"""
|
||||||
|
must return selected log handler
|
||||||
|
"""
|
||||||
|
assert Log.handler(LogHandler.Console) == LogHandler.Console
|
||||||
|
|
||||||
|
|
||||||
|
def test_handler_syslog(mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must return syslog handler if no journal is available
|
||||||
|
"""
|
||||||
|
mocker.patch("pathlib.Path.exists", return_value=True)
|
||||||
|
mocker.patch.dict(sys.modules, {"systemd.journal": None})
|
||||||
|
assert Log.handler(None) == LogHandler.Syslog
|
||||||
|
|
||||||
|
|
||||||
|
def test_handler_console(mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must return console handler if no journal is available and no log device was found
|
||||||
|
"""
|
||||||
|
mocker.patch("pathlib.Path.exists", return_value=False)
|
||||||
|
mocker.patch.dict(sys.modules, {"systemd.journal": None})
|
||||||
|
assert Log.handler(None) == LogHandler.Console
|
||||||
|
|
||||||
|
|
||||||
def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must load logging
|
must load logging
|
||||||
"""
|
"""
|
||||||
logging_mock = mocker.patch("ahriman.core.log.log.fileConfig")
|
logging_mock = mocker.patch("ahriman.core.log.log.fileConfig", side_effect=fileConfig)
|
||||||
http_log_mock = mocker.patch("ahriman.core.log.http_log_handler.HttpLogHandler.load")
|
http_log_mock = mocker.patch("ahriman.core.log.http_log_handler.HttpLogHandler.load")
|
||||||
|
|
||||||
Log.load(configuration, quiet=False, report=False)
|
Log.load(configuration, LogHandler.Journald, quiet=False, report=False)
|
||||||
logging_mock.assert_called_once_with(configuration.logging_path)
|
logging_mock.assert_called_once_with(pytest.helpers.anyvar(int), disable_existing_loggers=True)
|
||||||
http_log_mock.assert_called_once_with(configuration, report=False)
|
http_log_mock.assert_called_once_with(configuration, report=False)
|
||||||
|
assert all(isinstance(handler, JournalHandler) for handler in logging.getLogger().handlers)
|
||||||
|
|
||||||
|
|
||||||
def test_load_fallback(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_load_fallback(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
@ -23,7 +61,7 @@ def test_load_fallback(configuration: Configuration, mocker: MockerFixture) -> N
|
|||||||
must fall back to stderr without errors
|
must fall back to stderr without errors
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.log.log.fileConfig", side_effect=PermissionError())
|
mocker.patch("ahriman.core.log.log.fileConfig", side_effect=PermissionError())
|
||||||
Log.load(configuration, quiet=False, report=False)
|
Log.load(configuration, LogHandler.Journald, quiet=False, report=False)
|
||||||
|
|
||||||
|
|
||||||
def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
@ -31,5 +69,5 @@ def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None
|
|||||||
must disable logging in case if quiet flag set
|
must disable logging in case if quiet flag set
|
||||||
"""
|
"""
|
||||||
disable_mock = mocker.patch("logging.disable")
|
disable_mock = mocker.patch("logging.disable")
|
||||||
Log.load(configuration, quiet=True, report=False)
|
Log.load(configuration, LogHandler.Journald, quiet=True, report=False)
|
||||||
disable_mock.assert_called_once_with(logging.WARNING)
|
disable_mock.assert_called_once_with(logging.WARNING)
|
||||||
|
0
tests/ahriman/models/test_log_handler.py
Normal file
0
tests/ahriman/models/test_log_handler.py
Normal file
Loading…
Reference in New Issue
Block a user