From 737d41a352b243dbcfbfa4760982e92e33831e03 Mon Sep 17 00:00:00 2001 From: Jordan Blasenhauer Date: Fri, 2 Feb 2024 16:55:10 +0100 Subject: [PATCH] start implementing metrics *handle falsy 0 value on client *update client script to fit new format *update get_metrics function *fix main.py considering empty dict as error --- src/common/core/antibot/ui/actions.py | 2 +- src/common/core/antibot/ui/template.html | 2 +- src/ui/main.py | 6 +-- src/ui/src/Instances.py | 55 +++++++++++++++++++----- src/ui/static/js/plugins/setup.js | 7 ++- 5 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/common/core/antibot/ui/actions.py b/src/common/core/antibot/ui/actions.py index 9de794980..be7c4748c 100644 --- a/src/common/core/antibot/ui/actions.py +++ b/src/common/core/antibot/ui/actions.py @@ -1,2 +1,2 @@ def antibot(): - return {"message": "ok", "data": {"info": "test", "count": 24}} + return {"counter_failed_challenges": 0} diff --git a/src/common/core/antibot/ui/template.html b/src/common/core/antibot/ui/template.html index 7bd242a34..6cc57a3a8 100644 --- a/src/common/core/antibot/ui/template.html +++ b/src/common/core/antibot/ui/template.html @@ -76,7 +76,7 @@ value: "{{ plugin['description'] or ''}}", type: "text", }, - count: { + counter_failed_challenges: { el: document.querySelector("[data-count]"), value: "unknown", type: "text", diff --git a/src/ui/main.py b/src/ui/main.py index 3fd53d4ee..641a6be65 100755 --- a/src/ui/main.py +++ b/src/ui/main.py @@ -1260,6 +1260,7 @@ def upload_plugin(): @login_required def custom_plugin(plugin: str): plugins = app.config["CONFIG"].get_plugins() + curr_plugin = {} for plug in plugins: if plug["id"] == plugin: @@ -1334,16 +1335,15 @@ def custom_plugin(plugin: str): sys_modules.pop("actions") del actions - if message or not res or not isinstance(res, dict): + if message or not isinstance(res, dict) and not res: message = message or f'The plugin "{plugin}" did not return a valid response' if error: app.logger.exception(message) else: app.logger.error(message) - return {"message": message}, error or 500 app.logger.info(f"Plugin {plugin} action executed successfully") - return {"message": "ok", "data": res}, 200 + return jsonify({"message": "ok", "data": res}), 200 @app.route("/cache", methods=["GET"]) diff --git a/src/ui/src/Instances.py b/src/ui/src/Instances.py index c604f1442..07db38cc0 100644 --- a/src/ui/src/Instances.py +++ b/src/ui/src/Instances.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 - from os import sep from os.path import join from pathlib import Path @@ -118,8 +117,8 @@ class Instance: def reports(self) -> Tuple[bool, dict[str, Any]]: return self.apiCaller.send_to_apis("GET", "/metrics/requests", response=True) - def metrics(self, plugin_id, metric) -> Tuple[bool, dict[str, Any]]: - return self.apiCaller.send_to_apis("GET", f"/metrics/{plugin_id}/{metric}", response=True) + def metrics(self, plugin_id) -> Tuple[bool, dict[str, Any]]: + return self.apiCaller.send_to_apis("GET", f"/metrics/{plugin_id}", response=True) class Instances: @@ -372,17 +371,53 @@ class Instances: return reports - def get_metrics(self, plugin_id: str, metric: str): - metrics: List[dict[str, Any]] = [] + def get_metrics(self, plugin_id: str): + # Get metrics from all instances + metrics = {} for instance in self.get_instances(): - try: - resp, instance_metrics = instance.metrics(plugin_id, metric) - except: - continue + resp, instance_metrics = instance.metrics(plugin_id) + # filters if not resp: continue - metrics.extend(instance_metrics[instance.name if instance.name != "local" else "127.0.0.1"].get("msg", [])) + if not instance.name in instance_metrics or instance_metrics[instance.name]["msg"] is None or instance_metrics[instance.name]["msg"] is not dict or instance_metrics[instance.name]["status"] != "success": + continue + + metric_data = instance_metrics[instance.name]["msg"] + + # Update metrics looking for value type + for key, value in metric_data.items(): + if key not in metrics: + metrics[key] = value + continue + + # Case value is number, add it to the existing value + if isinstance(value, (int, float)): + metrics[key] += value + continue + # Case value is string, replace the existing value + elif isinstance(value, str): + metrics[key] = value + continue + # Case value is list, extend it to the existing value + if isinstance(value, list): + metrics[key].extend(value) + continue + # Case value is a dict, loop on it and update the existing value + if isinstance(value, dict): + for k, v in value.items(): + if k not in metrics[key]: + metrics[key][k] = v + continue + if isinstance(v, (int, float)): + metrics[key][k] += v + continue + if isinstance(v, list): + metrics[key][k].extend(v) + continue + if isinstance(v, str): + metrics[key][k] = v + continue return metrics diff --git a/src/ui/static/js/plugins/setup.js b/src/ui/static/js/plugins/setup.js index 685658d0e..9a99eb789 100644 --- a/src/ui/static/js/plugins/setup.js +++ b/src/ui/static/js/plugins/setup.js @@ -54,7 +54,7 @@ class SetupPlugin { .then((res) => res.json()) .then((res) => { // Update data and DOM - this.getFetchDataByKey(res.data.data); + this.getFetchDataByKey(res.data); this.updateDataDOM(); // Show hidden elements this.showSuccessEls(); @@ -154,7 +154,10 @@ class SetupPlugin { // Key of fetch data need to match key of this.data getFetchDataByKey(fetchDataObj) { for (const [key, value] of Object.entries(this.data)) { - value["value"] = fetchDataObj[key] || value["value"] || ""; + value["value"] = + fetchDataObj[key] == 0 + ? "0" + : fetchDataObj[key] || value["value"] || ""; } }