fix: improve authn, authz metrics

This commit is contained in:
EMQ-YangM 2022-05-05 14:32:03 +08:00
parent 28b7021322
commit 30b3060327
10 changed files with 199 additions and 73 deletions

View File

@ -616,8 +616,8 @@ handle_create_authenticator(Chain, Config, Providers) ->
ok = emqx_metrics_worker:create_metrics( ok = emqx_metrics_worker:create_metrics(
authn_metrics, authn_metrics,
AuthenticatorID, AuthenticatorID,
[matched, success, failed, ignore], [total, success, failed, nomatch],
[matched] [total]
), ),
{ok, serialize_authenticator(Authenticator)}; {ok, serialize_authenticator(Authenticator)};
{error, Reason} -> {error, Reason} ->
@ -628,10 +628,10 @@ handle_create_authenticator(Chain, Config, Providers) ->
do_authenticate([], _) -> do_authenticate([], _) ->
{stop, {error, not_authorized}}; {stop, {error, not_authorized}};
do_authenticate([#authenticator{id = ID, provider = Provider, state = State} | More], Credential) -> do_authenticate([#authenticator{id = ID, provider = Provider, state = State} | More], Credential) ->
emqx_metrics_worker:inc(authn_metrics, ID, matched), emqx_metrics_worker:inc(authn_metrics, ID, total),
try Provider:authenticate(Credential, State) of try Provider:authenticate(Credential, State) of
ignore -> ignore ->
ok = emqx_metrics_worker:inc(authn_metrics, ID, ignore), ok = emqx_metrics_worker:inc(authn_metrics, ID, nomatch),
do_authenticate(More, Credential); do_authenticate(More, Credential);
Result -> Result ->
%% {ok, Extra} %% {ok, Extra}
@ -657,7 +657,7 @@ do_authenticate([#authenticator{id = ID, provider = Provider, state = State} | M
stacktrace => Stacktrace, stacktrace => Stacktrace,
authenticator => ID authenticator => ID
}), }),
emqx_metrics_worker:inc(authn_metrics, ID, ignore), emqx_metrics_worker:inc(authn_metrics, ID, nomatch),
do_authenticate(More, Credential) do_authenticate(More, Credential)
end. end.

View File

@ -163,4 +163,81 @@ emqx_authn_schema {
zh: """节点名称。""" zh: """节点名称。"""
} }
} }
metrics_nomatch {
desc {
en: """The number of times the instance was ignored when the required authentication information was not found in the current instance."""
zh: """在当前实例中没有找到需要的认证信息,实例被忽略的次数。"""
}
label: {
en: """Nomatch Times"""
zh: """实例被忽略的次数"""
}
}
metrics_total {
desc {
en: """The total number of times the current instance was triggered."""
zh: """当前实例被触发的总次数。"""
}
label: {
en: """Total Triggered Times"""
zh: """当前实例被触发的总次数"""
}
}
metrics_success {
desc {
en: """The required authentication information is found in the current instance, and the instance returns authentication success."""
zh: """在当前实例中找到需要的认证信息,并且实例返回认证成功的次数。"""
}
label: {
en: """Authentication Success Times"""
zh: """实例认证成功的次数"""
}
}
metrics_failed {
desc {
en: """The required authentication information is found in the current instance, and the instance returns authentication failure."""
zh: """在当前实例中找到需要的认证信息,并且实例返回认证失败的次数。"""
}
label: {
en: """Authentication Failed Times"""
zh: """实例认证失败的次数"""
}
}
metrics_rate {
desc {
en: """The total rate at which instances are triggered, times/second."""
zh: """实例被触发的速率。触发速率等于匹配速率 + 忽略速率,单位:次/秒。"""
}
label: {
en: """Total Triggered Rate"""
zh: """实例被触发的速率"""
}
}
metrics_rate_max {
desc {
en: """The highest trigger rate the instance has ever reached, times/second."""
zh: """实例曾经达到的最高触发速率,单位:次/秒。"""
}
label: {
en: """Highest Triggered Rate"""
zh: """实例曾经达到的最高触发速率"""
}
}
metrics_rate_last5m {
desc {
en: """The average trigger rate of the instance within 5 minutes, times/second."""
zh: """实例5分钟内平均触发速率单位次/秒。"""
}
label: {
en: """Average Triggered Rate in Last 5min"""
zh: """实例5分钟内平均触发速率"""
}
}
} }

