From 6314354fd43f58a0267ae4c40d61ad030a98b856 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Fri, 8 Jul 2016 07:28:25 +0200 Subject: [PATCH] Use built-in 'logging' module for logging. Add Logger.init_logging function to initialize logging according to config file. --- rida.conf | 15 ++++++--- rida.py | 8 ++++- rida/config.py | 27 +++++++++++++++ rida/logger.py | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ rida/logging.py | 26 --------------- 5 files changed, 134 insertions(+), 31 deletions(-) create mode 100644 rida/logger.py delete mode 100644 rida/logging.py diff --git a/rida.conf b/rida.conf index 3d9df27b..b5ba4c23 100644 --- a/rida.conf +++ b/rida.conf @@ -11,8 +11,15 @@ rpms_allow_repository = False rpms_default_cache = http://pkgs.stg.fedoraproject.org/repo/pkgs/ rpms_allow_cache = False -ssl_certificate_file=server.crt -ssl_certificate_key_file=server.key -ssl_ca_certificate_file=cacert.pem +ssl_certificate_file = server.crt +ssl_certificate_key_file = server.key +ssl_ca_certificate_file = cacert.pem -pkgdb_api_url=https://admin.stg.fedoraproject.org/pkgdb/api +pkgdb_api_url = https://admin.stg.fedoraproject.org/pkgdb/api + +# Path to log file or "console" for console output or "journal" for +# output to "journald" daemon. +log_file = console + +# Available log levels are: debug, info, warn, error +log_level = info diff --git a/rida.py b/rida.py index 00e79cde..b8cb469b 100755 --- a/rida.py +++ b/rida.py @@ -36,7 +36,8 @@ This is the implementation of the orchestrator's public RESTful API. # TODO: Emit messages about module submission. from flask import Flask, request -from rida import config, database, messaging, auth +from rida import config, database, messaging, auth, logger +import logging import json import modulemd import ssl @@ -46,6 +47,8 @@ app.config.from_envvar("RIDA_SETTINGS", silent=True) # TODO: Load the config file from environment conf = config.from_file("rida.conf") +logger.init_logging(conf) + db = database.Database() @app.route("/rida/module-builds/", methods=["POST"]) @@ -103,6 +106,8 @@ def submit_build(): backend=conf.messaging, ) + logging.info("%s submitted build of %s", username, mmd.name) + # XXX: Okay, we're pretending here... return json.dumps(module.json()), 201 @@ -133,6 +138,7 @@ def query_build(id): return "No such module found.", 404 if __name__ == "__main__": + logging.info("Starting Rida") ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) ssl_ctx.load_cert_chain(conf.ssl_certificate_file, conf.ssl_certificate_key_file) diff --git a/rida/config.py b/rida/config.py index 85fbd241..9dbd4554 100644 --- a/rida/config.py +++ b/rida/config.py @@ -28,6 +28,7 @@ import os.path import configparser import json +from rida import logger def from_file(filename=None): """Create the configuration instance from a file. @@ -62,6 +63,9 @@ def from_file(filename=None): conf.ssl_ca_certificate_file = default.get("ssl_ca_certificate_file") conf.pkgdb_api_url = default.get("pkgdb_api_url") + + conf.log_file = default.get("log_file") + conf.log_level = default.get("log_level") return conf class Config(object): @@ -82,6 +86,8 @@ class Config(object): self._ssl_certificate_key_file = "" self._ssl_ca_certificate_file = "" self._pkgdb_api_url = "" + self._log_file = "" + self._log_level = 0 @property def system(self): @@ -212,3 +218,24 @@ class Config(object): @pkgdb_api_url.setter def pkgdb_api_url(self, s): self._pkgdb_api_url = str(s) + + @property + def log_file(self): + return self._log_file + + @log_file.setter + def log_file(self, s): + if s == None: + self.log_file = "" + else: + self._log_file = str(s) + + @property + def log_level(self): + return self._log_level + + @log_level.setter + def log_level(self, s): + level = str(s).lower() + self._log_level = logger.str_to_log_level(level) + diff --git a/rida/logger.py b/rida/logger.py new file mode 100644 index 00000000..f39b2e21 --- /dev/null +++ b/rida/logger.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + + +# Copyright (c) 2016 Red Hat, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Written by Petr Šabata + +""" +Logging functions. + +At the beginning of the Rida flow, init_logging(conf) must be called. + +After that, logging from any module is possible using Python's "logging" +module as showed at +. + +Examples: + +import logging + +logging.debug("Phasers are set to stun.") +logging.info("%s tried to build something", username) +logging.warn("%s failed to build", build_id) + +""" + +import logging + +levels = {} +levels["debug"] = logging.DEBUG +levels["error"] = logging.ERROR +levels["warning"] = logging.WARNING +levels["info"] = logging.INFO + +def str_to_log_level(level): + """ + Returns internal representation of logging level defined + by the string `level`. + + Available levels are: debug, info, warning, error + """ + if not level in levels: + return logging.NOTSET + + return levels[level] + +def init_logging(conf): + """ + Initializes logging according to configuration file. + """ + log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' + + log_file = conf.log_file + if not log_file or len(log_file) == 0 or log_file == "console": + logging.basicConfig(level = conf.log_level, format = log_format) + log = logging.getLogger() + log.setLevel(conf.log_level) + elif log_file == "journal": + logging.basicConfig(level = conf.log_level, format = log_format) + try: + from systemd import journal + except: + raise ValueError("systemd.journal module is not installed") + + log = logging.getLogger() + log.propagate = False + log.addHandler(journal.JournalHandler()) + else: + logging.basicConfig(filename = conf.log_file, level = conf.log_level, + format = log_format) + log = logging.getLogger() diff --git a/rida/logging.py b/rida/logging.py deleted file mode 100644 index d28da99f..00000000 --- a/rida/logging.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- - - -# Copyright (c) 2016 Red Hat, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# Written by Petr Šabata - -"""Logging functions."""