refactor(metrics): more understandable auth metrics

`client.auth.success`/`client.auth.failure`
`client.auth.success.anonymous`
This commit is contained in:
JimMoen 2022-05-20 13:36:30 +08:00
parent 5e3b0cf2d8
commit 9435fe0bb9
3 changed files with 74 additions and 30 deletions

View File

@ -34,11 +34,15 @@
-spec(authenticate(emqx_types:clientinfo()) -> {ok, result()} | {error, term()}). -spec(authenticate(emqx_types:clientinfo()) -> {ok, result()} | {error, term()}).
authenticate(ClientInfo = #{zone := Zone}) -> authenticate(ClientInfo = #{zone := Zone}) ->
AuthResult = default_auth_result(Zone), AuthResult = default_auth_result(Zone),
case emqx_zone:get_env(Zone, bypass_auth_plugins, false) of case
begin ok = emqx_metrics:inc('client.authenticate'),
emqx_zone:get_env(Zone, bypass_auth_plugins, false)
end
of
true -> true ->
return_auth_result(AuthResult); return_auth_result(AuthResult);
false -> false ->
return_auth_result(run_hooks('client.authenticate', [ClientInfo], AuthResult)) return_auth_result(emqx_hooks:run_fold('client.authenticate', [ClientInfo], AuthResult))
end. end.
%% @doc Check ACL %% @doc Check ACL
@ -51,6 +55,10 @@ check_acl(ClientInfo, PubSub, Topic) ->
end, end,
inc_acl_metrics(Result), Result. inc_acl_metrics(Result), Result.
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
%% ACL
check_acl_cache(ClientInfo, PubSub, Topic) -> check_acl_cache(ClientInfo, PubSub, Topic) ->
case emqx_acl_cache:get_acl_cache(PubSub, Topic) of case emqx_acl_cache:get_acl_cache(PubSub, Topic) of
not_found -> not_found ->
@ -64,21 +72,16 @@ check_acl_cache(ClientInfo, PubSub, Topic) ->
do_check_acl(ClientInfo = #{zone := Zone}, PubSub, Topic) -> do_check_acl(ClientInfo = #{zone := Zone}, PubSub, Topic) ->
Default = emqx_zone:get_env(Zone, acl_nomatch, deny), Default = emqx_zone:get_env(Zone, acl_nomatch, deny),
case run_hooks('client.check_acl', [ClientInfo, PubSub, Topic], Default) of case
begin
ok = emqx_metrics:inc('client.check_acl'),
emqx_hooks:run_fold('client.check_acl', [ClientInfo, PubSub, Topic], Default)
end
of
allow -> allow; allow -> allow;
_Other -> deny _Other -> deny
end. end.
default_auth_result(Zone) ->
case emqx_zone:get_env(Zone, allow_anonymous, false) of
true -> #{auth_result => success, anonymous => true};
false -> #{auth_result => not_authorized, anonymous => false}
end.
-compile({inline, [run_hooks/3]}).
run_hooks(Name, Args, Acc) ->
ok = emqx_metrics:inc(Name), emqx_hooks:run_fold(Name, Args, Acc).
-compile({inline, [inc_acl_metrics/1]}). -compile({inline, [inc_acl_metrics/1]}).
inc_acl_metrics(allow) -> inc_acl_metrics(allow) ->
emqx_metrics:inc('client.acl.allow'); emqx_metrics:inc('client.acl.allow');
@ -87,8 +90,26 @@ inc_acl_metrics(deny) ->
inc_acl_metrics(cache_hit) -> inc_acl_metrics(cache_hit) ->
emqx_metrics:inc('client.acl.cache_hit'). emqx_metrics:inc('client.acl.cache_hit').
%% Auth
default_auth_result(Zone) ->
case emqx_zone:get_env(Zone, allow_anonymous, false) of
true -> #{auth_result => success, anonymous => true};
false -> #{auth_result => not_authorized, anonymous => false}
end.
-compile({inline, [return_auth_result/1]}). -compile({inline, [return_auth_result/1]}).
return_auth_result(Result = #{auth_result := success}) -> return_auth_result(AuthResult = #{auth_result := success}) ->
{ok, Result}; inc_auth_success_metrics(AuthResult),
return_auth_result(Result) -> {ok, AuthResult};
{error, maps:get(auth_result, Result, unknown_error)}. return_auth_result(AuthResult) ->
emqx_metrics:inc('client.auth.failure'),
{error, maps:get(auth_result, AuthResult, unknown_error)}.
-compile({inline, [inc_auth_success_metrics/1]}).
inc_auth_success_metrics(AuthResult) ->
is_anonymous(AuthResult) andalso
emqx_metrics:inc('client.auth.success.anonymous'),
emqx_metrics:inc('client.auth.success').
is_anonymous(#{anonymous := true}) -> true;
is_anonymous(_AuthResult) -> false.

View File

@ -1285,8 +1285,6 @@ auth_connect(#mqtt_packet_connect{password = Password},
username := Username} = ClientInfo, username := Username} = ClientInfo,
case emqx_access_control:authenticate(ClientInfo#{password => Password}) of case emqx_access_control:authenticate(ClientInfo#{password => Password}) of
{ok, AuthResult} -> {ok, AuthResult} ->
is_anonymous(AuthResult) andalso
emqx_metrics:inc('client.auth.anonymous'),
NClientInfo = maps:merge(ClientInfo, AuthResult), NClientInfo = maps:merge(ClientInfo, AuthResult),
{ok, Channel#channel{clientinfo = NClientInfo}}; {ok, Channel#channel{clientinfo = NClientInfo}};
{error, Reason} -> {error, Reason} ->
@ -1295,9 +1293,6 @@ auth_connect(#mqtt_packet_connect{password = Password},
{error, emqx_reason_codes:connack_error(Reason)} {error, emqx_reason_codes:connack_error(Reason)}
end. end.
is_anonymous(#{anonymous := true}) -> true;
is_anonymous(_AuthResult) -> false.
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Enhanced Authentication %% Enhanced Authentication

View File

@ -68,8 +68,10 @@
%% BACKW %% BACKW
-export([%% v4.3.0 -export([%% v4.3.0
upgrade_retained_delayed_counter_type/0, upgrade_retained_delayed_counter_type/0,
%% e4.4.0, e4.3.0-e4.3.6, v4.3.0-v4.3.11 %% v4.3.0-v4.3.11, e4.3.0-e4.3.6; v4.4.0, e4.4.0
assign_acl_stats_from_ets_to_counter/0 assign_acl_stats_from_ets_to_counter/0,
%% v4.3.0-v4.3.14, e4.3.0-e4.3.9; v4.4.0-v4.4.3, e4.4.0-e4.4.3,
assign_auth_stats_from_ets_to_counter/0
]). ]).
-export_type([metric_idx/0]). -export_type([metric_idx/0]).
@ -174,7 +176,6 @@
{counter, 'client.connack'}, {counter, 'client.connack'},
{counter, 'client.connected'}, {counter, 'client.connected'},
{counter, 'client.authenticate'}, {counter, 'client.authenticate'},
{counter, 'client.auth.anonymous'},
{counter, 'client.check_acl'}, {counter, 'client.check_acl'},
{counter, 'client.subscribe'}, {counter, 'client.subscribe'},
{counter, 'client.unsubscribe'}, {counter, 'client.unsubscribe'},
@ -189,8 +190,16 @@
{counter, 'session.discarded'}, {counter, 'session.discarded'},
{counter, 'session.terminated'} {counter, 'session.terminated'}
]). ]).
%% Statistic metrics for ACL checking
-define(STASTS_ACL_METRICS, %% Statistic metrics for auth checking
-define(STATS_AUTH_METRICS,
[ {counter, 'client.auth.success'},
{counter, 'client.auth.success.anonymous'},
{counter, 'client.auth.failure'}
]).
%% Statistic metrics for ACL checking stats
-define(STATS_ACL_METRICS,
[ {counter, 'client.acl.allow'}, [ {counter, 'client.acl.allow'},
{counter, 'client.acl.deny'}, {counter, 'client.acl.deny'},
{counter, 'client.acl.cache_hit'} {counter, 'client.acl.cache_hit'}
@ -228,6 +237,21 @@ assign_acl_stats_from_ets_to_counter() ->
ok = counters:put(CRef, Idx, Val) ok = counters:put(CRef, Idx, Val)
end, Names). end, Names).
%% BACKW: %% v4.3.0-v4.3.14, e4.3.0-e4.3.9; v4.4.0-v4.4.3, e4.4.0-e4.4.3,
assign_auth_stats_from_ets_to_counter() ->
CRef = persistent_term:get(?MODULE),
Names = ['client.auth.success', 'client.auth.success.anonymous', 'client.auth.failure'],
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 %% Metrics API
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -458,7 +482,8 @@ init([]) ->
?DELIVERY_METRICS, ?DELIVERY_METRICS,
?CLIENT_METRICS, ?CLIENT_METRICS,
?SESSION_METRICS, ?SESSION_METRICS,
?STASTS_ACL_METRICS ?STATS_AUTH_METRICS,
?STATS_ACL_METRICS
]), ]),
% Store reserved indices % Store reserved indices
ok = lists:foreach(fun({Type, Name}) -> ok = lists:foreach(fun({Type, Name}) ->
@ -592,7 +617,6 @@ reserved_idx('client.connack') -> 201;
reserved_idx('client.connected') -> 202; reserved_idx('client.connected') -> 202;
reserved_idx('client.authenticate') -> 203; reserved_idx('client.authenticate') -> 203;
reserved_idx('client.enhanced_authenticate') -> 204; reserved_idx('client.enhanced_authenticate') -> 204;
reserved_idx('client.auth.anonymous') -> 205;
reserved_idx('client.check_acl') -> 206; reserved_idx('client.check_acl') -> 206;
reserved_idx('client.subscribe') -> 207; reserved_idx('client.subscribe') -> 207;
reserved_idx('client.unsubscribe') -> 208; reserved_idx('client.unsubscribe') -> 208;
@ -604,9 +628,13 @@ reserved_idx('session.takeovered') -> 222;
reserved_idx('session.discarded') -> 223; reserved_idx('session.discarded') -> 223;
reserved_idx('session.terminated') -> 224; reserved_idx('session.terminated') -> 224;
%% Stats metrics %% Stats metrics
%% ACL
reserved_idx('client.acl.allow') -> 300; reserved_idx('client.acl.allow') -> 300;
reserved_idx('client.acl.deny') -> 301; reserved_idx('client.acl.deny') -> 301;
reserved_idx('client.acl.cache_hit') -> 302; reserved_idx('client.acl.cache_hit') -> 302;
%% Auth
reserved_idx('client.auth.success') -> 310;
reserved_idx('client.auth.success.anonymous') -> 311;
reserved_idx('client.auth.failure') -> 312;
reserved_idx(_) -> undefined. reserved_idx(_) -> undefined.