View File

@ -1036,14 +1036,14 @@ make_result_map(ResList) ->
lists:foldl(Fun, {maps:new(), maps:new(), maps:new(), maps:new()}, ResList). lists:foldl(Fun, {maps:new(), maps:new(), maps:new(), maps:new()}, ResList).
restructure_map(#{ restructure_map(#{
counters := #{failed := Failed, matched := Match, success := Succ, ignore := Ignore}, counters := #{failed := Failed, total := Total, success := Succ, nomatch := Nomatch},
rate := #{matched := #{current := Rate, last5m := Rate5m, max := RateMax}} rate := #{total := #{current := Rate, last5m := Rate5m, max := RateMax}}
}) -> }) ->
#{ #{
matched => Match, total => Total,
success => Succ, success => Succ,
failed => Failed, failed => Failed,
ignore => Ignore, nomatch => Nomatch,
rate => Rate, rate => Rate,
rate_last5m => Rate5m, rate_last5m => Rate5m,
rate_max => RateMax rate_max => RateMax
@ -1451,11 +1451,32 @@ status_metrics_example() ->
status_metrics => #{ status_metrics => #{
summary => <<"Authn status metrics">>, summary => <<"Authn status metrics">>,
value => #{ value => #{
metrics => #{ resource_metrics => #{
matched => 0, matched => 0,
success => 0, success => 0,
failed => 0, failed => 0,
ignore => 0, rate => 0.0,
rate_last5m => 0.0,
rate_max => 0.0
},
node_resource_metrics => [
#{
node => node(),
metrics => #{
matched => 0,
success => 0,
failed => 0,
rate => 0.0,
rate_last5m => 0.0,
rate_max => 0.0
}
}
],
metrics => #{
total => 0,
success => 0,
failed => 0,
nomatch => 0,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.0 rate_max => 0.0
@ -1466,9 +1487,9 @@ status_metrics_example() ->
node => node(), node => node(),
metrics => #{ metrics => #{
matched => 0, matched => 0,
success => 0, total => 0,
failed => 0, failed => 0,
ignore => 0, nomatch => 0,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.0 rate_max => 0.0

View File

@ -115,8 +115,14 @@ fields("metrics_status_fields") ->
]; ];
fields("metrics") -> fields("metrics") ->
[ [
{"ignore", mk(integer(), #{desc => ?DESC("failed")})} {"nomatch", mk(integer(), #{desc => ?DESC("metrics_nomatch")})},
] ++ common_field(); {"total", mk(integer(), #{desc => ?DESC("metrics_total")})},
{"success", mk(integer(), #{desc => ?DESC("metrics_success")})},
{"failed", mk(integer(), #{desc => ?DESC("metrics_failed")})},
{"rate", mk(float(), #{desc => ?DESC("metrics_rate")})},
{"rate_max", mk(float(), #{desc => ?DESC("metrics_rate_max")})},
{"rate_last5m", mk(float(), #{desc => ?DESC("metrics_rate_last5m")})}
];
fields("resource_metrics") -> fields("resource_metrics") ->
common_field(); common_field();
fields("node_metrics") -> fields("node_metrics") ->

View File

@ -125,24 +125,24 @@ t_aggregate_metrics(_) ->
metrics => metrics =>
#{ #{
failed => 0, failed => 0,
matched => 1, total => 1,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.1, rate_max => 0.1,
success => 1, success => 1,
ignore => 1 nomatch => 1
} }
}, },
'emqx@node2.emqx.io' => #{ 'emqx@node2.emqx.io' => #{
metrics => metrics =>
#{ #{
failed => 0, failed => 0,
matched => 1, total => 1,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.1, rate_max => 0.1,
success => 1, success => 1,
ignore => 2 nomatch => 2
} }
} }
}, },
@ -152,12 +152,12 @@ t_aggregate_metrics(_) ->
metrics => metrics =>
#{ #{
failed => 0, failed => 0,
matched => 2, total => 2,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.2, rate_max => 0.2,
success => 2, success => 2,
ignore => 3 nomatch => 3
} }
}, },
Res Res
@ -226,7 +226,7 @@ test_authenticator(PathPrefix) ->
LookFun = fun(List) -> LookupVal(List, RList) end, LookFun = fun(List) -> LookupVal(List, RList) end,
MetricsList = [ MetricsList = [
{<<"failed">>, 0}, {<<"failed">>, 0},
{<<"matched">>, 0}, {<<"total">>, 0},
{<<"rate">>, 0.0}, {<<"rate">>, 0.0},
{<<"rate_last5m">>, 0.0}, {<<"rate_last5m">>, 0.0},
{<<"rate_max">>, 0.0}, {<<"rate_max">>, 0.0},
@ -321,17 +321,17 @@ test_authenticator_users(PathPrefix) ->
[] -> [] ->
#{ #{
<<"metrics">> := #{ <<"metrics">> := #{
<<"matched">> := 1, <<"total">> := 1,
<<"success">> := 0, <<"success">> := 0,
<<"ignore">> := 1 <<"nomatch">> := 1
} }
} = jiffy:decode(PageData0, [return_maps]); } = jiffy:decode(PageData0, [return_maps]);
["listeners", 'tcp:default'] -> ["listeners", 'tcp:default'] ->
#{ #{
<<"metrics">> := #{ <<"metrics">> := #{
<<"matched">> := 1, <<"total">> := 1,
<<"success">> := 0, <<"success">> := 0,
<<"ignore">> := 1 <<"nomatch">> := 1
} }
} = jiffy:decode(PageData0, [return_maps]) } = jiffy:decode(PageData0, [return_maps])
end, end,
@ -379,17 +379,17 @@ test_authenticator_users(PathPrefix) ->
[] -> [] ->
#{ #{
<<"metrics">> := #{ <<"metrics">> := #{
<<"matched">> := 2, <<"total">> := 2,
<<"success">> := 1, <<"success">> := 1,
<<"ignore">> := 1 <<"nomatch">> := 1
} }
} = jiffy:decode(PageData01, [return_maps]); } = jiffy:decode(PageData01, [return_maps]);
["listeners", 'tcp:default'] -> ["listeners", 'tcp:default'] ->
#{ #{
<<"metrics">> := #{ <<"metrics">> := #{
<<"matched">> := 2, <<"total">> := 2,
<<"success">> := 1, <<"success">> := 1,
<<"ignore">> := 1 <<"nomatch">> := 1
} }
} = jiffy:decode(PageData01, [return_maps]) } = jiffy:decode(PageData01, [return_maps])
end, end,

View File

@ -528,36 +528,47 @@ Filter supports the following placeholders:
} }
} }
ignore { metrics_total {
desc { desc {
en: """Not match any rules.""" en: """The total number of times the authorization rule was triggered."""
zh: """没有匹配到任何规则。""" zh: """鉴权实例被触发的总次数。"""
} }
label: { label: {
en: """Not Match Any Rules""" en: """The Total Number of Times the Authorization Rule was Triggered"""
zh: """没有匹配到任何规则。""" zh: """鉴权实例被触发的总次数"""
}
}
nomatch {
desc {
en: """The number of times that no authorization rules were matched."""
zh: """没有匹配到任何鉴权规则的次数。"""
}
label: {
en: """The Number of Times that no Authorization Rules were Matched"""
zh: """没有匹配到任何鉴权规则的次数"""
} }
} }
allow { allow {
desc { desc {
en: """Authorize allow.""" en: """The number of times the authentication was successful."""
zh: """鉴权成功。""" zh: """鉴权成功的次数。"""
} }
label: { label: {
en: """Authorize Allow""" en: """The Number of Times the Authentication was Successful"""
zh: """鉴权成功""" zh: """鉴权成功次数"""
} }
} }
deny { deny {
desc { desc {
en: """Authorize Deny.""" en: """The number of authentication failures."""
zh: """鉴权失败""" zh: """鉴权失败的次数。"""
} }
label: { label: {
en: """Authorize Deny""" en: """The Number of Authentication Failures"""
zh: """鉴权失败""" zh: """鉴权失败次数"""
} }
} }
} }

View File

@ -176,8 +176,8 @@ do_post_config_update({?CMD_PREPEND, RawNewSource}, Sources) ->
ok = emqx_metrics_worker:create_metrics( ok = emqx_metrics_worker:create_metrics(
authz_metrics, authz_metrics,
TypeName, TypeName,
[matched, allow, deny, ignore], [total, allow, deny, nomatch],
[matched] [total]
), ),
[InitedNewSource] ++ lookup(); [InitedNewSource] ++ lookup();
do_post_config_update({?CMD_APPEND, RawNewSource}, Sources) -> do_post_config_update({?CMD_APPEND, RawNewSource}, Sources) ->
@ -271,8 +271,8 @@ init_metrics(Source) ->
emqx_metrics_worker:create_metrics( emqx_metrics_worker:create_metrics(
authz_metrics, authz_metrics,
TypeName, TypeName,
[matched, allow, deny, ignore], [total, allow, deny, nomatch],
[matched] [total]
). ).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
@ -354,13 +354,24 @@ do_authorize(
[Connector = #{type := Type} | Tail] [Connector = #{type := Type} | Tail]
) -> ) ->
Module = authz_module(Type), Module = authz_module(Type),
emqx_metrics_worker:inc(authz_metrics, Type, matched), emqx_metrics_worker:inc(authz_metrics, Type, total),
case Module:authorize(Client, PubSub, Topic, Connector) of try Module:authorize(Client, PubSub, Topic, Connector) of
nomatch -> nomatch ->
emqx_metrics_worker:inc(authz_metrics, Type, ignore), emqx_metrics_worker:inc(authz_metrics, Type, nomatch),
do_authorize(Client, PubSub, Topic, Tail); do_authorize(Client, PubSub, Topic, Tail);
Matched -> Matched ->
{Matched, Type} {Matched, Type}
catch
Class:Reason:Stacktrace ->
emqx_metrics_worker:inc(authz_metrics, Type, nomatch),
?SLOG(warning, #{
msg => "unexpected_error_in_authorize",
exception => Class,
reason => Reason,
stacktrace => Stacktrace,
authorize_type => Type
}),
do_authorize(Client, PubSub, Topic, Tail)
end. end.
get_enabled_authzs() -> get_enabled_authzs() ->

View File

@ -398,14 +398,14 @@ make_result_map(ResList) ->
lists:foldl(Fun, {maps:new(), maps:new(), maps:new(), maps:new()}, ResList). lists:foldl(Fun, {maps:new(), maps:new(), maps:new(), maps:new()}, ResList).
restructure_map(#{ restructure_map(#{
counters := #{deny := Failed, matched := Match, allow := Succ, ignore := Ignore}, counters := #{deny := Failed, total := Total, allow := Succ, nomatch := Nomatch},
rate := #{matched := #{current := Rate, last5m := Rate5m, max := RateMax}} rate := #{total := #{current := Rate, last5m := Rate5m, max := RateMax}}
}) -> }) ->
#{ #{
matched => Match, total => Total,
allow => Succ, allow => Succ,
deny => Failed, deny => Failed,
ignore => Ignore, nomatch => Nomatch,
rate => Rate, rate => Rate,
rate_last5m => Rate5m, rate_last5m => Rate5m,
rate_max => RateMax rate_max => RateMax
@ -592,10 +592,10 @@ status_metrics_example() ->
} }
], ],
metrics => #{ metrics => #{
matched => 0, total => 0,
allow => 0, allow => 0,
deny => 0, deny => 0,
ignore => 0, nomatch => 0,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.0 rate_max => 0.0
@ -604,10 +604,10 @@ status_metrics_example() ->
#{ #{
node => node(), node => node(),
metrics => #{ metrics => #{
matched => 0, total => 0,
allow => 0, allow => 0,
deny => 0, deny => 0,
ignore => 0, nomatch => 0,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.0 rate_max => 0.0

View File

@ -166,10 +166,10 @@ fields("metrics_status_fields") ->
]; ];
fields("metrics") -> fields("metrics") ->
[ [
{"matched", mk(integer(), #{desc => ?DESC("matched")})}, {"total", mk(integer(), #{desc => ?DESC("metrics_total")})},
{"allow", mk(integer(), #{desc => ?DESC("allow")})}, {"allow", mk(integer(), #{desc => ?DESC("allow")})},
{"deny", mk(integer(), #{desc => ?DESC("deny")})}, {"deny", mk(integer(), #{desc => ?DESC("deny")})},
{"ignore", mk(float(), #{desc => ?DESC("ignore")})} {"nomatch", mk(float(), #{desc => ?DESC("nomatch")})}
] ++ common_rate_field(); ] ++ common_rate_field();
fields("node_metrics") -> fields("node_metrics") ->
[ [

View File

@ -243,8 +243,8 @@ t_api(_) ->
<<"metrics">> := #{ <<"metrics">> := #{
<<"allow">> := 0, <<"allow">> := 0,
<<"deny">> := 0, <<"deny">> := 0,
<<"matched">> := 0, <<"total">> := 0,
<<"ignore">> := 0 <<"nomatch">> := 0
} }
} = jiffy:decode(Status4, [return_maps]), } = jiffy:decode(Status4, [return_maps]),
?assertMatch( ?assertMatch(
@ -298,8 +298,8 @@ t_api(_) ->
<<"metrics">> := #{ <<"metrics">> := #{
<<"allow">> := 0, <<"allow">> := 0,
<<"deny">> := 0, <<"deny">> := 0,
<<"matched">> := 0, <<"total">> := 0,
<<"ignore">> := 0 <<"nomatch">> := 0
} }
} = jiffy:decode(Status5_1, [return_maps]), } = jiffy:decode(Status5_1, [return_maps]),
@ -377,8 +377,8 @@ t_api(_) ->
<<"metrics">> := #{ <<"metrics">> := #{
<<"allow">> := 1, <<"allow">> := 1,
<<"deny">> := 0, <<"deny">> := 0,
<<"matched">> := 1, <<"total">> := 1,
<<"ignore">> := 0 <<"nomatch">> := 0
} }
} = jiffy:decode(Status5, [return_maps]), } = jiffy:decode(Status5, [return_maps]),
@ -396,8 +396,8 @@ t_api(_) ->
<<"metrics">> := #{ <<"metrics">> := #{
<<"allow">> := 2, <<"allow">> := 2,
<<"deny">> := 0, <<"deny">> := 0,
<<"matched">> := 2, <<"total">> := 2,
<<"ignore">> := 0 <<"nomatch">> := 0
} }
} = jiffy:decode(Status6, [return_maps]), } = jiffy:decode(Status6, [return_maps]),
@ -416,8 +416,8 @@ t_api(_) ->
<<"metrics">> := #{ <<"metrics">> := #{
<<"allow">> := 3, <<"allow">> := 3,
<<"deny">> := 0, <<"deny">> := 0,
<<"matched">> := 3, <<"total">> := 3,
<<"ignore">> := 0 <<"nomatch">> := 0
} }
} = jiffy:decode(Status7, [return_maps]), } = jiffy:decode(Status7, [return_maps]),
@ -508,7 +508,7 @@ t_aggregate_metrics(_) ->
metrics => metrics =>
#{ #{
failed => 0, failed => 0,
matched => 1, total => 1,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.1, rate_max => 0.1,
@ -519,7 +519,7 @@ t_aggregate_metrics(_) ->
metrics => metrics =>
#{ #{
failed => 0, failed => 0,
matched => 1, total => 1,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.1, rate_max => 0.1,
@ -533,7 +533,7 @@ t_aggregate_metrics(_) ->
metrics => metrics =>
#{ #{
failed => 0, failed => 0,
matched => 2, total => 2,
rate => 0.0, rate => 0.0,
rate_last5m => 0.0, rate_last5m => 0.0,
rate_max => 0.2, rate_max => 0.2,