From 8c1c87a8d6b810548184bcc4d39759483a6abb5d Mon Sep 17 00:00:00 2001 From: DDDHuang <44492639+DDDHuang@users.noreply.github.com> Date: Thu, 24 Feb 2022 14:39:30 +0800 Subject: [PATCH] fix(test): add monitor SUITE, TODO: API Test SUITE --- .../emqx_dashboard/include/emqx_dashboard.hrl | 7 +- .../src/emqx_dashboard_monitor.erl | 34 ++--- .../src/emqx_dashboard_monitor_api.erl | 15 +- .../test/emqx_dashboard_monitor_SUITE.erl | 130 ++++++++++++++++++ .../test/emqx_dashboard_monitor_api_SUITE.erl | 40 ------ 5 files changed, 148 insertions(+), 78 deletions(-) create mode 100644 apps/emqx_dashboard/test/emqx_dashboard_monitor_SUITE.erl delete mode 100644 apps/emqx_dashboard/test/emqx_dashboard_monitor_api_SUITE.erl diff --git a/apps/emqx_dashboard/include/emqx_dashboard.hrl b/apps/emqx_dashboard/include/emqx_dashboard.hrl index 8deae8187..a32affef0 100644 --- a/apps/emqx_dashboard/include/emqx_dashboard.hrl +++ b/apps/emqx_dashboard/include/emqx_dashboard.hrl @@ -39,8 +39,13 @@ -define(DASHBOARD_SHARD, emqx_dashboard_shard). -%% 10 seconds +-ifdef(TEST). +%% for test, 2s +-define(DEFAULT_SAMPLE_INTERVAL, 1). +-else. +%% dashboard monitor do sample interval, default 10s -define(DEFAULT_SAMPLE_INTERVAL, 10). +-endif. -define(DELTA_SAMPLER_LIST, [ received diff --git a/apps/emqx_dashboard/src/emqx_dashboard_monitor.erl b/apps/emqx_dashboard/src/emqx_dashboard_monitor.erl index 99c636fe1..40008f23e 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_monitor.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_monitor.erl @@ -40,26 +40,14 @@ ]). %% for rpc --export([ do_samples/1]). +-export([ do_sample/1]). -define(TAB, ?MODULE). --ifdef(TEST). -%% for test --define(CLEAN_EXPIRED_INTERVAL, 2 * 1000). --define(RETENTION_TIME, 3 * 1000). --define(DEFAULT_GET_DATA_TIME, 5* 1000). - --else. - %% 1 hour = 60 * 60 * 1000 milliseconds -define(CLEAN_EXPIRED_INTERVAL, 60 * 60 * 1000). %% 7 days = 7 * 24 * 60 * 60 * 1000 milliseconds -define(RETENTION_TIME, 7 * 24 * 60 * 60 * 1000). -%% 1 day = 60 * 60 * 1000 milliseconds --define(DEFAULT_GET_DATA_TIME, 60 * 60 * 1000). - --endif. -record(state, { last @@ -82,7 +70,7 @@ samplers() -> samplers(all). samplers(NodeOrCluster) -> - format(do_samples(NodeOrCluster)). + format(do_sample(NodeOrCluster)). samplers(NodeOrCluster, 0) -> samplers(NodeOrCluster); @@ -141,10 +129,10 @@ code_change(_OldVsn, State = #state{}, _Extra) -> %%% Internal functions %%%=================================================================== -do_samples(all) -> +do_sample(all) -> Fun = fun(Node, All) -> - case do_samples(Node) of + case do_sample(Node) of {badrpc, Reason} -> {badrpc, {Node, Reason}}; NodeSamplers -> @@ -152,9 +140,10 @@ do_samples(all) -> end end, lists:foldl(Fun, #{}, mria_mnesia:cluster_nodes(running)); -do_samples(Node) when Node == node() -> - get_data(?DEFAULT_GET_DATA_TIME); -do_samples(Node) -> +do_sample(Node) when Node == node() -> + ExpiredMS = [{'$1',[],['$1']}], + internal_format(ets:select(?TAB, ExpiredMS)); +do_sample(Node) -> rpc:call(Node, ?MODULE, ?FUNCTION_NAME, [Node], 5000). merge_cluster_samplers(Node, Cluster) -> @@ -191,7 +180,7 @@ clean_timer() -> %% The monitor will start working at full seconds, as like 00:00:00, 00:00:10, 00:00:20 ... %% Ensure that the monitor data of all nodes in the cluster are aligned in time next_interval() -> - Interval = emqx_conf:get([dashboard, monitor, interval], ?DEFAULT_SAMPLE_INTERVAL) * 1000, + Interval = emqx_conf:get([dashboard, sample_interval], ?DEFAULT_SAMPLE_INTERVAL) * 1000, Now = erlang:system_time(millisecond), NextTime = ((Now div Interval) + 1) * Interval, Remaining = NextTime - Now, @@ -232,11 +221,6 @@ clean() -> end, Expired), ok. -get_data(PastTime) -> - Now = erlang:system_time(millisecond), - ExpiredMS = [{{'_', '$1', '_'}, [{'<', {'-', Now, '$1'}, PastTime}], ['$_']}], - internal_format(ets:select(?TAB, ExpiredMS)). - %% To make it easier to do data aggregation internal_format(List) when is_list(List) -> Fun = diff --git a/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl index d3cf5523c..65fb3a153 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl @@ -18,15 +18,6 @@ -export([ monitor/2]). --define(SAMPLERS, - [ connection - , route - , subscriptions - , received - , sent - , dropped - ]). - api_spec() -> emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true, translate_body => true}). @@ -41,7 +32,7 @@ schema("/monitor") -> get => #{ description => <<"List monitor data.">>, parameters => [ - {latest, hoconsc:mk(integer(), #{in => query, required => false, example => 1000})} + {latest, hoconsc:mk(integer(), #{in => query, nullable => true, example => 1000})} ], responses => #{ 200 => hoconsc:mk(hoconsc:array(hoconsc:ref(sampler)), #{}), @@ -56,8 +47,8 @@ schema("/monitor/nodes/:node") -> get => #{ description => <<"List the monitor data on the node.">>, parameters => [ - {node, hoconsc:mk(binary(), #{in => path, required => true, example => node()})}, - {latest, hoconsc:mk(integer(), #{in => query, required => false, example => 1000})} + {node, hoconsc:mk(binary(), #{in => path, nullable => false, example => node()})}, + {latest, hoconsc:mk(integer(), #{in => query, nullable => true, example => 1000})} ], responses => #{ 200 => hoconsc:mk(hoconsc:array(hoconsc:ref(sampler)), #{}), diff --git a/apps/emqx_dashboard/test/emqx_dashboard_monitor_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_monitor_SUITE.erl new file mode 100644 index 000000000..43d8d0712 --- /dev/null +++ b/apps/emqx_dashboard/test/emqx_dashboard_monitor_SUITE.erl @@ -0,0 +1,130 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020-2022 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_dashboard_monitor_SUITE). + +-compile(nowarn_export_all). +-compile(export_all). + +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include_lib("emqx/include/emqx.hrl"). +-include("emqx_dashboard.hrl"). + +-define(SERVER, "http://127.0.0.1:18083"). +-define(BASE_PATH, "/api/v5"). + +all() -> + emqx_common_test_helpers:all(?MODULE). + +init_per_suite(Config) -> + mria:start(), + emqx_common_test_helpers:start_apps([emqx_dashboard], fun set_special_configs/1), + Config. + +end_per_suite(Config) -> + emqx_common_test_helpers:stop_apps([emqx_dashboard]), + Config. + +set_special_configs(emqx_dashboard) -> + Config = #{ + default_username => <<"admin">>, + default_password => <<"public">>, + listeners => [#{ + protocol => http, + port => 18083 + }] + }, + emqx_config:put([dashboard], Config), + ok; +set_special_configs(_) -> + ok. + +t_monitor_samplers_all(_Config) -> + timer:sleep(?DEFAULT_SAMPLE_INTERVAL * 2 * 1000 + 20), + Size = mnesia:table_info(emqx_dashboard_monitor,size), + All = emqx_dashboard_monitor:samplers(all), + All2 = emqx_dashboard_monitor:samplers(), + ?assert(erlang:length(All) == Size), + ?assert(erlang:length(All2) == Size), + ok. + +t_monitor_samplers_latest(_Config) -> + timer:sleep(?DEFAULT_SAMPLE_INTERVAL * 2 * 1000 + 20), + Samplers = emqx_dashboard_monitor:samplers(node(), 2), + Latest = emqx_dashboard_monitor:samplers(node(), 1), + ?assert(erlang:length(Samplers) == 2), + ?assert(erlang:length(Latest) == 1), + ?assert(hd(Latest) == lists:nth(2, Samplers)), + ok. + +t_monitor_sampler_format(_Config) -> + timer:sleep(?DEFAULT_SAMPLE_INTERVAL * 2 * 1000 + 20), + Latest = hd(emqx_dashboard_monitor:samplers(node(), 1)), + SamplerKeys = maps:keys(Latest), + [?assert(lists:member(SamplerName, SamplerKeys)) || SamplerName <- ?SAMPLER_LIST], + ok. + +%% TODO: api test +% t_monitor_api(_) -> +% timer:sleep(?DEFAULT_SAMPLE_INTERVAL * 2 * 1000 + 20), +% {ok, Samplers} = request(["monitor"]), +% ?assert(erlang:length(Samplers) >= 2), +% Sample = hd(Samplers), +% Fun = +% fun(Sampler) -> +% Keys = [binary_to_atom(Key, utf8) || Key <- maps:keys(Sampler)], +% [?assert(lists:member(SamplerName, Keys)) || SamplerName<- ?SAMPLER_LIST] +% end, +% [Fun(Sampler) || Sampler <- Samplers], +% ok. + +% t_monitor_api_error(_) -> +% {error, _Reason} = request(["monitor_a"]), +% ok. + +% request(Path) -> +% request(Path, ""). + +% request(Path, QS) -> +% Url = url(Path, QS), +% case do_request_api(get, {Path, auth_header_()}) of +% {ok, Apps} -> {ok, emqx_json:decode(Apps, [return_maps])}; +% Error -> Error +% end. + +% url(Parts, QS)-> +% case QS of +% "" -> +% ?SERVER ++ filename:join([?BASE_PATH | Parts]); +% _ -> +% ?SERVER ++ filename:join([?BASE_PATH | Parts]) ++ "?" ++ QS +% end. + +% do_request_api(Method, Request)-> +% case httpc:request(Method, Request, [], []) of +% {error, socket_closed_remotely} -> +% {error, socket_closed_remotely}; +% {ok, {{"HTTP/1.1", Code, _}, _, Return} } +% when Code >= 200 andalso Code =< 299 -> +% {ok, emqx_json:decode(Return)}; +% {ok, Resp} -> +% {error, Resp} +% end. + +% auth_header_() -> +% Basic = binary_to_list(base64:encode(<<"admin:public">>)), +% {"Authorization", "Basic " ++ Basic}. diff --git a/apps/emqx_dashboard/test/emqx_dashboard_monitor_api_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_monitor_api_SUITE.erl deleted file mode 100644 index aae7a4b69..000000000 --- a/apps/emqx_dashboard/test/emqx_dashboard_monitor_api_SUITE.erl +++ /dev/null @@ -1,40 +0,0 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2020-2022 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_dashboard_monitor_api_SUITE). - --compile(nowarn_export_all). --compile(export_all). - --include_lib("eunit/include/eunit.hrl"). --include_lib("common_test/include/ct.hrl"). --include_lib("emqx/include/emqx.hrl"). --include("emqx_dashboard.hrl"). - -all() -> - emqx_common_test_helpers:all(?MODULE). - -init_per_testcase(_, Config) -> - Config. - -end_per_testcase(_, _Config) -> - ok. - - -%%------------------------------------------------------------------------------ -%% Internal functions -%%------------------------------------------------------------------------------ -