Преглед изворни кода

Merge pull request #7099 from HJianBo/swagger_api_mgmt_metrics

refactor(mgmt): refactor api_metrics with dashboard_swagger
JimMoen пре 4 година
родитељ
комит
7eb3c0d4e5
1 измењених фајлова са 241 додато и 130 уклоњено
  1. 241 130
      apps/emqx_management/src/emqx_mgmt_api_metrics.erl

+ 241 - 130
apps/emqx_management/src/emqx_mgmt_api_metrics.erl

@@ -18,142 +18,253 @@
 
 
 -behaviour(minirest_api).
 -behaviour(minirest_api).
 
 
--export([api_spec/0]).
+-include_lib("typerefl/include/types.hrl").
 
 
--export([list/2]).
+-import(hoconsc, [mk/2, ref/2]).
+
+%% minirest/dashbaord_swagger behaviour callbacks
+-export([ api_spec/0
+        , paths/0
+        , schema/1
+        ]).
+
+-export([ roots/0
+        , fields/1
+        ]).
+
+%% http handlers
+-export([metrics/2]).
+
+%%--------------------------------------------------------------------
+%% minirest behaviour callbacks
+%%--------------------------------------------------------------------
 
 
 api_spec() ->
 api_spec() ->
-    {[metrics_api()], [metrics_schema()]}.
-
-metrics_schema() ->
-    Metric = #{
-        type => object,
-        properties => emqx_mgmt_util:properties(properties())
-    },
-    Metrics = #{
-        type => array,
-        items => #{
-            type => object,
-            properties => emqx_mgmt_util:properties([{node, string} | properties()])
-        }
-    },
-    MetricsInfo = #{
-        oneOf => [ minirest:ref(metric)
-                 , minirest:ref(metrics)
-                 ]
-    },
-    #{metric => Metric, metrics => Metrics, metrics_info => MetricsInfo}.
+%    {[metrics_api()], [metrics_schema()]}.
+    emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
 
 
-properties() ->
-    [
-        {'actions.failure',                 integer, <<"Number of failure executions of the rule engine action">>},
-        {'actions.success',                 integer, <<"Number of successful executions of the rule engine action">>},
-        {'bytes.received',                  integer, <<"Number of bytes received ">>},
-        {'bytes.sent',                      integer, <<"Number of bytes sent on this connection">>},
-        {'client.auth.anonymous',           integer, <<"Number of clients who log in anonymously">>},
-        {'client.authenticate',             integer, <<"Number of client authentications">>},
-        {'client.check_authz',              integer, <<"Number of Authorization rule checks">>},
-        {'client.connack',                  integer, <<"Number of CONNACK packet sent">>},
-        {'client.connect',                  integer, <<"Number of client connections">>},
-        {'client.connected',                integer, <<"Number of successful client connections">>},
-        {'client.disconnected',             integer, <<"Number of client disconnects">>},
-        {'client.subscribe',                integer, <<"Number of client subscriptions">>},
-        {'client.unsubscribe',              integer, <<"Number of client unsubscriptions">>},
-        {'delivery.dropped',                integer, <<"Total number of discarded messages when sending">>},
-        {'delivery.dropped.expired',        integer, <<"Number of messages dropped due to message expiration on sending">>},
-        {'delivery.dropped.no_local',       integer, <<"Number of messages that were dropped due to the No Local subscription option when sending">>},
-        {'delivery.dropped.qos0_msg',       integer, <<"Number of messages with QoS 0 that were dropped because the message queue was full when sending">>},
-        {'delivery.dropped.queue_full',     integer, <<"Number of messages with a non-zero QoS that were dropped because the message queue was full when sending">>},
-        {'delivery.dropped.too_large',      integer, <<"The number of messages that were dropped because the length exceeded the limit when sending">>},
-        {'messages.acked',                  integer, <<"Number of received PUBACK and PUBREC packet">>},
-        {'messages.delayed',                integer, <<"Number of delay-published messages">>},
-        {'messages.delivered',              integer, <<"Number of messages forwarded to the subscription process internally">>},
-        {'messages.dropped',                integer, <<"Total number of messages dropped before forwarding to the subscription process">>},
-        {'messages.dropped.await_pubrel_timeout', integer, <<"Number of messages dropped due to waiting PUBREL timeout">>},
-        {'messages.dropped.no_subscribers', integer, <<"Number of messages dropped due to no subscribers">>},
-        {'messages.forward',                integer, <<"Number of messages forwarded to other nodes">>},
-        {'messages.publish',                integer, <<"Number of messages published in addition to system messages">>},
-        {'messages.qos0.received',          integer, <<"Number of QoS 0 messages received from clients">>},
-        {'messages.qos0.sent',              integer, <<"Number of QoS 0 messages sent to clients">>},
-        {'messages.qos1.received',          integer, <<"Number of QoS 1 messages received from clients">>},
-        {'messages.qos1.sent',              integer, <<"Number of QoS 1 messages sent to clients">>},
-        {'messages.qos2.received',          integer, <<"Number of QoS 2 messages received from clients">>},
-        {'messages.qos2.sent',              integer, <<"Number of QoS 2 messages sent to clients">>},
-        {'messages.received',               integer, <<"Number of messages received from the client, equal to the sum of messages.qos0.received\fmessages.qos1.received and messages.qos2.received">>},
-        {'messages.retained',               integer, <<"Number of retained messages">>},
-        {'messages.sent',                   integer, <<"Number of messages sent to the client, equal to the sum of messages.qos0.sent\fmessages.qos1.sent and messages.qos2.sent">>},
-        {'packets.auth.received',           integer, <<"Number of received AUTH packet">>},
-        {'packets.auth.sent',               integer, <<"Number of sent AUTH packet">>},
-        {'packets.connack.auth_error',      integer, <<"Number of received CONNECT packet with failed authentication">>},
-        {'packets.connack.error',           integer, <<"Number of received CONNECT packet with unsuccessful connections">>},
-        {'packets.connack.sent',            integer, <<"Number of sent CONNACK packet">>},
-        {'packets.connect.received',        integer, <<"Number of received CONNECT packet">>},
-        {'packets.disconnect.received',     integer, <<"Number of received DISCONNECT packet">>},
-        {'packets.disconnect.sent',         integer, <<"Number of sent DISCONNECT packet">>},
-        {'packets.pingreq.received',        integer, <<"Number of received PINGREQ packet">>},
-        {'packets.pingresp.sent',           integer, <<"Number of sent PUBRESP packet">>},
-        {'packets.puback.inuse',            integer, <<"Number of received PUBACK packet with occupied identifiers">>},
-        {'packets.puback.missed',           integer, <<"Number of received packet with identifiers.">>},
-        {'packets.puback.received',         integer, <<"Number of received PUBACK packet">>},
-        {'packets.puback.sent',             integer, <<"Number of sent PUBACK packet">>},
-        {'packets.pubcomp.inuse',           integer, <<"Number of received PUBCOMP packet with occupied identifiers">>},
-        {'packets.pubcomp.missed',          integer, <<"Number of missed PUBCOMP packet">>},
-        {'packets.pubcomp.received',        integer, <<"Number of received PUBCOMP packet">>},
-        {'packets.pubcomp.sent',            integer, <<"Number of sent PUBCOMP packet">>},
-        {'packets.publish.auth_error',      integer, <<"Number of received PUBLISH packets with failed the Authorization check">>},
-        {'packets.publish.dropped',         integer, <<"Number of messages discarded due to the receiving limit">>},
-        {'packets.publish.error',           integer, <<"Number of received PUBLISH packet that cannot be published">>},
-        {'packets.publish.inuse',           integer, <<"Number of received PUBLISH packet with occupied identifiers">>},
-        {'packets.publish.received',        integer, <<"Number of received PUBLISH packet">>},
-        {'packets.publish.sent',            integer, <<"Number of sent PUBLISH packet">>},
-        {'packets.pubrec.inuse',            integer, <<"Number of received PUBREC packet with occupied identifiers">>},
-        {'packets.pubrec.missed',           integer, <<"Number of received PUBREC packet with unknown identifiers">>},
-        {'packets.pubrec.received',         integer, <<"Number of received PUBREC packet">>},
-        {'packets.pubrec.sent',             integer, <<"Number of sent PUBREC packet">>},
-        {'packets.pubrel.missed',           integer, <<"Number of received PUBREC packet with unknown identifiers">>},
-        {'packets.pubrel.received',         integer, <<"Number of received PUBREL packet">>},
-        {'packets.pubrel.sent',             integer, <<"Number of sent PUBREL packet">>},
-        {'packets.received',                integer, <<"Number of received packet">>},
-        {'packets.sent',                    integer, <<"Number of sent packet">>},
-        {'packets.suback.sent',             integer, <<"Number of sent SUBACK packet">>},
-        {'packets.subscribe.auth_error',    integer, <<"Number of received SUBACK packet with failed Authorization check">>},
-        {'packets.subscribe.error',         integer, <<"Number of received SUBSCRIBE packet with failed subscriptions">>},
-        {'packets.subscribe.received',      integer, <<"Number of received SUBSCRIBE packet">>},
-        {'packets.unsuback.sent',           integer, <<"Number of sent UNSUBACK packet">>},
-        {'packets.unsubscribe.error',       integer, <<"Number of received UNSUBSCRIBE packet with failed unsubscriptions">>},
-        {'packets.unsubscribe.received',    integer, <<"Number of received UNSUBSCRIBE packet">>},
-        {'rules.matched',                   integer, <<"Number of rule matched">>},
-        {'session.created',                 integer, <<"Number of sessions created">>},
-        {'session.discarded',               integer, <<"Number of sessions dropped because Clean Session or Clean Start is true">>},
-        {'session.resumed',                 integer, <<"Number of sessions resumed because Clean Session or Clean Start is false">>},
-        {'session.takenover',               integer, <<"Number of sessions takenover because Clean Session or Clean Start is false">>},
-        {'session.terminated',              integer, <<"Number of terminated sessions">>}
+paths() ->
+    [ "/metrics"
     ].
     ].
 
 
