refactor(api): prometheus swagger spec

This commit is contained in:
JimMoen 2022-01-20 16:35:05 +08:00
parent baa56a3416
commit b950042cbf
4 changed files with 92 additions and 37 deletions

View File

@ -1,3 +1,19 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2021-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%--------------------------------------------------------------------
-module(emqx_dashboard_swagger). -module(emqx_dashboard_swagger).
-include_lib("typerefl/include/types.hrl"). -include_lib("typerefl/include/types.hrl").
@ -313,6 +329,7 @@ responses(Responses, Module) ->
response(Status, Bin, {Acc, RefsAcc, Module}) when is_binary(Bin) -> response(Status, Bin, {Acc, RefsAcc, Module}) when is_binary(Bin) ->
{Acc#{integer_to_binary(Status) => #{description => Bin}}, RefsAcc, Module}; {Acc#{integer_to_binary(Status) => #{description => Bin}}, RefsAcc, Module};
%% Support swagger raw object(file download). %% Support swagger raw object(file download).
%% TODO: multi type response(i.e. Support both 'application/json' and 'plain/text')
response(Status, #{content := _} = Content, {Acc, RefsAcc, Module}) -> response(Status, #{content := _} = Content, {Acc, RefsAcc, Module}) ->
{Acc#{integer_to_binary(Status) => Content}, RefsAcc, Module}; {Acc#{integer_to_binary(Status) => Content}, RefsAcc, Module};
response(Status, ?REF(StructName), {Acc, RefsAcc, Module}) -> response(Status, ?REF(StructName), {Acc, RefsAcc, Module}) ->

View File

@ -45,6 +45,7 @@
-define(BAD_TOPIC, 'BAD_TOPIC'). -define(BAD_TOPIC, 'BAD_TOPIC').
-define(BAD_RPC, 'BAD_RPC'). -define(BAD_RPC, 'BAD_RPC').
-define(BAD_REQUEST, 'BAD_REQUEST'). -define(BAD_REQUEST, 'BAD_REQUEST').
-define(API_TAG_MQTT, [<<"mqtt">>]). -define(API_TAG_MQTT, [<<"mqtt">>]).

View File

@ -20,48 +20,56 @@
-include("emqx_prometheus.hrl"). -include("emqx_prometheus.hrl").
-import(emqx_mgmt_util, [ schema/1]). -import(hoconsc, [ref/2]).
-export([api_spec/0]). -export([ api_spec/0
, paths/0
, schema/1
]).
-export([ prometheus/2 -export([ prometheus/2
, stats/2 , stats/2
]). ]).
-define(API_TAG_PROMETHEUS, [<<"premetheus">>]).
-define(SCHEMA_MODULE, emqx_prometheus_schema).
api_spec() -> api_spec() ->
{[prometheus_api(), prometheus_data_api()], []}. emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
conf_schema() -> paths() ->
emqx_mgmt_api_configs:gen_schema(emqx:get_raw_config([prometheus])). [ "/prometheus"
, "/prometheus/stats"
].
prometheus_api() -> schema("/prometheus") ->
Metadata = #{ #{ 'operationId' => prometheus
get => #{ , get =>
description => <<"Get Prometheus info">>, #{ description => <<"Get Prometheus config info">>
responses => #{<<"200">> => schema(conf_schema())} , tags => ?API_TAG_PROMETHEUS
}, , responses =>
put => #{ #{200 => prometheus_config_schema()}
description => <<"Update Prometheus">>,
'requestBody' => schema(conf_schema()),
responses => #{<<"200">> => schema(conf_schema())}
}
},
{"/prometheus", Metadata, prometheus}.
prometheus_data_api() ->
Metadata = #{
get => #{
description => <<"Get Prometheus Data">>,
responses => #{<<"200">> =>
#{content =>
#{
'application/json' => #{schema => #{type => object}},
'text/plain' => #{schema => #{type => string}}
}}
} }
} , put =>
}, #{ description => <<"Update Prometheus config">>
{"/prometheus/stats", Metadata, stats}. , 'requestBody' => prometheus_config_schema()
, responses =>
#{200 => prometheus_config_schema()}
}
};
schema("/prometheus/stats") ->
#{ 'operationId' => stats
, get =>
#{ description => <<"Get Prometheus Data">>
, responses =>
#{200 => prometheus_data_schema()}
}
}.
%%--------------------------------------------------------------------
%% API Handler funcs
%%--------------------------------------------------------------------
prometheus(get, _Params) -> prometheus(get, _Params) ->
{200, emqx:get_raw_config([<<"prometheus">>], #{})}; {200, emqx:get_raw_config([<<"prometheus">>], #{})};
@ -83,6 +91,35 @@ stats(get, #{headers := Headers}) ->
end, end,
Data = emqx_prometheus:collect(Type), Data = emqx_prometheus:collect(Type),
case Type of case Type of
<<"json">> -> {200, Data}; <<"json">> ->
<<"prometheus">> -> {200, #{<<"content-type">> => <<"text/plain">>}, Data} {200, Data};
<<"prometheus">> ->
{200, #{<<"content-type">> => <<"text/plain">>}, Data}
end. end.
%%--------------------------------------------------------------------
%% Internal funcs
%%--------------------------------------------------------------------
prometheus_config_schema() ->
emqx_dashboard_swagger:schema_with_example(
ref(?SCHEMA_MODULE, "prometheus"),
prometheus_config_example()).
prometheus_config_example() ->
#{ enable => true
, interval => "15s"
, push_gateway_server => <<"http://127.0.0.1:9091">>
}.
prometheus_data_schema() ->
#{ description => <<"Get Prometheus Data">>
, content =>
#{ 'application/json' =>
#{ schema => #{type => object}
, description => <<"Prometheus Data in json">>}
, 'text/plain' =>
#{ schema => #{type => string}
, description => <<"Prometheus Data in text/plain">>}
}
}.

View File

@ -28,9 +28,9 @@ namespace() -> "prometheus".
roots() -> ["prometheus"]. roots() -> ["prometheus"].
fields("prometheus") -> fields("prometheus") ->
[ {push_gateway_server, sc(string(), #{})} [ {push_gateway_server, sc(string(), #{default => "http://127.0.0.1:9091", nullabel => false})}
, {interval, sc(emqx_schema:duration_ms(), #{default => "15s"})} , {interval, sc(emqx_schema:duration_ms(), #{default => "15s", nullabel => false})}
, {enable, sc(boolean(), #{default => false})} , {enable, sc(boolean(), #{default => false, nullabel => false})}
]. ].
sc(Type, Meta) -> hoconsc:mk(Type, Meta). sc(Type, Meta) -> hoconsc:mk(Type, Meta).