diff --git a/CHANGELOG.md b/CHANGELOG.md index 455c45a5297e95c456a6eac64d846190ef94a4fa..e4c3fda811f838a6f83090e271f5ac5bddda9fa7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed ### -- the suppression module is now a logging filter +- The suppression module is now a logging filter. +- The WebUIHandler is now a python logging formatter. - instead of `get_entity`, type-specific functions are used in `cfood.py` when the type of the entity in question is known. - Logger is used instead of `print` for errors in `crawler.py`. diff --git a/src/caosadvancedtools/serverside/helper.py b/src/caosadvancedtools/serverside/helper.py index e824c409b42acf9ccf0bfe0fae93707ed5037851..a09e6cfe867211e27fde8675d83d6b21bd14d456 100644 --- a/src/caosadvancedtools/serverside/helper.py +++ b/src/caosadvancedtools/serverside/helper.py @@ -23,7 +23,6 @@ from __future__ import absolute_import import argparse import datetime import json -import logging import sys import caosdb as db @@ -141,75 +140,6 @@ def print_error(text): print_bootstrap("<b>ERROR:</b> " + text, kind="danger", file=sys.stderr) -class WebUI_Handler(logging.StreamHandler): - """ allows to make logging to be nicely displayed in the WebUI - - You can enable this as follows: - logger = logging.getLogger("<LoggerName>") - logger.addHandler(WebUI_Handler()) - """ - - def __init__(self, *args, full_file=None, **kwargs): - super().__init__(*args, **kwargs) - self.max_elements = 100 - self.counter = 0 - self.full_file = full_file - - def format(self, record): - """ Return the HTML formatted log record for display on a website. - - Implementation of the format function as defined by - logging.StreamHandler. - - - Parameters - ---------- - - record : - - Raises - ------ - RuntimeError - If the log level of the record is not supported. Supported log - levels include logging.DEBUG, logging.INFO, logging.WARNING, - logging.ERROR, and logging.CRITICAL. - - Returns - ------- - str - The formatted log record. - - """ - self.counter += 1 - - if self.counter == self.max_elements: - return wrap_bootstrap_alert( - "<b>Warning:</b> Due to the large number of messages, the " - "output is stopped here. You can see the full log " - " <a href='{}'>here</a>.".format(self.full_file), - kind="warning") - - if self.counter > self.max_elements: - return "" - - text = str(record.getMessage()).replace("\n", r"</br>") - text = text.replace("\t", r" "*4) - - if record.levelno == logging.DEBUG: - return wrap_bootstrap_alert(str(record.getMessage()), kind="info") - elif record.levelno == logging.INFO: - return wrap_bootstrap_alert("<b>Info:</b> " + text, kind="info") - elif record.levelno == logging.WARNING: - return wrap_bootstrap_alert("<b>Warning:</b> " + text, kind="warning") - elif record.levelno == logging.ERROR: - return wrap_bootstrap_alert("<b>ERROR:</b> " + text, kind="danger") - elif record.levelno == logging.CRITICAL: - return wrap_bootstrap_alert("<b>CRITICAL ERROR:</b> " + text, kind="danger") - else: - raise RuntimeError("Unsupported log level: {}".format(record.levelno)) - - - class DataModelError(RuntimeError): """DataModelError indicates that the server-side script cannot work as intended due to missing datat model entities or an otherwise incompatible diff --git a/src/caosadvancedtools/webui_formatter.py b/src/caosadvancedtools/webui_formatter.py new file mode 100644 index 0000000000000000000000000000000000000000..c3c5381d96e86a2698cc16d1bf1a2726566dcd7b --- /dev/null +++ b/src/caosadvancedtools/webui_formatter.py @@ -0,0 +1,95 @@ +# encoding: utf-8 +# +# Copyright (C) 2019, 2020 IndiScale GmbH <info@indiscale.com> +# Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> +# Copyright (C) 2019, 2020 Henrik tom Wörden <h.tomwoerden@indiscale.com> +# +# 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 <https://www.gnu.org/licenses/>. +# +# +import logging + +from .serverside.helper import wrap_bootstrap_alert + + +class WebUI_Formatter(logging.Formatter): + """ allows to make logging to be nicely displayed in the WebUI + + You can enable this as follows: + logger = logging.getLogger("<LoggerName>") + formatter = WebUI_Formatter(full_file="path/to/file") + handler = logging.Handler() + handler.setFormatter(formatter) + logger.addHandler(handler) + """ + + def __init__(self, *args, full_file=None, **kwargs): + super().__init__(*args, **kwargs) + self.max_elements = 100 + self.counter = 0 + self.full_file = full_file + + def format(self, record): + """ Return the HTML formatted log record for display on a website. + + This essentially wraps the text formatted by the parent class in html. + + Parameters + ---------- + + record : + + Raises + ------ + RuntimeError + If the log level of the record is not supported. Supported log + levels include logging.DEBUG, logging.INFO, logging.WARNING, + logging.ERROR, and logging.CRITICAL. + + Returns + ------- + str + The formatted log record. + + """ + msg = super().format(record) + self.counter += 1 + + if self.counter == self.max_elements: + return wrap_bootstrap_alert( + "<b>Warning:</b> Due to the large number of messages, the " + "output is stopped here. You can see the full log " + " <a href='{}'>here</a>.".format(self.full_file), + kind="warning") + + if self.counter > self.max_elements: + return "" + + text = msg.replace("\n", r"</br>") + text = text.replace("\t", r" "*4) + + if record.levelno == logging.DEBUG: + return wrap_bootstrap_alert(msg, kind="info") + elif record.levelno == logging.INFO: + return wrap_bootstrap_alert("<b>Info:</b> " + text, kind="info") + elif record.levelno == logging.WARNING: + return wrap_bootstrap_alert("<b>Warning:</b> " + text, + kind="warning") + elif record.levelno == logging.ERROR: + return wrap_bootstrap_alert("<b>ERROR:</b> " + text, kind="danger") + elif record.levelno == logging.CRITICAL: + return wrap_bootstrap_alert("<b>CRITICAL ERROR:</b> " + text, + kind="danger") + else: + raise Exception("unknown level")