-metrics_api() ->
-    Metadata = #{
-        get => #{
-            description => <<"EMQX metrics">>,
-            parameters => [#{
-                name => aggregate,
-                in => query,
-                schema => #{type => boolean}
-            }],
-            responses => #{
-                <<"200">> => emqx_mgmt_util:schema(metrics_info, <<"List all metrics">>)
-            }
-        }
-    },
-    {"/metrics", Metadata, list}.
-
-%%%==============================================================================================
-%% api apply
-list(get, #{query_string := Qs}) ->
-    case maps:get(<<"aggregate">>, Qs, undefined) of
-        <<"true">> ->
+%%--------------------------------------------------------------------
+%% http handlers
+
+metrics(get, #{query_string := Qs}) ->
+    case maps:get(<<"aggregate">>, Qs, false) of
+        true ->
             {200, emqx_mgmt:get_metrics()};
             {200, emqx_mgmt:get_metrics()};
-        _ ->
-            Data = [maps:from_list(emqx_mgmt:get_metrics(Node) ++ [{node, Node}]) ||
-                        Node <- mria_mnesia:running_nodes()],
+        false ->
+            Data = [maps:from_list(
+                      emqx_mgmt:get_metrics(Node) ++ [{node, Node}])
+                    || Node <- mria_mnesia:running_nodes()],
             {200, Data}
             {200, Data}
     end.
     end.
+
+%%--------------------------------------------------------------------
+%% swagger defines
+%%--------------------------------------------------------------------
+
+schema("/metrics") ->
+    #{'operationId' => metrics,
+      get =>
+        #{ description => <<"EMQX metrics">>
+         , parameters =>
+            [{aggregate,
+              mk(boolean(),
+                 #{ in => query
+                  , nullable => true
+                  , desc => <<"">>
+                  })
+             }]
+         , responses =>
+            #{ 200 => hoconsc:union(
+                        [ref(?MODULE, aggregated_metrics),
+                         hoconsc:array(ref(?MODULE, node_metrics))])
+             }
+         }
+     }.
+
+roots() ->
+    [].
+
+fields(aggregated_metrics) ->
+    properties();
+fields(node_metrics) ->
+    [{node, mk(binary(), #{desc => <<"Node name">>})}] ++ properties().
+
+properties() ->
+    [ m('actions.failure',
+        <<"Number of failure executions of the rule engine action">>)
+    , m('actions.success',
+        <<"Number of successful executions of the rule engine action">>)
+    , m('bytes.received',
+        <<"Number of bytes received ">>)
+    , m('bytes.sent',
+        <<"Number of bytes sent on this connection">>)
+    , m('client.auth.anonymous',
+        <<"Number of clients who log in anonymously">>)
+    , m('client.authenticate',
+        <<"Number of client authentications">>)
+    , m('client.check_authz',
+        <<"Number of Authorization rule checks">>)
+    , m('client.connack',
+        <<"Number of CONNACK packet sent">>)
+    , m('client.connect',
+        <<"Number of client connections">>)
+    , m('client.connected',
+        <<"Number of successful client connections">>)
+    , m('client.disconnected',
+        <<"Number of client disconnects">>)
+    , m('client.subscribe',
+        <<"Number of client subscriptions">>)
+    , m('client.unsubscribe',
+        <<"Number of client unsubscriptions">>)
+    , m('delivery.dropped',
+        <<"Total number of discarded messages when sending">>)
+    , m('delivery.dropped.expired',
+        <<"Number of messages dropped due to message expiration on sending">>)
+    , m('delivery.dropped.no_local',
+        <<"Number of messages that were dropped due to the No Local subscription "
+          "option when sending">>)
+    , m('delivery.dropped.qos0_msg',
+        <<"Number of messages with QoS 0 that were dropped because the message "
+          "queue was full when sending">>)
+    , m('delivery.dropped.queue_full',
+        <<"Number of messages with a non-zero QoS that were dropped because the "
+          "message queue was full when sending">>)
+    , m('delivery.dropped.too_large',
+        <<"The number of messages that were dropped because the length exceeded "
+          "the limit when sending">>)
+    , m('messages.acked',
+        <<"Number of received PUBACK and PUBREC packet">>)
+    , m('messages.delayed',
+        <<"Number of delay-published messages">>)
+    , m('messages.delivered',
+        <<"Number of messages forwarded to the subscription process internally">>)
+    , m('messages.dropped',
+        <<"Total number of messages dropped before forwarding to the subscription process">>)
+    , m('messages.dropped.await_pubrel_timeout',
+        <<"Number of messages dropped due to waiting PUBREL timeout">>)
+    , m('messages.dropped.no_subscribers',
+        <<"Number of messages dropped due to no subscribers">>)
+    , m('messages.forward',
+        <<"Number of messages forwarded to other nodes">>)
+    , m('messages.publish',
+        <<"Number of messages published in addition to system messages">>)
+    , m('messages.qos0.received',
+        <<"Number of QoS 0 messages received from clients">>)
+    , m('messages.qos0.sent',
+        <<"Number of QoS 0 messages sent to clients">>)
+    , m('messages.qos1.received',
+        <<"Number of QoS 1 messages received from clients">>)
+    , m('messages.qos1.sent',
+        <<"Number of QoS 1 messages sent to clients">>)
+    , m('messages.qos2.received',
+        <<"Number of QoS 2 messages received from clients">>)
+    , m('messages.qos2.sent',
+        <<"Number of QoS 2 messages sent to clients">>)
+    , m('messages.received',
+        <<"Number of messages received from the client, equal to the sum of "
+          "messages.qos0.received\fmessages.qos1.received and messages.qos2.received">>)
+    , m('messages.retained',
+        <<"Number of retained messages">>)
+    , m('messages.sent',
+        <<"Number of messages sent to the client, equal to the sum of "
+          "messages.qos0.sent\fmessages.qos1.sent and messages.qos2.sent">>)
+    , m('packets.auth.received',
+        <<"Number of received AUTH packet">>)
+    , m('packets.auth.sent',
+        <<"Number of sent AUTH packet">>)
+    , m('packets.connack.auth_error',
+        <<"Number of received CONNECT packet with failed authentication">>)
+    , m('packets.connack.error',
+        <<"Number of received CONNECT packet with unsuccessful connections">>)
+    , m('packets.connack.sent',
+        <<"Number of sent CONNACK packet">>)
+    , m('packets.connect.received',
+        <<"Number of received CONNECT packet">>)
+    , m('packets.disconnect.received',
+        <<"Number of received DISCONNECT packet">>)
+    , m('packets.disconnect.sent',
+        <<"Number of sent DISCONNECT packet">>)
+    , m('packets.pingreq.received',
+        <<"Number of received PINGREQ packet">>)
+    , m('packets.pingresp.sent',
+        <<"Number of sent PUBRESP packet">>)
+    , m('packets.puback.inuse',
+        <<"Number of received PUBACK packet with occupied identifiers">>)
+    , m('packets.puback.missed',
+        <<"Number of received packet with identifiers.">>)
+    , m('packets.puback.received',
+        <<"Number of received PUBACK packet">>)
+    , m('packets.puback.sent',
+        <<"Number of sent PUBACK packet">>)
+    , m('packets.pubcomp.inuse',
+        <<"Number of received PUBCOMP packet with occupied identifiers">>)
+    , m('packets.pubcomp.missed',
+        <<"Number of missed PUBCOMP packet">>)
+    , m('packets.pubcomp.received',
+        <<"Number of received PUBCOMP packet">>)
+    , m('packets.pubcomp.sent',
+        <<"Number of sent PUBCOMP packet">>)
+    , m('packets.publish.auth_error',
+        <<"Number of received PUBLISH packets with failed the Authorization check">>)
+    , m('packets.publish.dropped',
+        <<"Number of messages discarded due to the receiving limit">>)
+    , m('packets.publish.error',
+        <<"Number of received PUBLISH packet that cannot be published">>)
+    , m('packets.publish.inuse',
+        <<"Number of received PUBLISH packet with occupied identifiers">>)
+    , m('packets.publish.received',
+        <<"Number of received PUBLISH packet">>)
+    , m('packets.publish.sent',
+        <<"Number of sent PUBLISH packet">>)
+    , m('packets.pubrec.inuse',
+        <<"Number of received PUBREC packet with occupied identifiers">>)
+    , m('packets.pubrec.missed',
+        <<"Number of received PUBREC packet with unknown identifiers">>)
+    , m('packets.pubrec.received',
+        <<"Number of received PUBREC packet">>)
+    , m('packets.pubrec.sent',
+        <<"Number of sent PUBREC packet">>)
+    , m('packets.pubrel.missed',
+        <<"Number of received PUBREC packet with unknown identifiers">>)
+    , m('packets.pubrel.received',
+        <<"Number of received PUBREL packet">>)
+    , m('packets.pubrel.sent',
+        <<"Number of sent PUBREL packet">>)
+    , m('packets.received',
+        <<"Number of received packet">>)
+    , m('packets.sent',
+        <<"Number of sent packet">>)
+    , m('packets.suback.sent',
+        <<"Number of sent SUBACK packet">>)
+    , m('packets.subscribe.auth_error',
+        <<"Number of received SUBACK packet with failed Authorization check">>)
+    , m('packets.subscribe.error',
+        <<"Number of received SUBSCRIBE packet with failed subscriptions">>)
+    , m('packets.subscribe.received',
+        <<"Number of received SUBSCRIBE packet">>)
+    , m('packets.unsuback.sent',
+        <<"Number of sent UNSUBACK packet">>)
+    , m('packets.unsubscribe.error',
+        <<"Number of received UNSUBSCRIBE packet with failed unsubscriptions">>)
+    , m('packets.unsubscribe.received',
+        <<"Number of received UNSUBSCRIBE packet">>)
+    , m('rules.matched',
+        <<"Number of rule matched">>)
+    , m('session.created',
+        <<"Number of sessions created">>)
+    , m('session.discarded',
+        <<"Number of sessions dropped because Clean Session or Clean Start is true">>)
+    , m('session.resumed',
+        <<"Number of sessions resumed because Clean Session or Clean Start is false">>)
+    , m('session.takenover',
+        <<"Number of sessions takenover because Clean Session or Clean Start is false">>)
+    , m('session.terminated',
+        <<"Number of terminated sessions">>)
+    ].
+
+m(K, Desc) ->
+    {K, mk(integer(), #{desc => Desc})}.