]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
kresctl: metrics: support for new API
authorAleš Mrázek <ales.mrazek@nic.cz>
Thu, 21 Mar 2024 14:19:50 +0000 (15:19 +0100)
committerAleš Mrázek <ales.mrazek@nic.cz>
Mon, 15 Apr 2024 14:28:37 +0000 (16:28 +0200)
doc/user/manager-client.rst
manager/knot_resolver_manager/cli/cmd/metrics.py
manager/knot_resolver_manager/cli/command.py

index 70c69aeb821a21a766eb16675641520cb7fe29ed..f21a69a7d2ca88d936b6e780dc440a9561e4ce48 100644 (file)
@@ -159,19 +159,24 @@ single ``kresctl`` command.
 
 .. option:: metrics
 
-    Reads aggregated metrics data in Prometheus format directly from the running
-    resolver.
+    Get aggregated metrics from the running resolver in JSON format (default) or optionally in Prometheus format.
+    The ``prometheus-client`` Python package needs to be installed if you wish to use the Prometheus format.
 
-    Requires a connection to the management API.
+    Requires a connection to the management HTTP API.
+
+    .. option:: --prometheus
+
+        Get metrics in Prometheus format if dependencies are met in the resolver.
 
     .. option:: [file]
 
-        Optional. The file into which Prometheus metrics will be exported.
+        Optional. The file into which metrics will be exported.
         If not specified, the metrics are printed into ``stdout``.
 
     .. code-block:: bash
 
-        $ kresctl metrics ./metrics/data.txt
+        $ kresctl metrics ./kres-metrics.json
+        $ kresctl metrics --prometheus
 
 .. option:: cache clear
 
index 64237ce4989dbbcfe4b0579403fd02e0e7d78166..c535186ef131f223496951538376cc51218facf2 100644 (file)
@@ -3,6 +3,7 @@ import sys
 from typing import List, Optional, Tuple, Type
 
 from knot_resolver_manager.cli.command import Command, CommandArgs, CompWords, register_command
+from knot_resolver_manager.utils.modeling.parsing import DataFormat, parse_json
 from knot_resolver_manager.utils.requests import request
 
 
@@ -10,6 +11,7 @@ from knot_resolver_manager.utils.requests import request
 class MetricsCommand(Command):
     def __init__(self, namespace: argparse.Namespace) -> None:
         self.file: Optional[str] = namespace.file
+        self.prometheus: bool = namespace.prometheus
 
         super().__init__(namespace)
 
@@ -17,10 +19,24 @@ class MetricsCommand(Command):
     def register_args_subparser(
         subparser: "argparse._SubParsersAction[argparse.ArgumentParser]",
     ) -> Tuple[argparse.ArgumentParser, "Type[Command]"]:
-        metrics = subparser.add_parser("metrics", help="get prometheus metrics data")
+        metrics = subparser.add_parser(
+            "metrics",
+            help="Get aggregated metrics from the running resolver in JSON format (default) or optionally in Prometheus format."
+            "\nThe 'prometheus-client' Python package needs to be installed if you wish to use the Prometheus format."
+            "\nRequires a connection to the management HTTP API.",
+        )
+
+        metrics.add_argument(
+            "--prometheus",
+            help="Get metrics in Prometheus format if dependencies are met in the resolver.",
+            action="store_true",
+            default=False,
+        )
+
         metrics.add_argument(
             "file",
-            help="Optional, file where to export Prometheus metrics. If not specified, the metrics are printed.",
+            help="Optional. The file into which metrics will be exported."
+            "\nIf not specified, the metrics are printed into stdout.",
             nargs="?",
             default=None,
         )
@@ -31,14 +47,19 @@ class MetricsCommand(Command):
         return {}
 
     def run(self, args: CommandArgs) -> None:
-        response = request(args.socket, "GET", "metrics")
+        response = request(args.socket, "GET", "metrics/prometheus" if self.prometheus else "metrics/json")
 
         if response.status == 200:
+            if self.prometheus:
+                metrics = response.body
+            else:
+                metrics = DataFormat.JSON.dict_dump(parse_json(response.body), indent=4)
+
             if self.file:
                 with open(self.file, "w") as f:
-                    f.write(response.body)
+                    f.write(metrics)
             else:
-                print(response.body)
+                print(metrics)
         else:
             print(response, file=sys.stderr)
             sys.exit(1)
index e2f6811fe1a7f8feac8f334963917e1393b508c8..72154a40887168e6f6d2295dd644cb162148f56a 100644 (file)
@@ -58,7 +58,7 @@ def get_socket_from_config(config: Path, optional_file: bool) -> Optional[Socket
                 )
         return None
     except ValueError as e:
-        raise DataValidationError(*e.args) from e
+        raise DataValidationError(*e.args) from e  # pylint: disable=no-value-for-parameter
     except OSError as e:
         if not optional_file:
             raise e