Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 2E7E011BF7 for ; Mon, 21 Jul 2014 23:57:22 +0000 (UTC) Received: (qmail 13467 invoked by uid 500); 21 Jul 2014 23:57:16 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 13377 invoked by uid 500); 21 Jul 2014 23:57:16 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 11765 invoked by uid 99); 21 Jul 2014 23:57:15 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 21 Jul 2014 23:57:15 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 3DE149AE322; Mon, 21 Jul 2014 23:57:15 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: chewbranca@apache.org To: commits@couchdb.apache.org Date: Mon, 21 Jul 2014 23:57:38 -0000 Message-Id: In-Reply-To: <16e2756e1fe64463b44481d620de941b@git.apache.org> References: <16e2756e1fe64463b44481d620de941b@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [25/43] couchdb commit: updated refs/heads/1963-eunit-bigcouch to 424dca5 Port 121-stats-aggregates.t etap test suite to eunit Merged into couch_stats_tests suite. Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/4804e2e5 Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/4804e2e5 Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/4804e2e5 Branch: refs/heads/1963-eunit-bigcouch Commit: 4804e2e56e2a78e914c42b319a4d0af7a8ec4d4d Parents: e897be8 Author: Alexander Shorin Authored: Tue May 27 18:27:53 2014 +0400 Committer: Russell Branca Committed: Mon Jul 21 16:44:00 2014 -0700 ---------------------------------------------------------------------- test/couchdb/couch_stats_tests.erl | 225 ++++++++++++++++++- .../couchdb/fixtures/couch_stats_aggregates.cfg | 19 ++ .../couchdb/fixtures/couch_stats_aggregates.ini | 20 ++ test/etap/121-stats-aggregates.cfg | 19 -- test/etap/121-stats-aggregates.ini | 20 -- test/etap/121-stats-aggregates.t | 162 ------------- 6 files changed, 261 insertions(+), 204 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/4804e2e5/test/couchdb/couch_stats_tests.erl ---------------------------------------------------------------------- diff --git a/test/couchdb/couch_stats_tests.erl b/test/couchdb/couch_stats_tests.erl index aaaa687..d156449 100644 --- a/test/couchdb/couch_stats_tests.erl +++ b/test/couchdb/couch_stats_tests.erl @@ -15,18 +15,41 @@ -include("couch_eunit.hrl"). -include_lib("couchdb/couch_db.hrl"). +-define(STATS_CFG_FIXTURE, + filename:join([?FIXTURESDIR, "couch_stats_aggregates.cfg"])). +-define(STATS_INI_FIXTURE, + filename:join([?FIXTURESDIR, "couch_stats_aggregates.ini"])). -define(TIMEOUT, 1000). --define(SLEEPTIME, 100). +-define(TIMEWAIT, 500). setup_collector() -> couch_stats_collector:start(), ok. +setup_aggregator(_) -> + {ok, Pid} = couch_config:start_link([?STATS_INI_FIXTURE]), + {ok, _} = couch_stats_collector:start(), + {ok, _} = couch_stats_aggregator:start(?STATS_CFG_FIXTURE), + Pid. + teardown_collector(_) -> couch_stats_collector:stop(), ok. +teardown_aggregator(_, Pid) -> + couch_stats_aggregator:stop(), + couch_stats_collector:stop(), + erlang:monitor(process, Pid), + couch_config:stop(), + receive + {'DOWN', _, _, Pid, _} -> + ok + after ?TIMEOUT -> + throw({timeout, config_stop}) + end, + ok. + couch_stats_collector_test_() -> { @@ -51,6 +74,39 @@ couch_stats_collector_test_() -> } }. +couch_stats_aggregator_test_() -> + Funs = [ + fun should_init_empty_aggregate/2, + fun should_get_empty_aggregate/2, + fun should_change_stats_on_values_add/2, + fun should_change_stats_for_all_times_on_values_add/2, + fun should_change_stats_on_values_change/2, + fun should_change_stats_for_all_times_on_values_change/2, + fun should_not_remove_data_after_some_time_for_0_sample/2, + fun should_remove_data_after_some_time_for_other_samples/2 + ], + { + "CouchDB stats aggregator tests", + [ + { + "Absolute values", + { + foreachx, + fun setup_aggregator/1, fun teardown_aggregator/2, + [{absolute, Fun} || Fun <- Funs] + } + }, + { + "Counters", + { + foreachx, + fun setup_aggregator/1, fun teardown_aggregator/2, + [{counter, Fun} || Fun <- Funs] + } + } + ] + }. + should_increment_counter() -> ?_assertEqual(100, @@ -122,7 +178,7 @@ should_decrement_counter_on_process_exit() -> end, % sleep for awhile to let collector handle the updates % suddenly, it couldn't notice process death instantly - timer:sleep(?SLEEPTIME), + timer:sleep(?TIMEWAIT), couch_stats_collector:get(hoopla) end). @@ -138,7 +194,7 @@ should_decrement_for_each_track_process_count_call_on_exit() -> after ?TIMEOUT -> throw(timeout) end, - timer:sleep(?SLEEPTIME), + timer:sleep(?TIMEWAIT), couch_stats_collector:get(hoopla) end). @@ -170,6 +226,158 @@ should_return_absolute_values() -> lists:sort(couch_stats_collector:all(absolute)) end). +should_init_empty_aggregate(absolute, _) -> + {Aggs} = couch_stats_aggregator:all(), + ?_assertEqual({[{'11', make_agg(<<"randomosity">>, + null, null, null, null, null)}]}, + couch_util:get_value(number, Aggs)); +should_init_empty_aggregate(counter, _) -> + {Aggs} = couch_stats_aggregator:all(), + ?_assertEqual({[{stuff, make_agg(<<"yay description">>, + null, null, null, null, null)}]}, + couch_util:get_value(testing, Aggs)). + +should_get_empty_aggregate(absolute, _) -> + ?_assertEqual(make_agg(<<"randomosity">>, null, null, null, null, null), + couch_stats_aggregator:get_json({number, '11'})); +should_get_empty_aggregate(counter, _) -> + ?_assertEqual(make_agg(<<"yay description">>, null, null, null, null, null), + couch_stats_aggregator:get_json({testing, stuff})). + +should_change_stats_on_values_add(absolute, _) -> + lists:foreach(fun(X) -> + couch_stats_collector:record({number, 11}, X) + end, lists:seq(0, 10)), + couch_stats_aggregator:collect_sample(), + ?_assertEqual(make_agg(<<"randomosity">>, 5.0, 5.0, null, 5.0, 5.0), + couch_stats_aggregator:get_json({number, 11})); +should_change_stats_on_values_add(counter, _) -> + lists:foreach(fun(_) -> + couch_stats_collector:increment({testing, stuff}) + end, lists:seq(1, 100)), + couch_stats_aggregator:collect_sample(), + ?_assertEqual(make_agg(<<"yay description">>, 100.0, 100.0, null, 100, 100), + couch_stats_aggregator:get_json({testing, stuff})). + +should_change_stats_for_all_times_on_values_add(absolute, _) -> + lists:foreach(fun(X) -> + couch_stats_collector:record({number, 11}, X) + end, lists:seq(0, 10)), + couch_stats_aggregator:collect_sample(), + ?_assertEqual(make_agg(<<"randomosity">>, 5.0, 5.0, null, 5.0, 5.0), + couch_stats_aggregator:get_json({number, 11}, 1)); +should_change_stats_for_all_times_on_values_add(counter, _) -> + lists:foreach(fun(_) -> + couch_stats_collector:increment({testing, stuff}) + end, lists:seq(1, 100)), + couch_stats_aggregator:collect_sample(), + ?_assertEqual(make_agg(<<"yay description">>, 100.0, 100.0, null, 100, 100), + couch_stats_aggregator:get_json({testing, stuff}, 1)). + +should_change_stats_on_values_change(absolute, _) -> + ?_assertEqual(make_agg(<<"randomosity">>, 20.0, 10.0, 7.071, 5.0, 15.0), + begin + lists:foreach(fun(X) -> + couch_stats_collector:record({number, 11}, X) + end, lists:seq(0, 10)), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_collector:record({number, 11}, 15), + couch_stats_aggregator:collect_sample(), + couch_stats_aggregator:get_json({number, 11}) + end); +should_change_stats_on_values_change(counter, _) -> + ?_assertEqual(make_agg(<<"yay description">>, 100.0, 50.0, 70.711, 0, 100), + begin + lists:foreach(fun(_) -> + couch_stats_collector:increment({testing, stuff}) + end, lists:seq(1, 100)), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_aggregator:collect_sample(), + couch_stats_aggregator:get_json({testing, stuff}) + end). + +should_change_stats_for_all_times_on_values_change(absolute, _) -> + ?_assertEqual(make_agg(<<"randomosity">>, 20.0, 10.0, 7.071, 5.0, 15.0), + begin + lists:foreach(fun(X) -> + couch_stats_collector:record({number, 11}, X) + end, lists:seq(0, 10)), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_collector:record({number, 11}, 15), + couch_stats_aggregator:collect_sample(), + couch_stats_aggregator:get_json({number, 11}, 1) + end); +should_change_stats_for_all_times_on_values_change(counter, _) -> + ?_assertEqual(make_agg(<<"yay description">>, 100.0, 50.0, 70.711, 0, 100), + begin + lists:foreach(fun(_) -> + couch_stats_collector:increment({testing, stuff}) + end, lists:seq(1, 100)), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_aggregator:collect_sample(), + couch_stats_aggregator:get_json({testing, stuff}, 1) + end). + +should_not_remove_data_after_some_time_for_0_sample(absolute, _) -> + ?_assertEqual(make_agg(<<"randomosity">>, 20.0, 10.0, 7.071, 5.0, 15.0), + begin + lists:foreach(fun(X) -> + couch_stats_collector:record({number, 11}, X) + end, lists:seq(0, 10)), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_collector:record({number, 11}, 15), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_aggregator:collect_sample(), + couch_stats_aggregator:get_json({number, 11}) + end); +should_not_remove_data_after_some_time_for_0_sample(counter, _) -> + ?_assertEqual(make_agg(<<"yay description">>, 100.0, 33.333, 57.735, 0, 100), + begin + lists:foreach(fun(_) -> + couch_stats_collector:increment({testing, stuff}) + end, lists:seq(1, 100)), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_aggregator:collect_sample(), + couch_stats_aggregator:get_json({testing, stuff}) + end). + +should_remove_data_after_some_time_for_other_samples(absolute, _) -> + ?_assertEqual(make_agg(<<"randomosity">>, 15.0, 15.0, null, 15.0, 15.0), + begin + lists:foreach(fun(X) -> + couch_stats_collector:record({number, 11}, X) + end, lists:seq(0, 10)), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_collector:record({number, 11}, 15), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_aggregator:collect_sample(), + couch_stats_aggregator:get_json({number, 11}, 1) + end); +should_remove_data_after_some_time_for_other_samples(counter, _) -> + ?_assertEqual(make_agg(<<"yay description">>, 0, 0.0, 0.0, 0, 0), + begin + lists:foreach(fun(_) -> + couch_stats_collector:increment({testing, stuff}) + end, lists:seq(1, 100)), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_aggregator:collect_sample(), + timer:sleep(?TIMEWAIT), + couch_stats_aggregator:collect_sample(), + couch_stats_aggregator:get_json({testing, stuff}, 1) + end). + spawn_and_count(N) -> Self = self(), @@ -191,3 +399,14 @@ repeat(_, 0) -> repeat(Fun, Count) -> Fun(), repeat(Fun, Count-1). + +make_agg(Desc, Sum, Mean, StdDev, Min, Max) -> + {[ + {description, Desc}, + {current, Sum}, + {sum, Sum}, + {mean, Mean}, + {stddev, StdDev}, + {min, Min}, + {max, Max} + ]}. http://git-wip-us.apache.org/repos/asf/couchdb/blob/4804e2e5/test/couchdb/fixtures/couch_stats_aggregates.cfg ---------------------------------------------------------------------- diff --git a/test/couchdb/fixtures/couch_stats_aggregates.cfg b/test/couchdb/fixtures/couch_stats_aggregates.cfg new file mode 100644 index 0000000..30e475d --- /dev/null +++ b/test/couchdb/fixtures/couch_stats_aggregates.cfg @@ -0,0 +1,19 @@ +% Licensed to the Apache Software Foundation (ASF) under one +% or more contributor license agreements. See the NOTICE file +% distributed with this work for additional information +% regarding copyright ownership. The ASF licenses this file +% to you 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. + +{testing, stuff, "yay description"}. +{number, '11', "randomosity"}. http://git-wip-us.apache.org/repos/asf/couchdb/blob/4804e2e5/test/couchdb/fixtures/couch_stats_aggregates.ini ---------------------------------------------------------------------- diff --git a/test/couchdb/fixtures/couch_stats_aggregates.ini b/test/couchdb/fixtures/couch_stats_aggregates.ini new file mode 100644 index 0000000..cc5cd21 --- /dev/null +++ b/test/couchdb/fixtures/couch_stats_aggregates.ini @@ -0,0 +1,20 @@ +; Licensed to the Apache Software Foundation (ASF) under one +; or more contributor license agreements. See the NOTICE file +; distributed with this work for additional information +; regarding copyright ownership. The ASF licenses this file +; to you 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. + +[stats] +rate = 10000000 ; We call collect_sample in testing +samples = [0, 1] http://git-wip-us.apache.org/repos/asf/couchdb/blob/4804e2e5/test/etap/121-stats-aggregates.cfg ---------------------------------------------------------------------- diff --git a/test/etap/121-stats-aggregates.cfg b/test/etap/121-stats-aggregates.cfg deleted file mode 100644 index 30e475d..0000000 --- a/test/etap/121-stats-aggregates.cfg +++ /dev/null @@ -1,19 +0,0 @@ -% Licensed to the Apache Software Foundation (ASF) under one -% or more contributor license agreements. See the NOTICE file -% distributed with this work for additional information -% regarding copyright ownership. The ASF licenses this file -% to you 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. - -{testing, stuff, "yay description"}. -{number, '11', "randomosity"}. http://git-wip-us.apache.org/repos/asf/couchdb/blob/4804e2e5/test/etap/121-stats-aggregates.ini ---------------------------------------------------------------------- diff --git a/test/etap/121-stats-aggregates.ini b/test/etap/121-stats-aggregates.ini deleted file mode 100644 index cc5cd21..0000000 --- a/test/etap/121-stats-aggregates.ini +++ /dev/null @@ -1,20 +0,0 @@ -; Licensed to the Apache Software Foundation (ASF) under one -; or more contributor license agreements. See the NOTICE file -; distributed with this work for additional information -; regarding copyright ownership. The ASF licenses this file -; to you 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. - -[stats] -rate = 10000000 ; We call collect_sample in testing -samples = [0, 1] http://git-wip-us.apache.org/repos/asf/couchdb/blob/4804e2e5/test/etap/121-stats-aggregates.t ---------------------------------------------------------------------- diff --git a/test/etap/121-stats-aggregates.t b/test/etap/121-stats-aggregates.t deleted file mode 100755 index 4436beb..0000000 --- a/test/etap/121-stats-aggregates.t +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env escript -%% -*- erlang -*- - -% 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. - -ini_file() -> - test_util:source_file("test/etap/121-stats-aggregates.ini"). - -cfg_file() -> - test_util:source_file("test/etap/121-stats-aggregates.cfg"). - -main(_) -> - test_util:run(17, fun() -> test() end). - -test() -> - config_sup:start_link([ini_file()]), - couch_stats_collector:start(), - couch_stats_aggregator:start(cfg_file()), - ok = test_all_empty(), - ok = test_get_empty(), - ok = test_count_stats(), - ok = test_abs_stats(), - ok. - -test_all_empty() -> - {Aggs} = couch_stats_aggregator:all(), - - etap:is(length(Aggs), 2, "There are only two aggregate types in testing."), - etap:is( - couch_util:get_value(testing, Aggs), - {[{stuff, make_agg(<<"yay description">>, - null, null, null, null, null)}]}, - "{testing, stuff} is empty at start." - ), - etap:is( - couch_util:get_value(number, Aggs), - {[{'11', make_agg(<<"randomosity">>, - null, null, null, null, null)}]}, - "{number, '11'} is empty at start." - ), - ok. - -test_get_empty() -> - etap:is( - couch_stats_aggregator:get_json({testing, stuff}), - make_agg(<<"yay description">>, null, null, null, null, null), - "Getting {testing, stuff} returns an empty aggregate." - ), - etap:is( - couch_stats_aggregator:get_json({number, '11'}), - make_agg(<<"randomosity">>, null, null, null, null, null), - "Getting {number, '11'} returns an empty aggregate." - ), - ok. - -test_count_stats() -> - lists:foreach(fun(_) -> - couch_stats_collector:increment({testing, stuff}) - end, lists:seq(1, 100)), - couch_stats_aggregator:collect_sample(), - etap:is( - couch_stats_aggregator:get_json({testing, stuff}), - make_agg(<<"yay description">>, 100, 100, null, 100, 100), - "COUNT: Adding values changes the stats." - ), - etap:is( - couch_stats_aggregator:get_json({testing, stuff}, 1), - make_agg(<<"yay description">>, 100, 100, null, 100, 100), - "COUNT: Adding values changes stats for all times." - ), - - timer:sleep(500), - couch_stats_aggregator:collect_sample(), - etap:is( - couch_stats_aggregator:get_json({testing, stuff}), - make_agg(<<"yay description">>, 100, 50, 70.711, 0, 100), - "COUNT: Removing values changes stats." - ), - etap:is( - couch_stats_aggregator:get_json({testing, stuff}, 1), - make_agg(<<"yay description">>, 100, 50, 70.711, 0, 100), - "COUNT: Removing values changes stats for all times." - ), - - timer:sleep(600), - couch_stats_aggregator:collect_sample(), - etap:is( - couch_stats_aggregator:get_json({testing, stuff}), - make_agg(<<"yay description">>, 100, 33.333, 57.735, 0, 100), - "COUNT: Letting time passes doesn't remove data from time 0 aggregates" - ), - etap:is( - couch_stats_aggregator:get_json({testing, stuff}, 1), - make_agg(<<"yay description">>, 0, 0, 0, 0, 0), - "COUNT: Letting time pass removes data from other time aggregates." - ), - ok. - -test_abs_stats() -> - lists:foreach(fun(X) -> - couch_stats_collector:record({number, 11}, X) - end, lists:seq(0, 10)), - couch_stats_aggregator:collect_sample(), - etap:is( - couch_stats_aggregator:get_json({number, 11}), - make_agg(<<"randomosity">>, 5, 5, null, 5, 5), - "ABS: Adding values changes the stats." - ), - etap:is( - couch_stats_aggregator:get_json({number, 11}, 1), - make_agg(<<"randomosity">>, 5, 5, null, 5, 5), - "ABS: Adding values changes stats for all times." - ), - - timer:sleep(500), - couch_stats_collector:record({number, 11}, 15), - couch_stats_aggregator:collect_sample(), - etap:is( - couch_stats_aggregator:get_json({number, 11}), - make_agg(<<"randomosity">>, 20, 10, 7.071, 5, 15), - "ABS: New values changes stats" - ), - etap:is( - couch_stats_aggregator:get_json({number, 11}, 1), - make_agg(<<"randomosity">>, 20, 10, 7.071, 5, 15), - "ABS: Removing values changes stats for all times." - ), - - timer:sleep(600), - couch_stats_aggregator:collect_sample(), - etap:is( - couch_stats_aggregator:get_json({number, 11}), - make_agg(<<"randomosity">>, 20, 10, 7.071, 5, 15), - "ABS: Letting time passes doesn't remove data from time 0 aggregates" - ), - etap:is( - couch_stats_aggregator:get_json({number, 11}, 1), - make_agg(<<"randomosity">>, 15, 15, null, 15, 15), - "ABS: Letting time pass removes data from other time aggregates." - ), - ok. - -make_agg(Desc, Sum, Mean, StdDev, Min, Max) -> - {[ - {description, Desc}, - {current, Sum}, - {sum, Sum}, - {mean, Mean}, - {stddev, StdDev}, - {min, Min}, - {max, Max} - ]}.