diff options
Diffstat (limited to 'deps/rabbitmq_management_agent/test/exometer_slide_SUITE.erl')
-rw-r--r-- | deps/rabbitmq_management_agent/test/exometer_slide_SUITE.erl | 631 |
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}}. |