feat(prometheus): api `format_mode` parameter support

- node(default):
  The only supported format_mode for PushGateway.
  Return the current node's metrics.
  -  Without label `node_name` with content-type: `text/plain`.
  -  Without key `node_name` with content-type: `application/json`

- nodes_aggregated:
  Return all nodes metrics Arithmetic-Sum or Logical-Sum.
  See details in callback modules.
    - Logical-Sum for metrics named with `xxx_enable` or `xxx_status`.
    - Arithmetic-Sum for other metrics.
  `node_name` field:
    -  Without label `node_name` with content-type: `text/plain`.
    -  Without key `node_name` with content-type: `application/json`

- nodes_unaggregated:
  Return all nodes metrics without aggregated.
  `node_name` field:
    -  _With_ label `node_name` with content-type: `text/plain`.
    -  _With_ key `node_name` with content-type: `application/json`
This commit is contained in:
JimMoen 2024-01-16 16:32:41 +08:00
parent 94032aafb2
commit fb330f77e6
No known key found for this signature in database
2 changed files with 54 additions and 9 deletions

View File

@ -21,10 +21,19 @@
-include_lib("hocon/include/hoconsc.hrl").
-include_lib("emqx/include/logger.hrl").
-import(
hoconsc,
[
mk/2,
ref/1
]
).
-export([
api_spec/0,
paths/0,
schema/1
schema/1,
fields/1
]).
-export([
@ -35,6 +44,8 @@
]).
-define(TAGS, [<<"Monitor">>]).
-define(IS_TRUE(Val), ((Val =:= true) orelse (Val =:= <<"true">>))).
-define(IS_FALSE(Val), ((Val =:= false) orelse (Val =:= <<"false">>))).
api_spec() ->
emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
@ -73,6 +84,7 @@ schema("/prometheus/auth") ->
#{
description => ?DESC(get_prom_auth_data),
tags => ?TAGS,
parameters => [ref(format_mode)],
security => security(),
responses =>
#{200 => prometheus_data_schema()}
@ -85,6 +97,7 @@ schema("/prometheus/stats") ->
#{
description => ?DESC(get_prom_data),
tags => ?TAGS,
parameters => [ref(format_mode)],
security => security(),
responses =>
#{200 => prometheus_data_schema()}
@ -97,6 +110,7 @@ schema("/prometheus/data_integration") ->
#{
description => ?DESC(get_prom_data_integration_data),
tags => ?TAGS,
parameters => [ref(format_mode)],
security => security(),
responses =>
#{200 => prometheus_data_schema()}
@ -108,6 +122,22 @@ security() ->
true -> [#{'basicAuth' => []}, #{'bearerAuth' => []}];
false -> []
end.
fields(format_mode) ->
[
{format_mode,
mk(
hoconsc:enum([node, nodes_aggregated, nodes_unaggregated]),
#{
default => node,
desc => <<"Metrics format mode.">>,
in => query,
required => false,
example => false
}
)}
].
%%--------------------------------------------------------------------
%% API Handler funcs
%%--------------------------------------------------------------------
@ -129,21 +159,21 @@ setting(put, #{body := Body}) ->
{500, 'INTERNAL_ERROR', Message}
end.
stats(get, #{headers := Headers}) ->
collect(emqx_prometheus, Headers).
stats(get, #{headers := Headers, query_string := Qs}) ->
collect(emqx_prometheus, collect_opts(Headers, Qs)).
auth(get, #{headers := Headers}) ->
collect(emqx_prometheus_auth, Headers).
auth(get, #{headers := Headers, query_string := Qs}) ->
collect(emqx_prometheus_auth, collect_opts(Headers, Qs)).
data_integration(get, #{headers := Headers}) ->
collect(emqx_prometheus_data_integration, Headers).
data_integration(get, #{headers := Headers, query_string := Qs}) ->
collect(emqx_prometheus_data_integration, collect_opts(Headers, Qs)).
%%--------------------------------------------------------------------
%% Internal funcs
%%--------------------------------------------------------------------
collect(Module, Headers) ->
Type = response_type(Headers),
collect(Module, #{type := Type, format_mode := FormatMode}) ->
erlang:put(format_mode, FormatMode),
Data =
case erlang:function_exported(Module, collect, 1) of
true ->
@ -157,11 +187,23 @@ collect(Module, Headers) ->
end,
gen_response(Type, Data).
collect_opts(Headers, Qs) ->
#{type => response_type(Headers), format_mode => format_mode(Qs)}.
response_type(#{<<"accept">> := <<"application/json">>}) ->
<<"json">>;
response_type(_) ->
<<"prometheus">>.
format_mode(#{<<"format_mode">> := <<"node">>}) ->
node;
format_mode(#{<<"format_mode">> := <<"nodes_aggregated">>}) ->
nodes_aggregated;
format_mode(#{<<"format_mode">> := <<"nodes_unaggregated">>}) ->
nodes_unaggregated;
format_mode(_) ->
node.
gen_response(<<"json">>, Data) ->
{200, Data};
gen_response(<<"prometheus">>, Data) ->

View File

@ -67,6 +67,9 @@ init([]) ->
Children =
case emqx_prometheus_config:is_push_gateway_server_enabled(Conf) of
false -> [];
%% TODO: add push gateway for endpoints
%% `/prometheus/auth`
%% `/prometheus/data_integration`
true -> [?CHILD(emqx_prometheus, Conf)]
end,
{ok, {{one_for_one, 10, 3600}, Children}}.