fixeria has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/41099?usp=email )


Change subject: [REST] Implement MetricsList
......................................................................

[REST] Implement MetricsList

Change-Id: I43114aa8f5f8a388dd6a436f83ad1ee97f1d2ab1
Related: SYS#7066
---
M contrib/openapi.yaml
M contrib/osmo-s1gw-cli.py
M priv/openapi.json
M src/rest_server.erl
4 files changed, 221 insertions(+), 3 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/erlang/osmo-s1gw 
refs/changes/99/41099/1

diff --git a/contrib/openapi.yaml b/contrib/openapi.yaml
index c7f7ec8..696e7a2 100644
--- a/contrib/openapi.yaml
+++ b/contrib/openapi.yaml
@@ -4,5 +4,52 @@
   title: 'OsmoS1GW REST interface'

 paths:
+  /metrics-list:
+    get:
+      summary: Get a list of metrics
+      operationId: MetricsList
+      parameters:
+        - name: type
+          in: query
+          description: Metric type
+          required: false
+          schema:
+            type: string
+            enum: [all, counter, gauge]
+            default: all
+        - name: path
+          in: query
+          description: Metrics path
+          required: false
+          schema:
+            type: string
+            example: s1ap.proxy
+      responses:
+        '200':
+          description: A list of metrics
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/MetricsList'

 components:
+  schemas:
+    MetricsList:
+      type: array
+      items:
+        $ref: '#/components/schemas/MetricsItem'
+
+    MetricsItem:
+      type: object
+      required:
+        - type
+        - name
+        - value
+      properties:
+        type:
+          type: string
+          enum: [counter, gauge]
+        name:
+          type: string
+        value:
+          type: integer
diff --git a/contrib/osmo-s1gw-cli.py b/contrib/osmo-s1gw-cli.py
index 7d13b08..9888ee9 100755
--- a/contrib/osmo-s1gw-cli.py
+++ b/contrib/osmo-s1gw-cli.py
@@ -73,10 +73,20 @@
         with self.send_get_req('swagger/spec.json') as f:
             return json.load(f)

+    def metrics_list(self, type: str = 'all', path: str = '') -> RESTResponse:
+        ''' MetricsList :: Get a list of metrics '''
+        query = {'type' : type}
+        if path:
+            query['path'] = path
+        with self.send_get_req('metrics-list', query) as f:
+            return json.load(f)
+

 class OsmoS1GWCli(cmd2.Cmd):
     DESC = 'Interactive CLI for OsmoS1GW'

+    CAT_METRICS = 'Metrics commands'
+
     def __init__(self, argv):
         super().__init__(allow_cli_args=False, include_py=True)

@@ -99,6 +109,31 @@
         spec = self.iface.fetch_spec()
         self.poutput(json.dumps(spec, indent=4))

+    @staticmethod
+    def metrics_list_item(item: dict) -> dict:
+        return {
+            'Name': item.get('name'),
+            'Type': item.get('type'),
+            'Value': item.get('value'),
+        }
+
+    metrics_list_parser = cmd2.Cmd2ArgumentParser()
+    metrics_list_parser.add_argument('-t', '--type',
+                                     type=str, default='all',
+                                     choices=('all', 'counter', 'gauge'),
+                                     help='Metric type (default: %(default)s)')
+    metrics_list_parser.add_argument('PATH',
+                                     type=str, default='', nargs='?',
+                                     help='Metric path')
+
+    @cmd2.with_argparser(metrics_list_parser)
+    @cmd2.with_category(CAT_METRICS)
+    def do_metrics_list(self, opts) -> None:
+        ''' Get a list of metrics '''
+        data = self.iface.metrics_list(opts.type, opts.PATH)
+        self.poutput(tabulate.tabulate(map(self.metrics_list_item, data),
+                                       headers='keys', tablefmt=self.tablefmt))
+

 ap = argparse.ArgumentParser(prog='osmo-s1gw-cli', 
description=OsmoS1GWCli.DESC)

diff --git a/priv/openapi.json b/priv/openapi.json
index 25ff62a..7323e9a 100644
--- a/priv/openapi.json
+++ b/priv/openapi.json
@@ -4,6 +4,84 @@
         "version": "0.1.0",
         "title": "OsmoS1GW REST interface"
     },
