Range, samples and avg tests. Fixed JSON output tags.
This commit is contained in:
parent
619211f792
commit
8ba208f05d
|
|
@ -614,8 +614,8 @@ format_rate(Type, {TP}, {RP}, {SP}, {STP}, Length)
|
|||
when Type =:= queue_stats_publish;
|
||||
Type =:= queue_exchange_stats_publish ->
|
||||
[
|
||||
{publish_out, TP},
|
||||
{publish_out_details, [{rate, RP},
|
||||
{publish, TP},
|
||||
{publish_details, [{rate, RP},
|
||||
{samples, SP}] ++ average(SP, STP, Length)}
|
||||
];
|
||||
format_rate(Type, {TR, TU, TM}, {RR, RU, RM}, {SR, SU, SM}, {STR, STU, STM},
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
-include_lib("proper/include/proper.hrl").
|
||||
-include("rabbit_mgmt_metrics.hrl").
|
||||
-include("rabbit_mgmt.hrl").
|
||||
|
||||
-compile(export_all).
|
||||
|
||||
|
|
@ -25,14 +26,26 @@ all() ->
|
|||
|
||||
groups() ->
|
||||
[
|
||||
{parallel_tests, [], [
|
||||
format_rate_no_range_test,
|
||||
format_zero_rate_no_range_test,
|
||||
format_incremental_rate_no_range_test,
|
||||
format_incremental_zero_rate_no_range_test,
|
||||
format_total_no_range_test,
|
||||
format_incremental_total_no_range_test
|
||||
]}
|
||||
{parallel_tests, [parallel], [
|
||||
format_rate_no_range_test,
|
||||
format_zero_rate_no_range_test,
|
||||
format_incremental_rate_no_range_test,
|
||||
format_incremental_zero_rate_no_range_test,
|
||||
format_total_no_range_test,
|
||||
format_incremental_total_no_range_test,
|
||||
format_rate_range_test,
|
||||
format_zero_rate_range_test,
|
||||
format_incremental_rate_range_test,
|
||||
format_incremental_zero_rate_range_test,
|
||||
format_total_range_test,
|
||||
format_incremental_total_range_test,
|
||||
format_samples_range_test,
|
||||
format_incremental_samples_range_test,
|
||||
format_avg_rate_range_test,
|
||||
format_incremental_avg_rate_range_test,
|
||||
format_avg_range_test,
|
||||
format_incremental_avg_range_test
|
||||
]}
|
||||
].
|
||||
|
||||
%% -------------------------------------------------------------------
|
||||
|
|
@ -122,30 +135,21 @@ format_rate_no_range_test(Config) ->
|
|||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_rate_no_range, []).
|
||||
|
||||
format_rate_no_range() ->
|
||||
rabbit_ct_proper_helpers:run_proper(fun prop_rate_format_no_range/0, [], 100).
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, rate_check(fun(Rate) -> Rate > 0 end),
|
||||
false, fun no_range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
prop_rate_format_no_range() ->
|
||||
prop_format_no_range(large, rate_check(fun(Rate) -> Rate > 0 end), false).
|
||||
|
||||
rate_check(RateCheck) ->
|
||||
fun(Results, _, Table) ->
|
||||
Check =
|
||||
fun(Detail) ->
|
||||
Rate = proplists:get_value(rate, proplists:get_value(Detail, Results), 0),
|
||||
RateCheck(Rate)
|
||||
end,
|
||||
lists:all(Check, details(Table))
|
||||
end.
|
||||
|
||||
prop_format_no_range(SampleSize, Check, Incremental) ->
|
||||
prop_format(Id, SampleSize, Check, Incremental, RangeFun) ->
|
||||
?FORALL(
|
||||
{{Table, Data}, Interval}, {content_gen(SampleSize), interval_gen()},
|
||||
begin
|
||||
{Slide, Total} = create_slide(Data, Interval, Incremental),
|
||||
Id = sample_one,
|
||||
{Slide, Total, Samples} = create_slide(Data, Interval, Incremental),
|
||||
Range = RangeFun(Interval),
|
||||
ets:insert(Table, {{Id, 5}, Slide}),
|
||||
Results = rabbit_mgmt_stats:format(no_range, Table, Id, 5000),
|
||||
Check(Results, Total, Table)
|
||||
Results = rabbit_mgmt_stats:format(Range, Table, Id, 5000),
|
||||
Check(Results, Total, Samples, Table)
|
||||
end).
|
||||
|
||||
%% Rates for 1 or no samples will always be 0.0 as there aren't
|
||||
|
|
@ -154,20 +158,22 @@ format_zero_rate_no_range_test(Config) ->
|
|||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_zero_rate_no_range, []).
|
||||
|
||||
format_zero_rate_no_range() ->
|
||||
rabbit_ct_proper_helpers:run_proper(fun prop_zero_rate_format_no_range/0, [], 100).
|
||||
|
||||
prop_zero_rate_format_no_range() ->
|
||||
prop_format_no_range(small, rate_check(fun(Rate) -> Rate == 0.0 end), false).
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, small, rate_check(fun(Rate) -> Rate == 0.0 end),
|
||||
false, fun no_range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
%% Rates for 3 or more monotonically increasing incremental samples will always be > 0
|
||||
format_incremental_rate_no_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_incremental_rate_no_range, []).
|
||||
|
||||
format_incremental_rate_no_range() ->
|
||||
rabbit_ct_proper_helpers:run_proper(fun prop_incremental_rate_format_no_range/0, [], 100).
|
||||
|
||||
prop_incremental_rate_format_no_range() ->
|
||||
prop_format_no_range(large, rate_check(fun(Rate) -> Rate > 0 end), true).
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, rate_check(fun(Rate) -> Rate > 0 end),
|
||||
true, fun no_range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
%% Rates for 1 or no samples will always be 0.0 as there aren't
|
||||
%% enough datapoints to calculate the instant rate
|
||||
|
|
@ -175,39 +181,151 @@ format_incremental_zero_rate_no_range_test(Config) ->
|
|||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_incremental_zero_rate_no_range, []).
|
||||
|
||||
format_incremental_zero_rate_no_range() ->
|
||||
rabbit_ct_proper_helpers:run_proper(fun prop_incremental_zero_rate_format_no_range/0, [], 100).
|
||||
|
||||
prop_incremental_zero_rate_format_no_range() ->
|
||||
prop_format_no_range(small, rate_check(fun(Rate) -> Rate == 0.0 end), true).
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, small, rate_check(fun(Rate) -> Rate == 0.0 end),
|
||||
true, fun no_range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
%% Checking totals
|
||||
format_total_no_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_total_no_range, []).
|
||||
|
||||
format_total_no_range() ->
|
||||
rabbit_ct_proper_helpers:run_proper(fun prop_total_format_no_range/0, [], 100).
|
||||
|
||||
prop_total_format_no_range() ->
|
||||
prop_format_no_range(large, fun check_total/3, false).
|
||||
|
||||
check_total(Results, Totals, Table) ->
|
||||
Expected = lists:zip(?stats_per_table(Table), tuple_to_list(Totals)),
|
||||
lists:all(fun({K, _} = E) ->
|
||||
case is_average_time(K) of
|
||||
false -> lists:member(E, Results);
|
||||
true -> lists:keymember(K, 1, Results)
|
||||
end
|
||||
end, Expected).
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_total/4, false, fun no_range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
format_incremental_total_no_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_incremental_total_no_range, []).
|
||||
|
||||
format_incremental_total_no_range() ->
|
||||
rabbit_ct_proper_helpers:run_proper(fun prop_incremental_total_format_no_range/0, [], 100).
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_total/4, true, fun no_range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
prop_incremental_total_format_no_range() ->
|
||||
prop_format_no_range(large, fun check_total/3, true).
|
||||
%%---------------------
|
||||
%% Requests using range
|
||||
%%---------------------
|
||||
format_rate_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_rate_range, []).
|
||||
|
||||
format_rate_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, rate_check(fun(Rate) -> Rate > 0 end),
|
||||
false, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
%% Rates for 1 or no samples will always be 0.0 as there aren't
|
||||
%% enough datapoints to calculate the instant rate
|
||||
format_zero_rate_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_zero_rate_range, []).
|
||||
|
||||
format_zero_rate_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, small, rate_check(fun(Rate) -> Rate == 0.0 end),
|
||||
false, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
%% Rates for 3 or more monotonically increasing incremental samples will always be > 0
|
||||
format_incremental_rate_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_incremental_rate_range, []).
|
||||
|
||||
format_incremental_rate_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, rate_check(fun(Rate) -> Rate > 0 end),
|
||||
true, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
%% Rates for 1 or no samples will always be 0.0 as there aren't
|
||||
%% enough datapoints to calculate the instant rate
|
||||
format_incremental_zero_rate_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_incremental_zero_rate_range, []).
|
||||
|
||||
format_incremental_zero_rate_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, small, rate_check(fun(Rate) -> Rate == 0.0 end),
|
||||
true, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
%% Checking totals
|
||||
format_total_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_total_range, []).
|
||||
|
||||
format_total_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_total/4, false, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
format_incremental_total_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_incremental_total_range, []).
|
||||
|
||||
format_incremental_total_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_total/4, true, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
format_samples_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_samples_range, []).
|
||||
|
||||
format_samples_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_samples/4, false, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
format_incremental_samples_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_incremental_samples_range, []).
|
||||
|
||||
format_incremental_samples_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_samples/4, true, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
format_avg_rate_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_avg_rate_range, []).
|
||||
|
||||
format_avg_rate_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_avg_rate/4, false, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
format_incremental_avg_rate_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_incremental_avg_rate_range, []).
|
||||
|
||||
format_incremental_avg_rate_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_avg_rate/4, true, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
format_avg_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_avg_range, []).
|
||||
|
||||
format_avg_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_avg/4, false, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
|
||||
format_incremental_avg_range_test(Config) ->
|
||||
true == rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, format_incremental_avg_range, []).
|
||||
|
||||
format_incremental_avg_range() ->
|
||||
Fun = fun() ->
|
||||
prop_format(?FUNCTION_NAME, large, fun check_avg/4, true, fun range/1)
|
||||
end,
|
||||
rabbit_ct_proper_helpers:run_proper(Fun, [], 100).
|
||||
%% -------------------------------------------------------------------
|
||||
%% Helpers
|
||||
%% -------------------------------------------------------------------
|
||||
|
|
@ -223,7 +341,7 @@ create_slide(Data, Interval, Incremental) ->
|
|||
%% Use the samples as increments for data generation, so we have always increasing counters
|
||||
Slide = exometer_slide:new(60 * 1000, [{interval, Interval}, {incremental, Incremental}]),
|
||||
Sleep = min_wait(Interval, Data),
|
||||
lists:foldl(fun(E, {Acc, Total}) ->
|
||||
lists:foldl(fun(E, {Acc, Total, Samples}) ->
|
||||
timer:sleep(Sleep),
|
||||
NewTotal = add(E, Total),
|
||||
Sample = case Incremental of
|
||||
|
|
@ -233,8 +351,8 @@ create_slide(Data, Interval, Incremental) ->
|
|||
true ->
|
||||
E
|
||||
end,
|
||||
{exometer_slide:add_element(Sample, Acc), NewTotal}
|
||||
end, {Slide, undefined}, Data).
|
||||
{exometer_slide:add_element(Sample, Acc), NewTotal, [NewTotal | Samples]}
|
||||
end, {Slide, undefined, []}, Data).
|
||||
|
||||
min_wait(_, []) ->
|
||||
0;
|
||||
|
|
@ -256,3 +374,83 @@ is_average_time(Atom) ->
|
|||
_ ->
|
||||
true
|
||||
end.
|
||||
|
||||
rate_check(RateCheck) ->
|
||||
fun(Results, _, _, Table) ->
|
||||
Check =
|
||||
fun(Detail) ->
|
||||
Rate = proplists:get_value(rate, proplists:get_value(Detail, Results), 0),
|
||||
RateCheck(Rate)
|
||||
end,
|
||||
lists:all(Check, details(Table))
|
||||
end.
|
||||
|
||||
check_total(Results, Totals, _Samples, Table) ->
|
||||
Expected = lists:zip(?stats_per_table(Table), tuple_to_list(Totals)),
|
||||
lists:all(fun({K, _} = E) ->
|
||||
case is_average_time(K) of
|
||||
false -> lists:member(E, Results);
|
||||
true -> lists:keymember(K, 1, Results)
|
||||
end
|
||||
end, Expected).
|
||||
|
||||
check_samples(Results, _Totals, Samples, Table) ->
|
||||
Details = details(Table),
|
||||
%% Lookup list for the position of the key in the stats tuple
|
||||
Pairs = lists:zip(Details, lists:seq(1, length(Details))),
|
||||
|
||||
%% Check that all samples in the results match one of the samples in the inputs
|
||||
lists:all(fun(Detail) ->
|
||||
RSamples = get_from_detail(samples, Detail, Results),
|
||||
lists:all(fun(RS) ->
|
||||
Value = proplists:get_value(sample, RS),
|
||||
case Value of
|
||||
0 ->
|
||||
true;
|
||||
_ ->
|
||||
lists:keymember(Value,
|
||||
proplists:get_value(Detail, Pairs),
|
||||
Samples)
|
||||
end
|
||||
end, RSamples)
|
||||
end, Details)
|
||||
%% ensure that not all samples are 0
|
||||
andalso lists:all(fun(Detail) ->
|
||||
RSamples = get_from_detail(samples, Detail, Results),
|
||||
lists:any(fun(RS) ->
|
||||
0 =/= proplists:get_value(sample, RS)
|
||||
end, RSamples)
|
||||
end, Details).
|
||||
|
||||
check_avg_rate(Results, _Totals, _Samples, Table) ->
|
||||
Details = details(Table),
|
||||
|
||||
lists:all(fun(Detail) ->
|
||||
AvgRate = get_from_detail(avg_rate, Detail, Results),
|
||||
Samples = get_from_detail(samples, Detail, Results),
|
||||
S2 = proplists:get_value(sample, hd(Samples)),
|
||||
T2 = proplists:get_value(timestamp, hd(Samples)),
|
||||
S1 = proplists:get_value(sample, lists:last(Samples)),
|
||||
T1 = proplists:get_value(timestamp, lists:last(Samples)),
|
||||
AvgRate == ((S2 - S1) * 1000 / (T2 - T1))
|
||||
end, Details).
|
||||
|
||||
check_avg(Results, _Totals, _Samples, Table) ->
|
||||
Details = details(Table),
|
||||
|
||||
lists:all(fun(Detail) ->
|
||||
Avg = get_from_detail(avg, Detail, Results),
|
||||
Samples = get_from_detail(samples, Detail, Results),
|
||||
Sum = lists:sum([proplists:get_value(sample, S) || S <- Samples]),
|
||||
Avg == (Sum / length(Samples))
|
||||
end, Details).
|
||||
|
||||
get_from_detail(Tag, Detail, Results) ->
|
||||
proplists:get_value(Tag, proplists:get_value(Detail, Results), []).
|
||||
|
||||
range(Interval) ->
|
||||
Now = exometer_slide:timestamp(),
|
||||
#range{first = Now - 500, last = Now, incr = Interval}.
|
||||
|
||||
no_range(_Interval) ->
|
||||
no_range.
|
||||
|
|
|
|||
Loading…
Reference in New Issue