diff --git a/src/emqx_access_control.erl b/src/emqx_access_control.erl index 1ef885ed5..fb0741c0c 100644 --- a/src/emqx_access_control.erl +++ b/src/emqx_access_control.erl @@ -45,10 +45,11 @@ authenticate(ClientInfo = #{zone := Zone}) -> -spec(check_acl(emqx_types:clientinfo(), emqx_types:pubsub(), emqx_types:topic()) -> allow | deny). check_acl(ClientInfo, PubSub, Topic) -> - case emqx_acl_cache:is_enabled() of + Result = case emqx_acl_cache:is_enabled() of true -> check_acl_cache(ClientInfo, PubSub, Topic); false -> do_check_acl(ClientInfo, PubSub, Topic) - end. + end, + inc_acl_metrics(Result), Result. check_acl_cache(ClientInfo, PubSub, Topic) -> case emqx_acl_cache:get_acl_cache(PubSub, Topic) of @@ -56,7 +57,9 @@ check_acl_cache(ClientInfo, PubSub, Topic) -> AclResult = do_check_acl(ClientInfo, PubSub, Topic), emqx_acl_cache:put_acl_cache(PubSub, Topic, AclResult), AclResult; - AclResult -> AclResult + AclResult -> + inc_acl_metrics(cache_hit), + AclResult end. do_check_acl(ClientInfo = #{zone := Zone}, PubSub, Topic) -> @@ -76,6 +79,14 @@ default_auth_result(Zone) -> run_hooks(Name, Args, Acc) -> ok = emqx_metrics:inc(Name), emqx_hooks:run_fold(Name, Args, Acc). +-compile({inline, [inc_acl_metrics/1]}). +inc_acl_metrics(allow) -> + emqx_metrics:inc('client.acl.allow'); +inc_acl_metrics(deny) -> + emqx_metrics:inc('client.acl.deny'); +inc_acl_metrics(cache_hit) -> + emqx_metrics:inc('client.acl.cache_hit'). + -compile({inline, [return_auth_result/1]}). return_auth_result(Result = #{auth_result := success}) -> {ok, Result}; diff --git a/src/emqx_metrics.erl b/src/emqx_metrics.erl index 6cd4d05b1..8189b6218 100644 --- a/src/emqx_metrics.erl +++ b/src/emqx_metrics.erl @@ -65,8 +65,11 @@ , code_change/3 ]). -%% BACKW: v4.3.0 --export([ upgrade_retained_delayed_counter_type/0 +%% BACKW +-export([%% v4.3.0 + upgrade_retained_delayed_counter_type/0, + %% e4.4.0, e4.3.0-e4.3.6, v4.3.0-v4.3.11 + assign_acl_stats_from_ets_to_counter/0 ]). -export_type([metric_idx/0]). @@ -186,6 +189,12 @@ {counter, 'session.discarded'}, {counter, 'session.terminated'} ]). +%% Statistic metrics for ACL checking +-define(STASTS_ACL_METRICS, + [ {counter, 'client.acl.allow'}, + {counter, 'client.acl.deny'}, + {counter, 'client.acl.cache_hit'} + ]). -record(state, {next_idx = 1}). @@ -204,6 +213,21 @@ upgrade_retained_delayed_counter_type() -> Ks = ['messages.retained', 'messages.delayed'], gen_server:call(?SERVER, {set_type_to_counter, Ks}, infinity). +%% BACKW: %% e4.4.0, e4.3.0-e4.3.6, v4.3.0-v4.3.11 +assign_acl_stats_from_ets_to_counter() -> + CRef = persistent_term:get(?MODULE), + Names = ['client.acl.allow', 'client.acl.deny', 'client.acl.cache_hit'], + lists:foreach(fun(Name) -> + Val = case emqx_metrics:val(Name) of + undefined -> 0; + Val0 -> Val0 + end, + Idx = reserved_idx(Name), + Metric = #metric{name = Name, type = counter, idx = Idx}, + ok = gen_server:call(?SERVER, {set, Metric}), + ok = counters:put(CRef, Idx, Val) + end, Names). + %%-------------------------------------------------------------------- %% Metrics API %%-------------------------------------------------------------------- @@ -433,7 +457,8 @@ init([]) -> ?MESSAGE_METRICS, ?DELIVERY_METRICS, ?CLIENT_METRICS, - ?SESSION_METRICS + ?SESSION_METRICS, + ?STASTS_ACL_METRICS ]), % Store reserved indices ok = lists:foreach(fun({Type, Name}) -> @@ -466,6 +491,10 @@ handle_call({set_type_to_counter, Keys}, _From, State) -> end, Keys), {reply, ok, State}; +handle_call({set, Metric}, _From, State) -> + true = ets:insert(?TAB, Metric), + {reply, ok, State}; + handle_call(Req, _From, State) -> ?LOG(error, "Unexpected call: ~p", [Req]), {reply, ignored, State}. @@ -574,6 +603,10 @@ reserved_idx('session.resumed') -> 221; reserved_idx('session.takeovered') -> 222; reserved_idx('session.discarded') -> 223; reserved_idx('session.terminated') -> 224; +%% Stats metrics +reserved_idx('client.acl.allow') -> 300; +reserved_idx('client.acl.deny') -> 301; +reserved_idx('client.acl.cache_hit') -> 302; reserved_idx(_) -> undefined.