-    "paths": null,
-    "components": null
+    "paths": {
+        "/metrics-list": {
+            "get": {
+                "summary": "Get a list of metrics",
+                "operationId": "MetricsList",
+                "parameters": [
+                    {
+                        "name": "type",
+                        "in": "query",
+                        "description": "Metric type",
+                        "required": false,
+                        "schema": {
+                            "type": "string",
+                            "enum": [
+                                "all",
+                                "counter",
+                                "gauge"
+                            ],
+                            "default": "all"
+                        }
+                    },
+                    {
+                        "name": "path",
+                        "in": "query",
+                        "description": "Metrics path",
+                        "required": false,
+                        "schema": {
+                            "type": "string",
+                            "example": "s1ap.proxy"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "A list of metrics",
+                        "content": {
+                            "application/json": {
+                                "schema": {
+                                    "$ref": "#/components/schemas/MetricsList"
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "components": {
+        "schemas": {
+            "MetricsList": {
+                "type": "array",
+                "items": {
+                    "$ref": "#/components/schemas/MetricsItem"
+                }
+            },
+            "MetricsItem": {
+                "type": "object",
+                "required": [
+                    "type",
+                    "name",
+                    "value"
+                ],
+                "properties": {
+                    "type": {
+                        "type": "string",
+                        "enum": [
+                            "counter",
+                            "gauge"
+                        ]
+                    },
+                    "name": {
+                        "type": "string"
+                    },
+                    "value": {
+                        "type": "integer"
+                    }
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/rest_server.erl b/src/rest_server.erl
index c4e0373..ee0a7de 100644
--- a/src/rest_server.erl
+++ b/src/rest_server.erl
@@ -34,19 +34,77 @@

 -module(rest_server).

--export([]).
+-export([metrics_list/1
+        ]).

 -include_lib("kernel/include/logger.hrl").

+-include("s1gw_metrics.hrl").
+

 %% ------------------------------------------------------------------
 %% public API
 %% ------------------------------------------------------------------

+%% MetricsList :: Get a list of metrics
+metrics_list(#{query_parameters := QP}) ->
+    L0 = case proplists:get_value(<< "type" >>, QP, << "all" >>) of
+        << "counter" >> -> metric_list([ctr]);
+        << "gauge" >> -> metric_list([gauge]);
+        << "all" >> -> metric_list([])
+    end,
+    L1 = case proplists:get_value(<< "path" >>, QP) of
+        undefined -> L0;
+        Path -> lists:filter(fun(M) -> metric_filter_path(M, Path) end, L0)
+    end,
+    {200, [], L1}.
+

 %% ------------------------------------------------------------------
 %% private API
 %% ------------------------------------------------------------------

+-spec metric_list(list()) -> [map()].
+metric_list(Path) ->
+    L = exometer:get_values(Path),
+    lists:map(fun metric_item/1, L).
+
+
+-spec metric_item({Name, Props}) -> map()
+    when Name :: s1gw_metrics:metric(),
+         Props :: proplists:proplist().
+metric_item({Name, Props}) ->
+    Value = proplists:get_value(value, Props),
+    #{<< "type" >> => metric_type(Name),
+      << "name" >> => metric_name(Name),
+      << "value" >> => Value}.
+
+
+-spec metric_type(s1gw_metrics:metric()) -> binary().
+metric_type([ctr | _]) -> << "counter" >>;
+metric_type([gauge | _]) -> << "gauge" >>.
+
+
+-spec metric_filter_path(map(), binary()) -> boolean().
+metric_filter_path(#{<< "name" >> := Name}, Path) ->
+    Len = erlang:min(byte_size(Name), byte_size(Path)),
+    binary:part(Name, 0, Len) =:= Path.
+
+
+-spec metric_name(s1gw_metrics:metric()) -> binary().
+metric_name([_Type | P0]) ->
+    %% turn each list member into a string
+    P1 = lists:map(fun thing_to_list/1, P0),
+    %% put the dot-separator in between
+    P2 = string:join(P1, "."),
+    list_to_binary(P2).
+
+
+%% stolen from exometer_report_statsd.git
+thing_to_list(X) when is_atom(X) -> atom_to_list(X);
+thing_to_list(X) when is_integer(X) -> integer_to_list(X);
+thing_to_list(X) when is_binary(X) -> X;
+thing_to_list(X) when is_list(X) -> X.
+

 %% vim:set ts=4 sw=4 et:

--
To view, visit https://gerrit.osmocom.org/c/erlang/osmo-s1gw/+/41099?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: erlang/osmo-s1gw
Gerrit-Branch: master
Gerrit-Change-Id: I43114aa8f5f8a388dd6a436f83ad1ee97f1d2ab1
Gerrit-Change-Number: 41099
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>

Reply via email to