diff --git a/plinth/__main__.py b/plinth/__main__.py index ec71646e6..b236bed78 100644 --- a/plinth/__main__.py +++ b/plinth/__main__.py @@ -22,7 +22,6 @@ import logging import os import stat import sys -import warnings import axes import cherrypy @@ -31,7 +30,7 @@ import django.core.management import django.core.wsgi from django.contrib.messages import constants as message_constants -from plinth import cfg, frontpage, menu, module_loader, service, setup +from . import cfg, frontpage, log, menu, module_loader, service, setup axes.default_app_config = "plinth.axes_app_config.AppConfig" precedence_commandline_arguments = ["server_dir", "develop"] @@ -67,23 +66,6 @@ def parse_arguments(): return parser.parse_args() -def setup_logging(): - """Setup logging framework""" - # Remove default handlers and let the log message propagate to root logger. - for cherrypy_logger in [cherrypy.log.error_log, cherrypy.log.access_log]: - for handler in list(cherrypy_logger.handlers): - cherrypy_logger.removeHandler(handler) - - # Capture all Python warnings such as deprecation warnings - logging.captureWarnings(True) - - # Log all deprecation warnings when in develop mode - if cfg.develop: - warnings.filterwarnings('default', '', DeprecationWarning) - warnings.filterwarnings('default', '', PendingDeprecationWarning) - warnings.filterwarnings('default', '', ImportWarning) - - def _mount_static_directory(static_dir, static_url): config = { '/': { @@ -93,10 +75,7 @@ def _mount_static_directory(static_dir, static_url): } } app = cherrypy.tree.mount(None, static_url, config) - # Don't log requests for static files as they are rarely useful. - app.log.access_log.propagate = False - app.log.error_log.propagate = False - + log.setup_cherrypy_static_directory(app) logger.debug('Serving static directory %s on %s', static_dir, static_url) @@ -155,38 +134,6 @@ def on_server_stop(): def configure_django(): """Setup Django configuration in the absence of .settings file""" - logging_configuration = { - 'version': 1, - 'disable_existing_loggers': False, - 'formatters': { - 'default': { - 'format': - '%(name)-14s %(levelname)-8s %(message)s', - } - }, - 'handlers': { - 'console': { - 'class': 'logging.StreamHandler', - 'formatter': 'default' - } - }, - 'root': { - 'handlers': ['console'], - 'level': 'DEBUG' if cfg.develop else 'INFO' - } - } - - try: - importlib.import_module('systemd.journal') - except ModuleNotFoundError: - pass - else: - logging_configuration['handlers']['journal'] = { - 'class': 'systemd.journal.JournalHandler' - } - logging_configuration['root']['handlers'].append('journal') - - templates = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', @@ -267,7 +214,7 @@ def configure_django(): FORCE_SCRIPT_NAME=cfg.server_dir, INSTALLED_APPS=applications, IPWARE_META_PRECEDENCE_ORDER=('HTTP_X_FORWARDED_FOR', ), - LOGGING=logging_configuration, + LOGGING=log.get_configuration(), LOGIN_URL='users:login', LOGIN_REDIRECT_URL='index', MESSAGE_TAGS={message_constants.ERROR: 'danger'}, @@ -393,7 +340,7 @@ def main(): adapt_config(arguments) - setup_logging() + log.init() service.init() diff --git a/plinth/log.py b/plinth/log.py new file mode 100644 index 000000000..1ed8cdcfa --- /dev/null +++ b/plinth/log.py @@ -0,0 +1,89 @@ +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Setup logging for the application. +""" + +import importlib +import logging +import warnings + +import cherrypy + +from . import cfg + + +def init(): + """Setup the logging framework.""" + # Remove default handlers and let the log message propagate to root logger. + for cherrypy_logger in [cherrypy.log.error_log, cherrypy.log.access_log]: + for handler in list(cherrypy_logger.handlers): + cherrypy_logger.removeHandler(handler) + + # Capture all Python warnings such as deprecation warnings + logging.captureWarnings(True) + + # Log all deprecation warnings when in develop mode + if cfg.develop: + warnings.filterwarnings('default', '', DeprecationWarning) + warnings.filterwarnings('default', '', PendingDeprecationWarning) + warnings.filterwarnings('default', '', ImportWarning) + + +def setup_cherrypy_static_directory(app): + """Hush output from cherrypy static file request logging. + + Static file serving logs are hardly useful. + """ + app.log.access_log.propagate = False + app.log.error_log.propagate = False + + +def get_configuration(): + """Return the main python logging module configuration.""" + configuration = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'default': { + 'format': + '%(name)-14s %(levelname)-8s %(message)s', + } + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'formatter': 'default' + } + }, + 'root': { + 'handlers': ['console'], + 'level': 'DEBUG' if cfg.develop else 'INFO' + } + } + + try: + importlib.import_module('systemd.journal') + except ModuleNotFoundError: + pass + else: + configuration['handlers']['journal'] = { + 'class': 'systemd.journal.JournalHandler' + } + configuration['root']['handlers'].append('journal') + + return configuration