summaryrefslogtreecommitdiff
path: root/deps/rabbitmq_management_agent/test/exometer_slide_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'deps/rabbitmq_management_agent/test/exometer_slide_SUITE.erl')
-rw-r--r--deps/rabbitmq_management_agent/test/exometer_slide_SUITE.erl631
1 files changed, 631 insertions, 0 deletions
diff --git a/deps/rabbitmq_management_agent/test/exometer_slide_SUITE.erl b/deps/rabbitmq_management_agent/test/exometer_slide_SUITE.erl
new file mode 100644
index 0000000000..abdf24853d
--- /dev/null
+++ b/deps/rabbitmq_management_agent/test/exometer_slide_SUITE.erl
@@ -0,0 +1,631 @@
+%% This Source Code Form is subject to the terms of the Mozilla Public
+%% License, v. 2.0. If a copy of the MPL was not distributed with this
+%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
+%%
+%% Copyright (c) 2016-2020 VMware, Inc. or its affiliates. All rights reserved.
+%%
+
+-module(exometer_slide_SUITE).
+
+-include_lib("proper/include/proper.hrl").
+-include_lib("eunit/include/eunit.hrl").
+
+-compile(export_all).
+
+all() ->
+ [
+ {group, parallel_tests}
+ ].
+
+groups() ->
+ [
+ {parallel_tests, [parallel], [
+ incremental_add_element_basics,
+ last_two_normalises_old_sample_timestamp,
+ incremental_last_two_returns_last_two_completed_samples,
+ incremental_sum,
+ incremental_sum_stale,
+ incremental_sum_stale2,
+ incremental_sum_with_drop,
+ incremental_sum_with_total,
+ foldl_realises_partial_sample,
+ foldl_and_to_list,
+ foldl_and_to_list_incremental,
+ optimize,
+ stale_to_list,
+ to_list_single_after_drop,
+ to_list_drop_and_roll,
+ to_list_with_drop,
+ to_list_simple,
+ foldl_with_drop,
+ sum_single,
+ to_normalized_list,
+ to_normalized_list_no_padding,
+ to_list_in_the_past,
+ sum_mgmt_352,
+ sum_mgmt_352_extra,
+ sum_mgmt_352_peak
+ ]}
+ ].
+
+%% -------------------------------------------------------------------
+%% Testsuite setup/teardown.
+%% -------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _Config) ->
+ ok.
+
+init_per_testcase(_, Config) ->
+ Config.
+
+end_per_testcase(_, _Config) ->
+ ok.
+
+%% -------------------------------------------------------------------
+%% Generators.
+%% -------------------------------------------------------------------
+elements_gen() ->
+ ?LET(Length, oneof([1, 2, 3, 7, 8, 20]),
+ ?LET(Elements, list(vector(Length, int())),
+ [erlang:list_to_tuple(E) || E <- Elements])).
+
+%% -------------------------------------------------------------------
+%% Testcases.
+%% -------------------------------------------------------------------
+
+%% TODO: turn tests into properties
+
+incremental_add_element_basics(_Config) ->
+ Now = exometer_slide:timestamp(),
+ S0 = exometer_slide:new(Now, 10, [{incremental, true},
+ {interval, 100}]),
+
+ [] = exometer_slide:to_list(Now, S0),
+ % add element before next interval
+ S1 = exometer_slide:add_element(Now + 10, {1}, S0),
+
+ [] = exometer_slide:to_list(Now + 20, S1),
+
+ %% to_list is not empty, as we take the 'real' total if a full interval has passed
+ Now100 = Now + 100,
+ [{Now100, {1}}] = exometer_slide:to_list(Now100, S1),
+
+ Then = Now + 101,
+ % add element after interval
+ S2 = exometer_slide:add_element(Then, {1}, S1),
+
+ % contains single element with incremented value
+ [{Then, {2}}] = exometer_slide:to_list(Then, S2).
+
+last_two_normalises_old_sample_timestamp(_Config) ->
+ Now = 0,
+ S0 = exometer_slide:new(Now, 10, [{incremental, true},
+ {interval, 100}]),
+
+ S1 = exometer_slide:add_element(100, {1}, S0),
+ S2 = exometer_slide:add_element(500, {1}, S1),
+
+ [{500, {2}}, {400, {1}}] = exometer_slide:last_two(S2).
+
+
+incremental_last_two_returns_last_two_completed_samples(_Config) ->
+ Now = exometer_slide:timestamp(),
+ S0 = exometer_slide:new(Now, 10, [{incremental, true},
+ {interval, 100}]),
+
+ % add two full elements then a partial
+ Now100 = Now + 100,
+ Now200 = Now + 200,
+ S1 = exometer_slide:add_element(Now100, {1}, S0),
+ S2 = exometer_slide:add_element(Now200, {1}, S1),
+ S3 = exometer_slide:add_element(Now + 210, {1}, S2),
+
+ [{Now200, {2}}, {Now100, {1}}] = exometer_slide:last_two(S3).
+
+incremental_sum(_Config) ->
+ Now = exometer_slide:timestamp(),
+ S1 = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {1}, S)
+ end,
+ exometer_slide:new(Now, 1000, [{incremental, true}, {interval, 100}]),
+ lists:seq(100, 1000, 100)),
+ Now50 = Now - 50,
+ S2 = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now50 + Next, {1}, S)
+ end,
+ exometer_slide:new(Now50, 1000, [{incremental, true}, {interval, 100}]),
+ lists:seq(100, 1000, 100)),
+ S3 = exometer_slide:sum([S1, S2]),
+
+ 10 = length(exometer_slide:to_list(Now + 1000, S1)),
+ 10 = length(exometer_slide:to_list(Now + 1000, S2)),
+ 10 = length(exometer_slide:to_list(Now + 1000, S3)).
+
+incremental_sum_stale(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{incremental, true}, {interval, 5}]),
+
+ S1 = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {1}, S)
+ end, Slide, [1, 8, 15, 21, 27]),
+
+ S2 = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {1}, S)
+ end, Slide, [2, 7, 14, 20, 25]),
+ S3 = exometer_slide:sum([S1, S2]),
+ [27,22,17,12,7] = lists:reverse([T || {T, _} <- exometer_slide:to_list(27, S3)]),
+ [10,8,6,4,2] = lists:reverse([V || {_, {V}} <- exometer_slide:to_list(27, S3)]).
+
+incremental_sum_stale2(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{incremental, true},
+ {max_n, 5},
+ {interval, 5}]),
+
+ S1 = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {1}, S)
+ end, Slide, [5]),
+
+ S2 = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {1}, S)
+ end, Slide, [500, 505, 510, 515, 520, 525, 527]),
+ S3 = exometer_slide:sum([S1, S2], {0}),
+ [500, 505, 510, 515, 520, 525] = [T || {T, _} <- exometer_slide:to_list(525, S3)],
+ [7,6,5,4,3,2] = lists:reverse([V || {_, {V}} <- exometer_slide:to_list(525, S3)]).
+
+incremental_sum_with_drop(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{incremental, true},
+ {max_n, 5},
+ {interval, 5}]),
+
+ S1 = lists:foldl(fun ({Next, Incr}, S) ->
+ exometer_slide:add_element(Now + Next, {Incr}, S)
+ end, Slide, [{1, 1}, {8, 0}, {15, 0}, {21, 1}, {27, 0}]),
+
+ S2 = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {1}, S)
+ end, Slide, [2, 7, 14, 20, 25]),
+ S3 = exometer_slide:sum([S1, S2]),
+ [27,22,17,12,7] = lists:reverse([T || {T, _} <- exometer_slide:to_list(27, S3)]),
+ [7,6,4,3,2] = lists:reverse([V || {_, {V}} <- exometer_slide:to_list(27, S3)]).
+
+incremental_sum_with_total(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 50, [{incremental, true}, {interval, 5}]),
+
+ S1 = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {1}, S)
+ end, Slide, [5, 10, 15, 20, 25]),
+
+ S2 = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {1}, S)
+ end, Slide, [7, 12, 17, 22, 23]),
+ S3 = exometer_slide:sum([S1, S2]),
+ {10} = exometer_slide:last(S3),
+ [25,20,15,10,5] = lists:reverse([T || {T, _} <- exometer_slide:to_list(26, S3)]),
+ [ 9, 7, 5, 3,1] = lists:reverse([V || {_, {V}} <- exometer_slide:to_list(26, S3)]).
+
+foldl_realises_partial_sample(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{incremental, true}, {interval, 5}]),
+ S = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {1}, S)
+ end, Slide, [5, 10, 15, 20, 23]),
+ Fun = fun(last, Acc) -> Acc;
+ ({TS, {X}}, Acc) -> [{TS, X} | Acc]
+ end,
+
+ [{25, 5}, {20, 4}, {15, 3}, {10, 2}, {5, 1}] =
+ exometer_slide:foldl(25, 5, Fun, [], S),
+ [{20, 4}, {15, 3}, {10, 2}, {5, 1}] =
+ exometer_slide:foldl(20, 5, Fun, [], S),
+ % do not realise sample unless Now is at least an interval beyond the last
+ % full sample
+ [{20, 4}, {15, 3}, {10, 2}, {5, 1}] =
+ exometer_slide:foldl(23, 5, Fun, [], S).
+
+optimize(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{interval, 5}, {max_n, 5}]),
+ S = lists:foldl(fun (Next, S) ->
+ exometer_slide:add_element(Now + Next, {Next}, S)
+ end, Slide, [5, 10, 15, 20, 25, 30, 35]),
+ OS = exometer_slide:optimize(S),
+ SRes = exometer_slide:to_list(35, S),
+ OSRes = exometer_slide:to_list(35, OS),
+ SRes = OSRes,
+ ?assert(S =/= OS).
+
+to_list_with_drop(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{interval, 5},
+ {incremental, true},
+ {max_n, 5}]),
+ S = exometer_slide:add_element(30, {1}, Slide),
+ S2 = exometer_slide:add_element(35, {1}, S),
+ S3 = exometer_slide:add_element(40, {0}, S2),
+ S4 = exometer_slide:add_element(45, {0}, S3),
+ [{30, {1}}, {35, {2}}, {40, {2}}, {45, {2}}] = exometer_slide:to_list(45, S4).
+
+to_list_simple(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{interval, 5},
+ {incremental, true},
+ {max_n, 5}]),
+ S = exometer_slide:add_element(30, {0}, Slide),
+ S2 = exometer_slide:add_element(35, {0}, S),
+ [{30, {0}}, {35, {0}}] = exometer_slide:to_list(38, S2).
+
+foldl_with_drop(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{interval, 5},
+ {incremental, true},
+ {max_n, 5}]),
+ S = exometer_slide:add_element(30, {1}, Slide),
+ S2 = exometer_slide:add_element(35, {1}, S),
+ S3 = exometer_slide:add_element(40, {0}, S2),
+ S4 = exometer_slide:add_element(45, {0}, S3),
+ Fun = fun(last, Acc) -> Acc;
+ ({TS, {X}}, Acc) -> [{TS, X} | Acc]
+ end,
+ [{45, 2}, {40, 2}, {35, 2}, {30, 1}] =
+ exometer_slide:foldl(45, 30, Fun, [], S4).
+
+foldl_and_to_list(_Config) ->
+ Now = 0,
+ Tests = [ % {input, expected, query range}
+ {[],
+ [],
+ {0, 10}},
+ {[{5, 1}],
+ [{5, {1}}],
+ {0, 5}},
+ {[{10, 1}],
+ [{10, {1}}],
+ {0, 10}},
+ {[{5, 1}, {10, 2}],
+ [{10, {2}}, {5, {1}}],
+ {0, 10}},
+ {[{5, 0}, {10, 0}], % drop 1
+ [{10, {0}}, {5, {0}}],
+ {0, 10}},
+ {[{5, 2}, {10, 1}, {15, 1}], % drop 2
+ [{15, {1}}, {10, {1}}, {5, {2}}],
+ {0, 15}},
+ {[{10, 0}, {15, 0}, {20, 0}], % drop
+ [{20, {0}}, {15, {0}}, {10, {0}}],
+ {0, 20}},
+ {[{5, 1}, {10, 5}, {15, 5}, {20, 0}], % drop middle
+ [{20, {0}}, {15, {5}}, {10, {5}}, {5, {1}}],
+ {0, 20}},
+ {[{5, 1}, {10, 5}, {15, 5}, {20, 1}], % drop middle filtered
+ [{20, {1}}, {15, {5}}, {10, {5}}],
+ {10, 20}},
+ {[{5, 1}, {10, 2}, {15, 3}, {20, 4}, {25, 4}, {30, 5}], % buffer roll over
+ [{30, {5}}, {25, {4}}, {20, {4}}, {15, {3}}, {10, {2}}, {5, {1}}],
+ {5, 30}}
+ ],
+ Slide = exometer_slide:new(Now, 25, [{interval, 5},
+ {max_n, 5}]),
+ Fun = fun(last, Acc) -> Acc;
+ (V, Acc) -> [V | Acc]
+ end,
+ [begin
+ S = lists:foldl(fun ({T, V}, Acc) ->
+ exometer_slide:add_element(T, {V}, Acc)
+ end, Slide, Inputs),
+ Expected = exometer_slide:foldl(To, From, Fun, [], S),
+ ExpRev = lists:reverse(Expected),
+ ExpRev = exometer_slide:to_list(To, From, S)
+ end || {Inputs, Expected, {From, To}} <- Tests].
+
+foldl_and_to_list_incremental(_Config) ->
+ Now = 0,
+ Tests = [ % {input, expected, query range}
+ {[],
+ [],
+ {0, 10}},
+ {[{5, 1}],
+ [{5, {1}}],
+ {0, 5}},
+ {[{10, 1}],
+ [{10, {1}}],
+ {0, 10}},
+ {[{5, 1}, {10, 1}],
+ [{10, {2}}, {5, {1}}],
+ {0, 10}},
+ {[{5, 0}, {10, 0}], % drop 1
+ [{10, {0}}, {5, {0}}],
+ {0, 10}},
+ {[{5, 1}, {10, 0}, {15, 0}], % drop 2
+ [{15, {1}}, {10, {1}}, {5, {1}}],
+ {0, 15}},
+ {[{10, 0}, {15, 0}, {20, 0}], % drop
+ [{20, {0}}, {15, {0}}, {10, {0}}],
+ {0, 20}},
+ {[{5, 1}, {10, 0}, {15, 0}, {20, 1}], % drop middle
+ [{20, {2}}, {15, {1}}, {10, {1}}, {5, {1}}],
+ {0, 20}},
+ {[{5, 1}, {10, 0}, {15, 0}, {20, 1}], % drop middle filtered
+ [{20, {2}}, {15, {1}}, {10, {1}}],
+ {10, 20}},
+ {[{5, 1}, {10, 1}, {15, 1}, {20, 1}, {25, 0}, {30, 1}], % buffer roll over
+ [{30, {5}}, {25, {4}}, {20, {4}}, {15, {3}}, {10, {2}}, {5, {1}}],
+ {5, 30}}
+ ],
+ Slide = exometer_slide:new(Now, 25, [{interval, 5},
+ {incremental, true},
+ {max_n, 5}]),
+ Fun = fun(last, Acc) -> Acc;
+ (V, Acc) -> [V | Acc]
+ end,
+ [begin
+ S = lists:foldl(fun ({T, V}, Acc) ->
+ exometer_slide:add_element(T, {V}, Acc)
+ end, Slide, Inputs),
+ Expected = exometer_slide:foldl(To, From, Fun, [], S),
+ ExpRev = lists:reverse(Expected),
+ ExpRev = exometer_slide:to_list(To, From, S)
+ end || {Inputs, Expected, {From, To}} <- Tests].
+
+stale_to_list(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{interval, 5}, {max_n, 5}]),
+ S = exometer_slide:add_element(50, {1}, Slide),
+ S2 = exometer_slide:add_element(55, {1}, S),
+ [] = exometer_slide:to_list(100, S2).
+
+to_list_single_after_drop(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{interval, 5},
+ {incremental, true},
+ {max_n, 5}]),
+ S = exometer_slide:add_element(5, {0}, Slide),
+ S2 = exometer_slide:add_element(10, {0}, S),
+ S3 = exometer_slide:add_element(15, {1}, S2),
+ Res = exometer_slide:to_list(17, S3),
+ [{5,{0}},{10,{0}},{15,{1}}] = Res.
+
+
+to_list_drop_and_roll(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 10, [{interval, 5},
+ {incremental, true},
+ {max_n, 5}]),
+ S = exometer_slide:add_element(5, {0}, Slide),
+ S2 = exometer_slide:add_element(10, {0}, S),
+ S3 = exometer_slide:add_element(15, {0}, S2),
+ [{10, {0}}, {15, {0}}] = exometer_slide:to_list(17, S3).
+
+
+sum_single(_Config) ->
+ Now = 0,
+ Slide = exometer_slide:new(Now, 25, [{interval, 5},
+ {incremental, true},
+ {max_n, 5}]),
+ S = exometer_slide:add_element(Now + 5, {0}, Slide),
+ S2 = exometer_slide:add_element(Now + 10, {0}, S),
+ Summed = exometer_slide:sum([S2]),
+ [_,_] = exometer_slide:to_list(15, Summed).
+
+
+to_normalized_list(_Config) ->
+ Interval = 5,
+ Tests = [ % {input, expected, query range}
+ {[], % zero pad when slide has never seen any samples
+ [{10, {0}}, {5, {0}}, {0, {0}}],
+ {0, 10}},
+ {[{5, 1}], % zero pad before first known sample
+ [{5, {1}}, {0, {0}}],
+ {0, 5}},
+ {[{10, 1}, {15, 1}], % zero pad before last know sample
+ [{15, {2}}, {10, {1}}, {5, {0}}],
+ {5, 15}},
+ {[{5, 1}, {15, 1}], % insert missing sample using previous total
+ [{15, {2}}, {10, {1}}, {5, {1}}],
+ {5, 15}},
+ % {[{6, 1}, {11, 1}, {16, 1}], % align timestamps with query
+ % [{15, {3}}, {10, {2}}, {5, {1}}, {0, {0}}],
+ % {0, 15}},
+ {[{5, 1}, {10, 1}, {15, 1}, {20, 1}, {25, 1}, {30, 1}], % outside of max_n
+ [{30, {6}}, {25, {5}}, {20, {4}}, {15, {3}}, {10, {2}}], % we cannot possibly be expected deduce what 10 should be
+ {10, 30}},
+ {[{5, 1}, {20, 1}, {25, 1}], % as long as the past TS 5 sample still exists we should use to for padding
+ [{25, {3}}, {20, {2}}, {15, {1}}, {10, {1}}],
+ {10, 25}},
+ {[{5, 1}, {10, 1}], % pad based on total
+ [{35, {2}}, {30, {2}}],
+ {30, 35}},
+ {[{5, 1}], % make up future values to fill the window
+ [{10, {1}}, {5, {1}}],
+ {5, 10}},
+ {[{5, 1}, {7, 1}], % realise last sample
+ [{10, {2}}, {5, {1}}],
+ {5, 10}}
+ ],
+
+ Slide = exometer_slide:new(0, 20, [{interval, 5},
+ {incremental, true},
+ {max_n, 4}]),
+ [begin
+ S0 = lists:foldl(fun ({T, V}, Acc) ->
+ exometer_slide:add_element(T, {V}, Acc)
+ end, Slide, Inputs),
+ Expected = exometer_slide:to_normalized_list(To, From, Interval, S0, {0}),
+ S = exometer_slide:sum([exometer_slide:optimize(S0)], {0}), % also test it post sum
+ Expected = exometer_slide:to_normalized_list(To, From, Interval, S, {0})
+ end || {Inputs, Expected, {From, To}} <- Tests].
+
+to_normalized_list_no_padding(_Config) ->
+ Interval = 5,
+ Tests = [ % {input, expected, query range}
+ {[],
+ [],
+ {0, 10}},
+ {[{5, 1}],
+ [{5, {1}}],
+ {0, 5}},
+ {[{5, 1}, {15, 1}],
+ [{15, {2}}, {10, {1}}, {5, {1}}],
+ {5, 15}},
+ {[{10, 1}, {15, 1}],
+ [{15, {2}}, {10, {1}}],
+ {5, 15}},
+ {[{5, 1}, {20, 1}], % NB as 5 is outside of the query we can't pick the value up
+ [{20, {2}}],
+ {10, 20}}
+ ],
+
+ Slide = exometer_slide:new(0, 20, [{interval, 5},
+ {incremental, true},
+ {max_n, 4}]),
+ [begin
+ S = lists:foldl(fun ({T, V}, Acc) ->
+ exometer_slide:add_element(T, {V}, Acc)
+ end, Slide, Inputs),
+ Expected = exometer_slide:to_normalized_list(To, From, Interval, S, no_pad)
+ end || {Inputs, Expected, {From, To}} <- Tests].
+
+to_list_in_the_past(_Config) ->
+ Slide = exometer_slide:new(0, 20, [{interval, 5},
+ {incremental, true},
+ {max_n, 4}]),
+ % ensure firstTS is way in the past
+ S0 = exometer_slide:add_element(5, {1}, Slide),
+ S1 = exometer_slide:add_element(105, {0}, S0),
+ S = exometer_slide:add_element(110, {0}, S1), % create drop
+ % query into the past
+ % this could happen if a node with and incorrect clock joins the cluster
+ [] = exometer_slide:to_list(50, 10, S).
+
+sum_mgmt_352(_Config) ->
+ %% In bug mgmt#352 all the samples returned have the same vale
+ Slide = sum_mgmt_352_slide(),
+ Last = 1487689330000,
+ First = 1487689270000,
+ Incr = 5000,
+ Empty = {0},
+ Sum = exometer_slide:sum(Last, First, Incr, [Slide], Empty),
+ Values = sets:to_list(sets:from_list(
+ [V || {_, V} <- exometer_slide:buffer(Sum)])),
+ true = (length(Values) == 12),
+ ok.
+
+sum_mgmt_352_extra(_Config) ->
+ %% Testing previous case clause to the one that fixes mgmt_352
+ %% exometer_slide.erl#L463
+ %% In the buggy version, all but the last sample are the same
+ Slide = sum_mgmt_352_slide_extra(),
+ Last = 1487689330000,
+ First = 1487689260000,
+ Incr = 5000,
+ Empty = {0},
+ Sum = exometer_slide:sum(Last, First, Incr, [Slide], Empty),
+ Values = sets:to_list(sets:from_list(
+ [V || {_, V} <- exometer_slide:buffer(Sum)])),
+ true = (length(Values) == 13),
+ ok.
+
+sum_mgmt_352_peak(_Config) ->
+ %% When buf2 contains data, we were returning a too old sample that
+ %% created a massive rate peak at the beginning of the graph.
+ %% The sample used was captured during a debug session.
+ Slide = sum_mgmt_352_slide_peak(),
+ Last = 1487752040000,
+ First = 1487751980000,
+ Incr = 5000,
+ Empty = {0},
+ Sum = exometer_slide:sum(Last, First, Incr, [Slide], Empty),
+ [{LastV}, {BLastV} | _] =
+ lists:reverse([V || {_, V} <- exometer_slide:buffer(Sum)]),
+ Rate = (BLastV - LastV) div 5,
+ true = (Rate < 20000),
+ ok.
+
+%% -------------------------------------------------------------------
+%% Util
+%% -------------------------------------------------------------------
+
+ele(TS, V) -> {TS, {V}}.
+
+%% -------------------------------------------------------------------
+%% Data
+%% -------------------------------------------------------------------
+sum_mgmt_352_slide() ->
+ %% Provide slide as is, from a debug session triggering mgmt-352 bug
+ {slide,610000,45,122,true,5000,1487689328468,1487689106834,
+ [{1487689328468,{1574200}},
+ {1487689323467,{1538800}},
+ {1487689318466,{1500800}},
+ {1487689313465,{1459138}},
+ {1487689308463,{1419200}},
+ {1487689303462,{1379600}},
+ {1487689298461,{1340000}},
+ {1487689293460,{1303400}},
+ {1487689288460,{1265600}},
+ {1487689283458,{1231400}},
+ {1487689278457,{1215800}},
+ {1487689273456,{1215200}},
+ {1487689262487,drop},
+ {1487689257486,{1205600}}],
+ [],
+ {1591000}}.
+
+sum_mgmt_352_slide_extra() ->
+ {slide,610000,45,122,true,5000,1487689328468,1487689106834,
+ [{1487689328468,{1574200}},
+ {1487689323467,{1538800}},
+ {1487689318466,{1500800}},
+ {1487689313465,{1459138}},
+ {1487689308463,{1419200}},
+ {1487689303462,{1379600}},
+ {1487689298461,{1340000}},
+ {1487689293460,{1303400}},
+ {1487689288460,{1265600}},
+ {1487689283458,{1231400}},
+ {1487689278457,{1215800}},
+ {1487689273456,{1215200}},
+ {1487689272487,drop},
+ {1487689269486,{1205600}}],
+ [],
+ {1591000}}.
+
+sum_mgmt_352_slide_peak() ->
+ {slide,610000,96,122,true,5000,1487752038481,1487750936863,
+ [{1487752038481,{11994024}},
+ {1487752033480,{11923200}},
+ {1487752028476,{11855800}},
+ {1487752023474,{11765800}},
+ {1487752018473,{11702431}},
+ {1487752013472,{11636200}},
+ {1487752008360,{11579800}},
+ {1487752003355,{11494800}},
+ {1487751998188,{11441400}},
+ {1487751993184,{11381000}},
+ {1487751988180,{11320000}},
+ {1487751983178,{11263000}},
+ {1487751978177,{11187600}},
+ {1487751973172,{11123375}},
+ {1487751968167,{11071800}},
+ {1487751963166,{11006200}},
+ {1487751958162,{10939477}},
+ {1487751953161,{10882400}},
+ {1487751948140,{10819600}},
+ {1487751943138,{10751200}},
+ {1487751938134,{10744400}},
+ {1487751933129,drop},
+ {1487751927807,{10710200}},
+ {1487751922803,{10670000}}],
+ [{1487751553386,{6655800}},
+ {1487751548385,{6580365}},
+ {1487751543384,{6509358}}],
+ {11994024}}.