feat(prometheus): auth metrics with text/plain
This commit is contained in:
parent
092159b071
commit
e0feb580b6
|
@ -1106,6 +1106,7 @@ tr_prometheus_collectors(Conf) ->
|
||||||
prometheus_summary,
|
prometheus_summary,
|
||||||
%% emqx collectors
|
%% emqx collectors
|
||||||
emqx_prometheus,
|
emqx_prometheus,
|
||||||
|
{'/prometheus/auth', emqx_prometheus_auth},
|
||||||
emqx_prometheus_mria
|
emqx_prometheus_mria
|
||||||
%% builtin vm collectors
|
%% builtin vm collectors
|
||||||
| prometheus_collectors(Conf)
|
| prometheus_collectors(Conf)
|
||||||
|
|
|
@ -16,3 +16,15 @@
|
||||||
|
|
||||||
-define(APP, emqx_prometheus).
|
-define(APP, emqx_prometheus).
|
||||||
-define(PROMETHEUS, [prometheus]).
|
-define(PROMETHEUS, [prometheus]).
|
||||||
|
|
||||||
|
-define(PROMETHEUS_DEFAULT_REGISTRY, default).
|
||||||
|
-define(PROMETHEUS_AUTH_REGISTRY, '/prometheus/auth').
|
||||||
|
-define(PROMETHEUS_AUTH_COLLECTOR, emqx_prometheus_auth).
|
||||||
|
-define(PROMETHEUS_DATA_INTEGRATION_REGISTRY, '/prometheus/data_integration').
|
||||||
|
-define(PROMETHEUS_DATA_INTEGRATION_COLLECTOR, emqx_prometheus_data_integration).
|
||||||
|
|
||||||
|
-define(PROMETHEUS_ALL_REGISTRYS, [
|
||||||
|
?PROMETHEUS_DEFAULT_REGISTRY,
|
||||||
|
?PROMETHEUS_AUTH_REGISTRY,
|
||||||
|
?PROMETHEUS_DATA_INTEGRATION_REGISTRY
|
||||||
|
]).
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
{deps, [
|
{deps, [
|
||||||
{emqx, {path, "../emqx"}},
|
{emqx, {path, "../emqx"}},
|
||||||
{emqx_utils, {path, "../emqx_utils"}},
|
{emqx_utils, {path, "../emqx_utils"}},
|
||||||
{prometheus, {git, "https://github.com/emqx/prometheus.erl", {tag, "v4.10.0.1"}}}
|
{emqx_auth, {path, "../emqx_auth"}},
|
||||||
|
{prometheus, {git, "https://github.com/emqx/prometheus.erl", {tag, "v4.10.0.2"}}}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
{edoc_opts, [{preprocess, true}]}.
|
{edoc_opts, [{preprocess, true}]}.
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{vsn, "5.0.19"},
|
{vsn, "5.0.19"},
|
||||||
{modules, []},
|
{modules, []},
|
||||||
{registered, [emqx_prometheus_sup]},
|
{registered, [emqx_prometheus_sup]},
|
||||||
{applications, [kernel, stdlib, prometheus, emqx, emqx_management]},
|
{applications, [kernel, stdlib, prometheus, emqx, emqx_auth, emqx_management]},
|
||||||
{mod, {emqx_prometheus_app, []}},
|
{mod, {emqx_prometheus_app, []}},
|
||||||
{env, []},
|
{env, []},
|
||||||
{licenses, ["Apache-2.0"]},
|
{licenses, ["Apache-2.0"]},
|
||||||
|
|
|
@ -121,7 +121,7 @@ handle_info(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
push_to_push_gateway(Url, Headers) when is_list(Headers) ->
|
push_to_push_gateway(Url, Headers) when is_list(Headers) ->
|
||||||
Data = prometheus_text_format:format(),
|
Data = prometheus_text_format:format(?PROMETHEUS_DEFAULT_REGISTRY),
|
||||||
case httpc:request(post, {Url, Headers, "text/plain", Data}, ?HTTP_OPTIONS, []) of
|
case httpc:request(post, {Url, Headers, "text/plain", Data}, ?HTTP_OPTIONS, []) of
|
||||||
{ok, {{"HTTP/1.1", 200, _}, _RespHeaders, _RespBody}} ->
|
{ok, {{"HTTP/1.1", 200, _}, _RespHeaders, _RespBody}} ->
|
||||||
ok;
|
ok;
|
||||||
|
@ -168,10 +168,10 @@ join_url(Url, JobName0) ->
|
||||||
}),
|
}),
|
||||||
lists:concat([Url, "/metrics/job/", unicode:characters_to_list(JobName1)]).
|
lists:concat([Url, "/metrics/job/", unicode:characters_to_list(JobName1)]).
|
||||||
|
|
||||||
deregister_cleanup(_Registry) ->
|
deregister_cleanup(?PROMETHEUS_DEFAULT_REGISTRY) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
collect_mf(_Registry, Callback) ->
|
collect_mf(?PROMETHEUS_DEFAULT_REGISTRY, Callback) ->
|
||||||
Metrics = emqx_metrics:all(),
|
Metrics = emqx_metrics:all(),
|
||||||
Stats = emqx_stats:getstats(),
|
Stats = emqx_stats:getstats(),
|
||||||
VMData = emqx_vm_data(),
|
VMData = emqx_vm_data(),
|
||||||
|
@ -192,6 +192,8 @@ collect_mf(_Registry, Callback) ->
|
||||||
_ = [add_collect_family(Name, Metrics, Callback, counter) || Name <- emqx_metrics_olp()],
|
_ = [add_collect_family(Name, Metrics, Callback, counter) || Name <- emqx_metrics_olp()],
|
||||||
_ = [add_collect_family(Name, Metrics, Callback, counter) || Name <- emqx_metrics_acl()],
|
_ = [add_collect_family(Name, Metrics, Callback, counter) || Name <- emqx_metrics_acl()],
|
||||||
_ = [add_collect_family(Name, Metrics, Callback, counter) || Name <- emqx_metrics_authn()],
|
_ = [add_collect_family(Name, Metrics, Callback, counter) || Name <- emqx_metrics_authn()],
|
||||||
|
ok;
|
||||||
|
collect_mf(_Registry, _Callback) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
%% @private
|
%% @private
|
||||||
|
@ -216,7 +218,7 @@ collect(<<"json">>) ->
|
||||||
session => maps:from_list([collect_stats(Name, Metrics) || Name <- emqx_metrics_session()])
|
session => maps:from_list([collect_stats(Name, Metrics) || Name <- emqx_metrics_session()])
|
||||||
};
|
};
|
||||||
collect(<<"prometheus">>) ->
|
collect(<<"prometheus">>) ->
|
||||||
prometheus_text_format:format().
|
prometheus_text_format:format(?PROMETHEUS_DEFAULT_REGISTRY).
|
||||||
|
|
||||||
%% @private
|
%% @private
|
||||||
collect_stats(Name, Stats) ->
|
collect_stats(Name, Stats) ->
|
||||||
|
@ -809,6 +811,7 @@ cert_expiry_at_from_path(Path0) ->
|
||||||
{ok, PemBin} = file:read_file(Path),
|
{ok, PemBin} = file:read_file(Path),
|
||||||
[CertEntry | _] = public_key:pem_decode(PemBin),
|
[CertEntry | _] = public_key:pem_decode(PemBin),
|
||||||
Cert = public_key:pem_entry_decode(CertEntry),
|
Cert = public_key:pem_entry_decode(CertEntry),
|
||||||
|
%% TODO: Not fully tested for all certs type
|
||||||
{'utcTime', NotAfterUtc} =
|
{'utcTime', NotAfterUtc} =
|
||||||
Cert#'Certificate'.'tbsCertificate'#'TBSCertificate'.validity#'Validity'.'notAfter',
|
Cert#'Certificate'.'tbsCertificate'#'TBSCertificate'.validity#'Validity'.'notAfter',
|
||||||
utc_time_to_epoch(NotAfterUtc).
|
utc_time_to_epoch(NotAfterUtc).
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
setting/2,
|
setting/2,
|
||||||
stats/2
|
stats/2,
|
||||||
|
auth/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-define(TAGS, [<<"Monitor">>]).
|
-define(TAGS, [<<"Monitor">>]).
|
||||||
|
@ -39,6 +40,7 @@ api_spec() ->
|
||||||
paths() ->
|
paths() ->
|
||||||
[
|
[
|
||||||
"/prometheus",
|
"/prometheus",
|
||||||
|
"/prometheus/auth",
|
||||||
"/prometheus/stats"
|
"/prometheus/stats"
|
||||||
].
|
].
|
||||||
|
|
||||||
|
@ -61,6 +63,18 @@ schema("/prometheus") ->
|
||||||
#{200 => prometheus_setting_response()}
|
#{200 => prometheus_setting_response()}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
schema("/prometheus/auth") ->
|
||||||
|
#{
|
||||||
|
'operationId' => auth,
|
||||||
|
get =>
|
||||||
|
#{
|
||||||
|
description => ?DESC(get_prom_auth_data),
|
||||||
|
tags => ?TAGS,
|
||||||
|
security => security(),
|
||||||
|
responses =>
|
||||||
|
#{200 => prometheus_data_schema()}
|
||||||
|
}
|
||||||
|
};
|
||||||
schema("/prometheus/stats") ->
|
schema("/prometheus/stats") ->
|
||||||
#{
|
#{
|
||||||
'operationId' => stats,
|
'operationId' => stats,
|
||||||
|
@ -114,6 +128,20 @@ stats(get, #{headers := Headers}) ->
|
||||||
{200, #{<<"content-type">> => <<"text/plain">>}, Data}
|
{200, #{<<"content-type">> => <<"text/plain">>}, Data}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
auth(get, #{headers := Headers}) ->
|
||||||
|
Type =
|
||||||
|
case maps:get(<<"accept">>, Headers, <<"text/plain">>) of
|
||||||
|
<<"application/json">> -> <<"json">>;
|
||||||
|
_ -> <<"prometheus">>
|
||||||
|
end,
|
||||||
|
Data = emqx_prometheus_auth:collect(Type),
|
||||||
|
case Type of
|
||||||
|
<<"json">> ->
|
||||||
|
{200, Data};
|
||||||
|
<<"prometheus">> ->
|
||||||
|
{200, #{<<"content-type">> => <<"text/plain">>}, Data}
|
||||||
|
end.
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Internal funcs
|
%% Internal funcs
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,400 @@
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Copyright (c) 2022-2024 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_prometheus_auth).
|
||||||
|
|
||||||
|
-export([
|
||||||
|
deregister_cleanup/1,
|
||||||
|
collect_mf/2,
|
||||||
|
collect_metrics/2
|
||||||
|
]).
|
||||||
|
|
||||||
|
-export([collect/1]).
|
||||||
|
|
||||||
|
-include("emqx_prometheus.hrl").
|
||||||
|
-include_lib("emqx_auth/include/emqx_authn_chains.hrl").
|
||||||
|
-include_lib("prometheus/include/prometheus.hrl").
|
||||||
|
|
||||||
|
-import(
|
||||||
|
prometheus_model_helpers,
|
||||||
|
[
|
||||||
|
create_mf/5,
|
||||||
|
gauge_metric/1,
|
||||||
|
gauge_metrics/1
|
||||||
|
]
|
||||||
|
).
|
||||||
|
|
||||||
|
-type authn_metric_key() ::
|
||||||
|
emqx_authn_enable
|
||||||
|
| emqx_authn_status
|
||||||
|
| emqx_authn_nomatch
|
||||||
|
| emqx_authn_total
|
||||||
|
| emqx_authn_success
|
||||||
|
| emqx_authn_failed
|
||||||
|
| emqx_authn_rate
|
||||||
|
| emqx_authn_rate_last5m
|
||||||
|
| emqx_authn_rate_max.
|
||||||
|
|
||||||
|
-type authz_metric_key() ::
|
||||||
|
emqx_authz_enable
|
||||||
|
| emqx_authz_status
|
||||||
|
| emqx_authz_nomatch
|
||||||
|
| emqx_authz_total
|
||||||
|
| emqx_authz_success
|
||||||
|
| emqx_authz_failed
|
||||||
|
| emqx_authz_rate
|
||||||
|
| emqx_authz_rate_last5m
|
||||||
|
| emqx_authz_rate_max.
|
||||||
|
|
||||||
|
%% Please don't remove this attribute, prometheus uses it to
|
||||||
|
%% automatically register collectors.
|
||||||
|
-behaviour(prometheus_collector).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Macros
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-define(METRIC_NAME_PREFIX, "emqx_auth_").
|
||||||
|
|
||||||
|
-define(MG(K, MAP), maps:get(K, MAP)).
|
||||||
|
-define(MG0(K, MAP), maps:get(K, MAP, 0)).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Collector API
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
%% @private
|
||||||
|
deregister_cleanup(_) -> ok.
|
||||||
|
|
||||||
|
%% @private
|
||||||
|
-spec collect_mf(_Registry, Callback) -> ok when
|
||||||
|
_Registry :: prometheus_registry:registry(),
|
||||||
|
Callback :: prometheus_collector:collect_mf_callback().
|
||||||
|
%% erlfmt-ignore
|
||||||
|
collect_mf(?PROMETHEUS_AUTH_REGISTRY, Callback) ->
|
||||||
|
_ = [add_collect_family(Name, authn_data(), Callback, gauge) || Name <- authn()],
|
||||||
|
_ = [add_collect_family(Name, authn_users_count_data(), Callback, gauge) || Name <- authn_users_count()],
|
||||||
|
_ = [add_collect_family(Name, authz_data(), Callback, gauge) || Name <- authz()],
|
||||||
|
_ = [add_collect_family(Name, authz_rules_count_data(), Callback, gauge) || Name <- authz_rules_count()],
|
||||||
|
_ = [add_collect_family(Name, banned_count_data(), Callback, gauge) || Name <- banned()],
|
||||||
|
ok;
|
||||||
|
collect_mf(_, _) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
%% @private
|
||||||
|
collect(<<"json">>) ->
|
||||||
|
%% TODO
|
||||||
|
#{};
|
||||||
|
collect(<<"prometheus">>) ->
|
||||||
|
prometheus_text_format:format(?PROMETHEUS_AUTH_REGISTRY).
|
||||||
|
|
||||||
|
add_collect_family(Name, Data, Callback, Type) ->
|
||||||
|
Callback(create_mf(Name, _Help = <<"">>, Type, ?MODULE, Data)).
|
||||||
|
|
||||||
|
collect_metrics(Name, Metrics) ->
|
||||||
|
collect_auth(Name, Metrics).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Collector
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
%%====================
|
||||||
|
%% Authn overview
|
||||||
|
collect_auth(K = emqx_authn_enable, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authn_status, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authn_nomatch, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authn_total, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authn_success, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authn_failed, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authn_rate, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authn_rate_last5m, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authn_rate_max, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
%%====================
|
||||||
|
%% Authn users count
|
||||||
|
%% Only provided for `password_based:built_in_database` and `scram:built_in_database`
|
||||||
|
collect_auth(K = emqx_authn_users_count, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
%%====================
|
||||||
|
%% Authz overview
|
||||||
|
collect_auth(K = emqx_authz_enable, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authz_status, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authz_nomatch, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authz_total, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authz_success, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authz_failed, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authz_rate, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authz_rate_last5m, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
collect_auth(K = emqx_authz_rate_max, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
%%====================
|
||||||
|
%% Authz rules count
|
||||||
|
%% Only provided for `file` and `built_in_database`
|
||||||
|
collect_auth(K = emqx_authz_rules_count, Data) ->
|
||||||
|
gauge_metrics(?MG(K, Data));
|
||||||
|
%%====================
|
||||||
|
%% Banned
|
||||||
|
collect_auth(emqx_banned_count, Data) ->
|
||||||
|
gauge_metric(Data).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Internal functions
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
%%========================================
|
||||||
|
%% AuthN (Authentication)
|
||||||
|
%%========================================
|
||||||
|
|
||||||
|
%%====================
|
||||||
|
%% Authn overview
|
||||||
|
authn() ->
|
||||||
|
[
|
||||||
|
emqx_authn_enable,
|
||||||
|
emqx_authn_status,
|
||||||
|
emqx_authn_nomatch,
|
||||||
|
emqx_authn_total,
|
||||||
|
emqx_authn_success,
|
||||||
|
emqx_authn_failed,
|
||||||
|
emqx_authn_rate,
|
||||||
|
emqx_authn_rate_last5m,
|
||||||
|
emqx_authn_rate_max
|
||||||
|
].
|
||||||
|
|
||||||
|
-spec authn_data() -> #{Key => [Point]} when
|
||||||
|
Key :: authn_metric_key(),
|
||||||
|
Point :: {[Label], Metric},
|
||||||
|
Label :: IdLabel,
|
||||||
|
IdLabel :: {id, AuthnName :: binary()},
|
||||||
|
Metric :: number().
|
||||||
|
authn_data() ->
|
||||||
|
Authns = emqx_config:get([authentication]),
|
||||||
|
lists:foldl(
|
||||||
|
fun(Key, AccIn) ->
|
||||||
|
AccIn#{Key => authn_backend_to_points(Key, Authns)}
|
||||||
|
end,
|
||||||
|
#{},
|
||||||
|
authn()
|
||||||
|
).
|
||||||
|
|
||||||
|
-spec authn_backend_to_points(Key, list(Authn)) -> list(Point) when
|
||||||
|
Key :: authn_metric_key(),
|
||||||
|
Authn :: map(),
|
||||||
|
Point :: {[Label], Metric},
|
||||||
|
Label :: IdLabel,
|
||||||
|
IdLabel :: {id, AuthnName :: binary()},
|
||||||
|
Metric :: number().
|
||||||
|
authn_backend_to_points(Key, Authns) ->
|
||||||
|
do_authn_backend_to_points(Key, Authns, []).
|
||||||
|
|
||||||
|
do_authn_backend_to_points(_K, [], AccIn) ->
|
||||||
|
lists:reverse(AccIn);
|
||||||
|
do_authn_backend_to_points(K, [Authn | Rest], AccIn) ->
|
||||||
|
Id = authenticator_id(Authn),
|
||||||
|
Point = {[{id, Id}], do_metric(K, Authn, lookup_authn_metrics_local(Id))},
|
||||||
|
do_authn_backend_to_points(K, Rest, [Point | AccIn]).
|
||||||
|
|
||||||
|
lookup_authn_metrics_local(Id) ->
|
||||||
|
case emqx_authn_api:lookup_from_local_node(?GLOBAL, Id) of
|
||||||
|
{ok, {_Node, Status, #{counters := Counters, rate := Rate}, _ResourceMetrics}} ->
|
||||||
|
#{
|
||||||
|
emqx_authn_status => status_to_number(Status),
|
||||||
|
emqx_authn_nomatch => ?MG0(nomatch, Counters),
|
||||||
|
emqx_authn_total => ?MG0(total, Counters),
|
||||||
|
emqx_authn_success => ?MG0(success, Counters),
|
||||||
|
emqx_authn_failed => ?MG0(failed, Counters),
|
||||||
|
emqx_authn_rate => ?MG0(current, Rate),
|
||||||
|
emqx_authn_rate_last5m => ?MG0(last5m, Rate),
|
||||||
|
emqx_authn_rate_max => ?MG0(max, Rate)
|
||||||
|
};
|
||||||
|
{error, _Reason} ->
|
||||||
|
maps:from_keys(authn() -- [emqx_authn_enable], 0)
|
||||||
|
end.
|
||||||
|
|
||||||
|
%%====================
|
||||||
|
%% Authn users count
|
||||||
|
|
||||||
|
authn_users_count() ->
|
||||||
|
[emqx_authn_users_count].
|
||||||
|
|
||||||
|
-define(AUTHN_MNESIA, emqx_authn_mnesia).
|
||||||
|
-define(AUTHN_SCRAM_MNESIA, emqx_authn_scram_mnesia).
|
||||||
|
|
||||||
|
authn_users_count_data() ->
|
||||||
|
Samples = lists:foldl(
|
||||||
|
fun
|
||||||
|
(#{backend := built_in_database, mechanism := password_based} = Authn, AccIn) ->
|
||||||
|
[auth_data_sample_point(authn, Authn, ?AUTHN_MNESIA) | AccIn];
|
||||||
|
(#{backend := built_in_database, mechanism := scram} = Authn, AccIn) ->
|
||||||
|
[auth_data_sample_point(authn, Authn, ?AUTHN_SCRAM_MNESIA) | AccIn];
|
||||||
|
(_, AccIn) ->
|
||||||
|
AccIn
|
||||||
|
end,
|
||||||
|
[],
|
||||||
|
emqx_config:get([authentication])
|
||||||
|
),
|
||||||
|
#{emqx_authn_users_count => Samples}.
|
||||||
|
|
||||||
|
%%========================================
|
||||||
|
%% AuthZ (Authorization)
|
||||||
|
%%========================================
|
||||||
|
|
||||||
|
%%====================
|
||||||
|
%% Authz overview
|
||||||
|
authz() ->
|
||||||
|
[
|
||||||
|
emqx_authz_enable,
|
||||||
|
emqx_authz_status,
|
||||||
|
emqx_authz_nomatch,
|
||||||
|
emqx_authz_total,
|
||||||
|
emqx_authz_success,
|
||||||
|
emqx_authz_failed,
|
||||||
|
emqx_authz_rate,
|
||||||
|
emqx_authz_rate_last5m,
|
||||||
|
emqx_authz_rate_max
|
||||||
|
].
|
||||||
|
|
||||||
|
-spec authz_data() -> #{Key => [Point]} when
|
||||||
|
Key :: authz_metric_key(),
|
||||||
|
Point :: {[Label], Metric},
|
||||||
|
Label :: TypeLabel,
|
||||||
|
TypeLabel :: {type, AuthZType :: binary()},
|
||||||
|
Metric :: number().
|
||||||
|
authz_data() ->
|
||||||
|
Authzs = emqx_config:get([authorization, sources]),
|
||||||
|
lists:foldl(
|
||||||
|
fun(Key, AccIn) ->
|
||||||
|
AccIn#{Key => authz_backend_to_points(Key, Authzs)}
|
||||||
|
end,
|
||||||
|
#{},
|
||||||
|
authz()
|
||||||
|
).
|
||||||
|
|
||||||
|
-spec authz_backend_to_points(Key, list(Authz)) -> list(Point) when
|
||||||
|
Key :: authz_metric_key(),
|
||||||
|
Authz :: map(),
|
||||||
|
Point :: {[Label], Metric},
|
||||||
|
Label :: TypeLabel,
|
||||||
|
TypeLabel :: {type, AuthZType :: binary()},
|
||||||
|
Metric :: number().
|
||||||
|
authz_backend_to_points(Key, Authzs) ->
|
||||||
|
do_authz_backend_to_points(Key, Authzs, []).
|
||||||
|
|
||||||
|
do_authz_backend_to_points(_K, [], AccIn) ->
|
||||||
|
lists:reverse(AccIn);
|
||||||
|
do_authz_backend_to_points(K, [Authz | Rest], AccIn) ->
|
||||||
|
Type = maps:get(type, Authz),
|
||||||
|
Point = {[{type, Type}], do_metric(K, Authz, lookup_authz_metrics_local(Type))},
|
||||||
|
do_authz_backend_to_points(K, Rest, [Point | AccIn]).
|
||||||
|
|
||||||
|
lookup_authz_metrics_local(Type) ->
|
||||||
|
case emqx_authz_api_sources:lookup_from_local_node(Type) of
|
||||||
|
{ok, {_Node, Status, #{counters := Counters, rate := Rate}, _ResourceMetrics}} ->
|
||||||
|
#{
|
||||||
|
emqx_authz_status => status_to_number(Status),
|
||||||
|
emqx_authz_nomatch => ?MG0(nomatch, Counters),
|
||||||
|
emqx_authz_total => ?MG0(total, Counters),
|
||||||
|
emqx_authz_success => ?MG0(success, Counters),
|
||||||
|
emqx_authz_failed => ?MG0(failed, Counters),
|
||||||
|
emqx_authz_rate => ?MG0(current, Rate),
|
||||||
|
emqx_authz_rate_last5m => ?MG0(last5m, Rate),
|
||||||
|
emqx_authz_rate_max => ?MG0(max, Rate)
|
||||||
|
};
|
||||||
|
{error, _Reason} ->
|
||||||
|
maps:from_keys(authz() -- [emqx_authz_enable], 0)
|
||||||
|
end.
|
||||||
|
|
||||||
|
%%====================
|
||||||
|
%% Authz rules count
|
||||||
|
|
||||||
|
authz_rules_count() ->
|
||||||
|
[emqx_authz_rules_count].
|
||||||
|
|
||||||
|
-define(ACL_TABLE, emqx_acl).
|
||||||
|
|
||||||
|
authz_rules_count_data() ->
|
||||||
|
Samples = lists:foldl(
|
||||||
|
fun
|
||||||
|
(#{type := built_in_database} = Authz, AccIn) ->
|
||||||
|
[auth_data_sample_point(authz, Authz, ?ACL_TABLE) | AccIn];
|
||||||
|
(#{type := file}, AccIn) ->
|
||||||
|
#{annotations := #{rules := Rules}} = emqx_authz:lookup(file),
|
||||||
|
Size = erlang:length(Rules),
|
||||||
|
[{[{type, file}], Size} | AccIn];
|
||||||
|
(_, AccIn) ->
|
||||||
|
AccIn
|
||||||
|
end,
|
||||||
|
[],
|
||||||
|
emqx_config:get([authorization, sources])
|
||||||
|
),
|
||||||
|
#{emqx_authz_rules_count => Samples}.
|
||||||
|
|
||||||
|
%%========================================
|
||||||
|
%% Banned
|
||||||
|
%%========================================
|
||||||
|
|
||||||
|
%%====================
|
||||||
|
%% Banned count
|
||||||
|
|
||||||
|
banned() ->
|
||||||
|
[emqx_banned_count].
|
||||||
|
|
||||||
|
-define(BANNED_TABLE, emqx_banned).
|
||||||
|
banned_count_data() ->
|
||||||
|
mnesia_size(?BANNED_TABLE).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Helper functions
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
authenticator_id(Authn) ->
|
||||||
|
emqx_authn_chains:authenticator_id(Authn).
|
||||||
|
|
||||||
|
auth_data_sample_point(authn, Authn, Tab) ->
|
||||||
|
Size = mnesia_size(Tab),
|
||||||
|
Id = authenticator_id(Authn),
|
||||||
|
{[{id, Id}], Size};
|
||||||
|
auth_data_sample_point(authz, #{type := Type} = _Authz, Tab) ->
|
||||||
|
Size = mnesia_size(Tab),
|
||||||
|
{[{type, Type}], Size}.
|
||||||
|
|
||||||
|
mnesia_size(Tab) ->
|
||||||
|
mnesia:table_info(Tab, size).
|
||||||
|
|
||||||
|
do_metric(emqx_authn_enable, #{enable := B}, _) ->
|
||||||
|
boolean_to_number(B);
|
||||||
|
do_metric(K, _, Metrics) ->
|
||||||
|
?MG0(K, Metrics).
|
||||||
|
|
||||||
|
boolean_to_number(true) -> 1;
|
||||||
|
boolean_to_number(false) -> 0.
|
||||||
|
|
||||||
|
status_to_number(connected) -> 1;
|
||||||
|
status_to_number(stopped) -> 0.
|
|
@ -101,7 +101,7 @@ post_config_update(_ConfPath, _Req, _NewConf, _OldConf, _AppEnvs) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
update_prometheus(AppEnvs) ->
|
update_prometheus(AppEnvs) ->
|
||||||
PrevCollectors = prometheus_registry:collectors(default),
|
PrevCollectors = all_collectors(),
|
||||||
CurCollectors = proplists:get_value(collectors, proplists:get_value(prometheus, AppEnvs)),
|
CurCollectors = proplists:get_value(collectors, proplists:get_value(prometheus, AppEnvs)),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun prometheus_registry:deregister_collector/1,
|
fun prometheus_registry:deregister_collector/1,
|
||||||
|
@ -113,6 +113,15 @@ update_prometheus(AppEnvs) ->
|
||||||
),
|
),
|
||||||
application:set_env(AppEnvs).
|
application:set_env(AppEnvs).
|
||||||
|
|
||||||
|
all_collectors() ->
|
||||||
|
lists:foldl(
|
||||||
|
fun(Registry, AccIn) ->
|
||||||
|
prometheus_registry:collectors(Registry) ++ AccIn
|
||||||
|
end,
|
||||||
|
_InitAcc = [],
|
||||||
|
?PROMETHEUS_ALL_REGISTRYS
|
||||||
|
).
|
||||||
|
|
||||||
update_push_gateway(Prometheus) ->
|
update_push_gateway(Prometheus) ->
|
||||||
case is_push_gateway_server_enabled(Prometheus) of
|
case is_push_gateway_server_enabled(Prometheus) of
|
||||||
true ->
|
true ->
|
||||||
|
|
|
@ -15,4 +15,9 @@ get_prom_data.desc:
|
||||||
get_prom_data.label:
|
get_prom_data.label:
|
||||||
"""Prometheus Metrics"""
|
"""Prometheus Metrics"""
|
||||||
|
|
||||||
|
get_prom_auth_data.desc:
|
||||||
|
"""Get Prometheus Metrics for AuthN, AuthZ and Banned"""
|
||||||
|
get_prom_auth_data.label:
|
||||||
|
"""Prometheus Metrics for Auth"""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue