Merge pull request #7966 from zmstone/0516-ignore-bad-metrix-value

fix(emqx_map_lib): ignore non-number non-map values
This commit is contained in:
Zaiming (Stone) Shi 2022-05-17 07:33:15 +01:00 committed by GitHub
commit d1ffba7ff4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 9 deletions

View File

@ -269,17 +269,50 @@ error_type_two_maps(M1, _M2) ->
%% @doc Sum-merge map values.
%% For bad merges, ErrorLogger is called to log the key, and value in M2 is ignored.
best_effort_recursive_sum(M1, M2, ErrorLogger) ->
best_effort_recursive_sum(M10, M20, ErrorLogger) ->
FilterF = fun(K, V) ->
case erlang:is_number(V) of
true ->
true;
false ->
ErrorLogger(#{failed_to_merge => K, bad_value => V}),
false
end
end,
M1 = deep_filter(M10, FilterF),
M2 = deep_filter(M20, FilterF),
do_best_effort_recursive_sum(M1, M2, ErrorLogger).
do_best_effort_recursive_sum(M1, M2, ErrorLogger) ->
F =
fun(Key, V1, V2) ->
case {erlang:is_map(V1), erlang:is_map(V2)} of
{true, true} ->
best_effort_recursive_sum(V1, V2, ErrorLogger);
{false, false} when is_number(V1) andalso is_number(V2) ->
V1 + V2;
_ ->
ErrorLogger(#{failed_to_merge => Key}),
V1
do_best_effort_recursive_sum(V1, V2, ErrorLogger);
{true, false} ->
ErrorLogger(#{failed_to_merge => Key, bad_value => V2}),
do_best_effort_recursive_sum(V1, #{}, ErrorLogger);
{false, true} ->
ErrorLogger(#{failed_to_merge => Key, bad_value => V1}),
do_best_effort_recursive_sum(V2, #{}, ErrorLogger);
{false, false} ->
true = is_number(V1),
true = is_number(V2),
V1 + V2
end
end,
merge_with(F, M1, M2).
deep_filter(M, F) when is_map(M) ->
%% maps:filtermap is not available before OTP 24
maps:from_list(
lists:filtermap(
fun
({K, V}) when is_map(V) ->
{true, {K, deep_filter(V, F)}};
({K, V}) ->
F(K, V) andalso {true, {K, V}}
end,
maps:to_list(M)
)
).

View File

@ -49,8 +49,62 @@ best_effort_recursive_sum_test_() ->
),
receive
{log, Log} ->
?assertEqual(#{failed_to_merge => bar}, Log)
?assertEqual(#{failed_to_merge => bar, bad_value => bar}, Log)
after 1000 -> error(timeout)
end
end
end,
?_assertEqual(
#{},
emqx_map_lib:best_effort_recursive_sum(
#{foo => foo}, #{foo => bar}, DummyLogger
)
),
?_assertEqual(
#{foo => 1},
emqx_map_lib:best_effort_recursive_sum(
#{foo => 1}, #{foo => bar}, DummyLogger
)
),
?_assertEqual(
#{foo => 1},
emqx_map_lib:best_effort_recursive_sum(
#{foo => bar}, #{foo => 1}, DummyLogger
)
),
?_assertEqual(
#{foo => #{bar => 1}},
emqx_map_lib:best_effort_recursive_sum(
#{foo => #{bar => 1}}, #{foo => 1}, DummyLogger
)
),
?_assertEqual(
#{foo => #{bar => 1}},
emqx_map_lib:best_effort_recursive_sum(
#{foo => 1}, #{foo => #{bar => 1}}, DummyLogger
)
),
?_assertEqual(
#{foo => #{bar => 1}},
emqx_map_lib:best_effort_recursive_sum(
#{foo => 1, bar => ignored}, #{foo => #{bar => 1}}, DummyLogger
)
),
?_assertEqual(
#{foo => #{bar => 2}, bar => #{foo => 1}},
emqx_map_lib:best_effort_recursive_sum(
#{foo => 1, bar => #{foo => 1}}, #{foo => #{bar => 2}, bar => 2}, DummyLogger
)
),
?_assertEqual(
#{foo => #{bar => 2}, bar => #{foo => 1}},
emqx_map_lib:best_effort_recursive_sum(
#{foo => #{bar => 2}, bar => 2}, #{foo => 1, bar => #{foo => 1}}, DummyLogger
)
),
?_assertEqual(
#{foo => #{bar => #{}}},
emqx_map_lib:best_effort_recursive_sum(
#{foo => #{bar => #{foo => []}}}, #{foo => 1}, DummyLogger
)
)
].