fix(test): add monitor SUITE, TODO: API Test SUITE

This commit is contained in:
DDDHuang 2022-02-24 14:39:30 +08:00
parent fedfa6c653
commit 8c1c87a8d6
5 changed files with 148 additions and 78 deletions

View File

@ -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

View File

@ -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 =

View File

@ -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)), #{}),

View File

@ -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}.

View File

@ -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
%%------------------------------------------------------------------------------