From 0af2042cec23af2a9d646c9e96ace24cfe799c68 Mon Sep 17 00:00:00 2001 From: wsw70 <1345886+wsw70@users.noreply.github.com> Date: Mon, 20 May 2024 20:06:30 +0200 Subject: [PATCH] new logger to dump a JSON file with all attributes --- docs/loggers/json_full.rst | 12 ++++++++ simplemonitor/Loggers/file.py | 55 ++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 docs/loggers/json_full.rst diff --git a/docs/loggers/json_full.rst b/docs/loggers/json_full.rst new file mode 100644 index 00000000..2092d14a --- /dev/null +++ b/docs/loggers/json_full.rst @@ -0,0 +1,12 @@ +json_full - write a full JSON status file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Writes the status of monitors to a JSON file. +This file includes all serializable data from a monitor instance and all dates are in plain ISO format. + +.. confval:: filename + + :type: string + :required: true + + the filename to write to diff --git a/simplemonitor/Loggers/file.py b/simplemonitor/Loggers/file.py index 2b77bb03..b6c135be 100644 --- a/simplemonitor/Loggers/file.py +++ b/simplemonitor/Loggers/file.py @@ -18,6 +18,8 @@ import arrow from jinja2 import Environment, FileSystemLoader, select_autoescape +import jsonpickle + from ..Monitors.monitor import Monitor from ..util import ( copy_if_different, @@ -29,7 +31,7 @@ from .logger import Logger, register if TYPE_CHECKING: - import datetime + pass @register @@ -544,3 +546,54 @@ def process_batch(self) -> None: def describe(self) -> str: return "Writing JSON file to {0}".format(self.filename) + + +@register +class JsonLoggerFull(Logger): + """Write monitor status to a full JSON file.""" + + logger_type = "json_full" + filename = "" # type: str + supports_batch = True + + def __init__(self, config_options: Optional[dict] = None) -> None: + if config_options is None: + config_options = {} + super().__init__(config_options) + self.filename = self.get_config_option( + "filename", required=True, allow_empty=False + ) + + def save_result2(self, name: str, monitor: Monitor) -> None: + if self.batch_data is None: + self.batch_data = {} + result = MonitorResult() + for k, v in vars(monitor).items(): + # remove built-in attributes + if k.startswith("__"): + continue + # remove attributes that are not JSON serializable + if not isinstance(v, (str, int, float, bool, dict, list)): + continue + # handle arrow dates + if isinstance(v, arrow.Arrow): + v = v.isoformat() + result.__setattr__(k, v) + # transform some attributes per the original JSON logger + if hasattr(monitor, "was_skipped") and monitor.was_skipped: + result.status = "Skipped" + elif monitor.virtual_fail_count() <= 0: + result.status = "OK" + self.batch_data[name] = result + + def process_batch(self) -> None: + payload = MonitorJsonPayload() + payload.generated = arrow.now().isoformat() + if self.batch_data is not None: + payload.monitors = self.batch_data + with open(self.filename, "w") as f: + f.write(jsonpickle.encode(payload, unpicklable=False)) + self.batch_data = {} + + def describe(self) -> str: + return "Writing full JSON file to {0}".format(self.filename)