Merge default
This commit is contained in:
commit
e8841ba530
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2007-2009 IOLA and Ole Laursen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -8,3 +8,10 @@ Sammy is "Copyright (c) 2008 Aaron Quint, Quirkey NYC, LLC" and is
|
|||
covered by the MIT license. It was downloaded from
|
||||
http://code.quirkey.com/sammy/
|
||||
|
||||
ExplorerCanvas is "Copyright 2006 Google Inc" and is covered by the
|
||||
Apache License version 2.0. It was downloaded from
|
||||
http://code.google.com/p/explorercanvas/
|
||||
|
||||
Flot is "Copyright (c) 2007-2009 IOLA and Ole Laursen" and is covered
|
||||
by the MIT license. It was downloaded from
|
||||
http://code.google.com/p/flot/
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -140,27 +140,52 @@ lookup_element(Table, Key, Pos) ->
|
|||
result_or_error([]) -> error;
|
||||
result_or_error(S) -> S.
|
||||
|
||||
rates(Stats, Timestamp, OldStats, OldTimestamp, Keys) ->
|
||||
append_samples(Stats, Timestamp, Id, Table, Keys) ->
|
||||
OldStats = lookup_element(Table, Id),
|
||||
OldTimestamp = lookup_element(Table, Id, 3),
|
||||
Stats ++ [R || Key <- Keys,
|
||||
R <- [rate(Stats, Timestamp, OldStats, OldTimestamp, Key)],
|
||||
R <- [append_sample(Stats, Timestamp,
|
||||
OldStats, OldTimestamp, Key)],
|
||||
R =/= unknown].
|
||||
|
||||
rate(Stats, Timestamp, OldStats, OldTimestamp, Key) ->
|
||||
case OldTimestamp == [] orelse not proplists:is_defined(Key, OldStats) of
|
||||
true -> unknown;
|
||||
false -> Diff = pget(Key, Stats) - pget(Key, OldStats),
|
||||
Name = details_key(Key),
|
||||
Interval = timer:now_diff(Timestamp, OldTimestamp),
|
||||
Rate = Diff / (Interval / 1000000),
|
||||
{Name, [{rate, Rate},
|
||||
{interval, Interval},
|
||||
{last_event,
|
||||
rabbit_mgmt_format:timestamp_ms(Timestamp)}]}
|
||||
append_sample(Stats, TS, OldStats, OldTS, Key) ->
|
||||
KeyDetails = details_key(Key),
|
||||
case {pget(Key, Stats), pget(Key, OldStats), pget(KeyDetails, OldStats)} of
|
||||
{unknown, _, _} -> unknown;
|
||||
{_, unknown, _} -> unknown;
|
||||
{New, Old, unknown} -> OldMS = rabbit_mgmt_format:timestamp_ms(OldTS),
|
||||
MS = rabbit_mgmt_format:timestamp_ms(TS),
|
||||
{KeyDetails,
|
||||
[[{sample, New}, {timestamp, MS}],
|
||||
[{sample, Old}, {timestamp, OldMS}]]};
|
||||
{New, _, Samples} -> MS = rabbit_mgmt_format:timestamp_ms(TS),
|
||||
{KeyDetails,
|
||||
[[{sample, New}, {timestamp, MS}] |
|
||||
remove_old_samples(MS, Samples)]}
|
||||
end.
|
||||
|
||||
sum(List, Keys) ->
|
||||
lists:foldl(fun (I0, I1) -> gs_update(I0, I1, Keys) end,
|
||||
gs_update([], [], Keys), List).
|
||||
%% TODO be less crude
|
||||
-define(MAX_SAMPLE_AGE, 60000).
|
||||
remove_old_samples(Now, Samples) ->
|
||||
Cutoff = Now - ?MAX_SAMPLE_AGE,
|
||||
[Sample || Sample <- Samples,
|
||||
pget(timestamp, Sample) > Cutoff].
|
||||
|
||||
sum(Keys, List) ->
|
||||
[{Key, sum2(Key, List)} || Key <- Keys].
|
||||
|
||||
sum2(Key, List) ->
|
||||
case is_details(Key) of
|
||||
true ->
|
||||
%% TODO this is a bit crude
|
||||
[{rate, lists:foldl(fun (Stats, T) ->
|
||||
T + pget(rate, pget(Key, Stats, []), 0)
|
||||
end, 0, List)}];
|
||||
false ->
|
||||
lists:foldl(fun (Stats, T) ->
|
||||
T + pget(Key, Stats, 0)
|
||||
end, 0, List)
|
||||
end.
|
||||
|
||||
%% List = [{ [{channel, Pid}, ...], [{deliver, 123}, ...] } ...]
|
||||
group_sum([], List) ->
|
||||
|
|
@ -186,25 +211,36 @@ gs_update(Item0, Item1, Keys) ->
|
|||
[{Key, gs_update_add(Key, pget(Key, Item0), pget(Key, Item1))} ||
|
||||
Key <- Keys].
|
||||
|
||||
-define(SAMPLE_COMBINE_WINDOW, 5000).
|
||||
|
||||
gs_update_add(Key, Item0, Item1) ->
|
||||
case is_details(Key) of
|
||||
true ->
|
||||
I0 = if_unknown(Item0, []),
|
||||
I1 = if_unknown(Item1, []),
|
||||
%% TODO if I0 and I1 are from different channels then should we not
|
||||
%% just throw away interval / last_event?
|
||||
[{rate, pget(rate, I0, 0) + pget(rate, I1, 0)},
|
||||
{interval, gs_max(interval, I0, I1)},
|
||||
{last_event, gs_max(last_event, I0, I1)}];
|
||||
%% TODO this could *ahem* probably be more efficient
|
||||
%% TODO apportion across samples
|
||||
%% TODO if I0 and I1 are from different channels then
|
||||
%% should we do this at all?
|
||||
Tree = lists:foldl(
|
||||
fun ([{sample, S},
|
||||
{timestamp, T}], D) ->
|
||||
K = (T div ?SAMPLE_COMBINE_WINDOW) *
|
||||
?SAMPLE_COMBINE_WINDOW,
|
||||
case gb_trees:lookup(K, D) of
|
||||
{value, S1} -> gb_trees:update(K, S + S1, D);
|
||||
none -> gb_trees:insert(K, S, D)
|
||||
end
|
||||
end, gb_trees:empty(), I0 ++ I1),
|
||||
[[{sample, S},
|
||||
{timestamp, T}] || {T, S} <- lists:reverse(
|
||||
gb_trees:to_list(Tree))];
|
||||
false ->
|
||||
I0 = if_unknown(Item0, 0),
|
||||
I1 = if_unknown(Item1, 0),
|
||||
I0 + I1
|
||||
end.
|
||||
|
||||
gs_max(Key, I0, I1) ->
|
||||
erlang:max(pget(Key, I0, 0), pget(Key, I1, 0)).
|
||||
|
||||
if_unknown(unknown, Def) -> Def;
|
||||
if_unknown(Val, _Def) -> Val.
|
||||
|
||||
|
|
@ -273,7 +309,7 @@ handle_call({get_overview, User}, _From, State = #state{tables = Tables}) ->
|
|||
Qs0 = [rabbit_mgmt_format:queue(Q) || V <- VHosts,
|
||||
Q <- rabbit_amqqueue:list(V)],
|
||||
Qs1 = basic_queue_stats(Qs0, State),
|
||||
QueueTotals = sum(Qs1, ?OVERVIEW_QUEUE_STATS),
|
||||
QueueTotals = sum(?OVERVIEW_QUEUE_STATS, Qs1),
|
||||
|
||||
Filter = fun(Id, Name) ->
|
||||
lists:member(pget(vhost, pget(Name, Id)), VHosts)
|
||||
|
|
@ -283,7 +319,7 @@ handle_call({get_overview, User}, _From, State = #state{tables = Tables}) ->
|
|||
[], [R || R = {Id, _, _}
|
||||
<- ets:tab2list(orddict:fetch(Type, Tables)),
|
||||
Filter(augment_msg_stats(format_id(Id), State),
|
||||
Name)], State)
|
||||
Name)])
|
||||
end,
|
||||
Publish = F(channel_exchange_stats, exchange),
|
||||
Consume = F(channel_queue_stats, queue_details),
|
||||
|
|
@ -305,7 +341,7 @@ handle_call({get_overview, User}, _From, State = #state{tables = Tables}) ->
|
|||
X <- rabbit_exchange:list(V)])},
|
||||
{connections, F2(created_events(connection_stats, Tables))},
|
||||
{channels, F2(created_events(channel_stats, Tables))}],
|
||||
reply([{message_stats, Publish ++ Consume},
|
||||
reply([{message_stats, calculate_rates(Publish ++ Consume, State)},
|
||||
{queue_totals, QueueTotals},
|
||||
{object_totals, ObjectTotals}], State);
|
||||
|
||||
|
|
@ -434,9 +470,7 @@ handle_stats(TName, Stats0, Timestamp, Funs,
|
|||
Stats0, ?FINE_STATS_TYPES),
|
||||
Table = orddict:fetch(TName, Tables),
|
||||
Id = {id(Stats), stats},
|
||||
OldStats = lookup_element(Table, Id),
|
||||
OldTimestamp = lookup_element(Table, Id, 3),
|
||||
Stats1 = rates(Stats, Timestamp, OldStats, OldTimestamp, RatesKeys),
|
||||
Stats1 = append_samples(Stats, Timestamp, Id, Table, RatesKeys),
|
||||
Stats2 = proplists:delete(pid, rabbit_mgmt_format:format(Stats1, Funs)),
|
||||
ets:insert(Table, {Id, Stats2, Timestamp}),
|
||||
{ok, State}.
|
||||
|
|
@ -455,36 +489,26 @@ handle_consumer(Fun, Props,
|
|||
Fun(Table, {pget(queue, P), pget(channel, P)}, P),
|
||||
{ok, State}.
|
||||
|
||||
handle_fine_stats(Type, Props, Timestamp, State = #state{tables = Tables}) ->
|
||||
handle_fine_stats(Type, Props, Timestamp, #state{tables = Tables}) ->
|
||||
case pget(Type, Props) of
|
||||
unknown ->
|
||||
ok;
|
||||
AllFineStats ->
|
||||
ChPid = id(Props),
|
||||
Table = orddict:fetch(Type, Tables),
|
||||
IdsStatsTS =
|
||||
[{Ids,
|
||||
Stats,
|
||||
lookup_element(Table, fine_stats_key(ChPid, Ids)),
|
||||
lookup_element(Table, fine_stats_key(ChPid, Ids), 3)} ||
|
||||
{Ids, Stats} <- AllFineStats],
|
||||
delete_fine_stats(Type, ChPid, State),
|
||||
[handle_fine_stat(ChPid, Ids, Stats, Timestamp,
|
||||
OldStats, OldTimestamp, Table) ||
|
||||
{Ids, Stats, OldStats, OldTimestamp} <- IdsStatsTS]
|
||||
[handle_fine_stat(
|
||||
fine_stats_id(ChPid, Ids), Stats, Timestamp, Table) ||
|
||||
{Ids, Stats} <- AllFineStats]
|
||||
end.
|
||||
|
||||
|
||||
handle_fine_stat(ChPid, Ids, Stats, Timestamp,
|
||||
OldStats, OldTimestamp,
|
||||
Table) ->
|
||||
Id = fine_stats_key(ChPid, Ids),
|
||||
handle_fine_stat(Id, Stats, Timestamp, Table) ->
|
||||
Total = lists:sum([V || {K, V} <- Stats, lists:member(K, ?DELIVER_GET)]),
|
||||
Stats1 = case Total of
|
||||
0 -> Stats;
|
||||
_ -> [{deliver_get, Total}|Stats]
|
||||
end,
|
||||
Res = rates(Stats1, Timestamp, OldStats, OldTimestamp, ?FINE_STATS),
|
||||
Res = append_samples(Stats1, Timestamp, Id, Table, ?FINE_STATS),
|
||||
ets:insert(Table, {Id, Res, Timestamp}).
|
||||
|
||||
delete_fine_stats(Type, ChPid, #state{tables = Tables}) ->
|
||||
|
|
@ -492,9 +516,9 @@ delete_fine_stats(Type, ChPid, #state{tables = Tables}) ->
|
|||
ets:match_delete(Table, {{ChPid, '_'}, '_', '_'}),
|
||||
ets:match_delete(Table, {{ChPid, '_', '_'}, '_', '_'}).
|
||||
|
||||
fine_stats_key(ChPid, {QPid, X}) -> {ChPid, id(QPid), X};
|
||||
fine_stats_key(ChPid, QPid) when is_pid(QPid) -> {ChPid, id(QPid)};
|
||||
fine_stats_key(ChPid, X) -> {ChPid, X}.
|
||||
fine_stats_id(ChPid, {QPid, X}) -> {ChPid, id(QPid), X};
|
||||
fine_stats_id(ChPid, QPid) when is_pid(QPid) -> {ChPid, id(QPid)};
|
||||
fine_stats_id(ChPid, X) -> {ChPid, X}.
|
||||
|
||||
created_event(Names, Type, Tables) ->
|
||||
Table = orddict:fetch(Type, Tables),
|
||||
|
|
@ -508,12 +532,12 @@ created_events(Type, Tables) ->
|
|||
[Facts || {{_, create}, Facts, _Name}
|
||||
<- ets:tab2list(orddict:fetch(Type, Tables))].
|
||||
|
||||
get_fine_stats(Type, GroupBy, State = #state{tables = Tables}) ->
|
||||
get_fine_stats(Type, GroupBy, #state{tables = Tables}) ->
|
||||
get_fine_stats_from_list(
|
||||
GroupBy, ets:tab2list(orddict:fetch(Type, Tables)), State).
|
||||
GroupBy, ets:tab2list(orddict:fetch(Type, Tables))).
|
||||
|
||||
get_fine_stats_from_list(GroupBy, List, State) ->
|
||||
All = [{format_id(Id), zero_old_rates(Stats, State)} ||
|
||||
get_fine_stats_from_list(GroupBy, List) ->
|
||||
All = [{format_id(Id), Stats} ||
|
||||
{Id, Stats, _Timestamp} <- List],
|
||||
group_sum(GroupBy, All).
|
||||
|
||||
|
|
@ -534,7 +558,7 @@ merge_stats(Objs, Funs) ->
|
|||
basic_stats_fun(Type, IdProperty, State = #state{tables = Tables}) ->
|
||||
Table = orddict:fetch(Type, Tables),
|
||||
fun (Props) ->
|
||||
zero_old_rates(
|
||||
calculate_rates(
|
||||
lookup_element(Table, {pget(IdProperty, Props), stats}), State)
|
||||
end.
|
||||
|
||||
|
|
@ -567,8 +591,8 @@ augment_fine_stats(Dict, State) when element(1, Dict) == dict ->
|
|||
[[{stats, augment_fine_stats(Stats, State)} |
|
||||
augment_msg_stats([IdTuple], State)]
|
||||
|| {IdTuple, Stats} <- dict:to_list(Dict)];
|
||||
augment_fine_stats(Stats, _State) ->
|
||||
Stats.
|
||||
augment_fine_stats(Stats, State) ->
|
||||
calculate_rates(Stats, State).
|
||||
|
||||
consumer_details_fun(PatternFun, State = #state{tables = Tables}) ->
|
||||
Table = orddict:fetch(consumers, Tables),
|
||||
|
|
@ -580,16 +604,32 @@ consumer_details_fun(PatternFun, State = #state{tables = Tables}) ->
|
|||
ets:match(Table, {Pattern, '$1'}))]}]
|
||||
end.
|
||||
|
||||
zero_old_rates(Stats, State) -> [maybe_zero_rate(S, State) || S <- Stats].
|
||||
calculate_rates(Stats, State) -> [calculate_rate(S, State) || S <- Stats].
|
||||
|
||||
maybe_zero_rate({Key, Val}, #state{interval = Interval}) ->
|
||||
calculate_rate({Key, Val}, #state{interval = Interval}) ->
|
||||
case is_details(Key) of
|
||||
true -> Age = rabbit_misc:now_ms() - pget(last_event, Val),
|
||||
{Key, case Age > Interval * 1.5 of
|
||||
true -> pset(rate, 0, Val);
|
||||
false -> Val
|
||||
end};
|
||||
false -> {Key, Val}
|
||||
true ->
|
||||
case length(Val) > 1 of
|
||||
true ->
|
||||
[[{sample, S3}, {timestamp, T3}],
|
||||
[{sample, S2}, {timestamp, T2}] | _] = Val,
|
||||
{Inst, Avg} =
|
||||
case rabbit_misc:now_ms() - T3 > Interval * 1.5 of
|
||||
true -> {0, 0};
|
||||
false -> [{sample, S1},
|
||||
{timestamp, T1}] = lists:last(Val),
|
||||
{(S3 - S2) * 1000 / (T3 - T2),
|
||||
(S3 - S1) * 1000 / (T3 - T1)}
|
||||
end,
|
||||
{Key, [{rate, Inst},
|
||||
{interval, T3 - T2},
|
||||
{avg_rate, Avg},
|
||||
{samples, Val}]};
|
||||
false ->
|
||||
{Key, [{samples, Val}]}
|
||||
end;
|
||||
false ->
|
||||
{Key, Val}
|
||||
end.
|
||||
|
||||
is_details(Key) -> lists:suffix("_details", atom_to_list(Key)).
|
||||
|
|
|
|||
|
|
@ -345,7 +345,7 @@ assert_equal(Item, PList1, PList2) ->
|
|||
assert_rate(Exp, Stats) ->
|
||||
Interval = pget(interval, Stats),
|
||||
Rate = pget(rate, Stats),
|
||||
CorrectedRate = Interval / 5000000 * Rate,
|
||||
CorrectedRate = Interval / 5000 * Rate,
|
||||
case abs(Exp - CorrectedRate) < 0.00001 of
|
||||
true -> ok;
|
||||
_ -> throw({expected, Exp, got, Rate, corrected, CorrectedRate})
|
||||
|
|
|
|||
Loading…
Reference in New Issue