stable to default

This commit is contained in:
Simon MacMullen 2015-01-06 12:19:34 +00:00
commit 457bb83c4d
17 changed files with 282 additions and 112 deletions

View File

@ -532,6 +532,82 @@
List of network partitions this node is seeing.
</td>
</tr>
<tr>
<td><code>persister_read_avg_time</code></td>
<td>
Average wall time (milliseconds) for each disk read operation in
the last statistics interval.
</td>
</tr>
<tr>
<td><code>persister_read_bytes</code></td>
<td>
Total number of bytes read from disk by the persister.
</td>
</tr>
<tr>
<td><code>persister_read_count</code></td>
<td>
Total number of read operations by the persister.
</td>
</tr>
<tr>
<td><code>persister_reopen_count</code></td>
<td>
Total number of times the persister has needed to recycle
file handles between queues. In an ideal world this number
will be zero; if the number is large, performance might be
improved by increasing the number of file handles available
to RabbitMQ.
</td>
</tr>
<tr>
<td><code>persister_seek_avg_time</code></td>
<td>
Average wall time (milliseconds) for each seek operation in
the last statistics interval.
</td>
</tr>
</tr>
<tr>
<td><code>persister_seek_count</code></td>
<td>
Total number of seek operations by the persister.
</td>
</tr>
<tr>
<td><code>persister_sync_avg_time</code></td>
<td>
Average wall time (milliseconds) for each fsync() operation in
the last statistics interval.
</td>
</tr>
</tr>
<tr>
<td><code>persister_sync_count</code></td>
<td>
Total number of fsync() operations by the persister.
</td>
</tr>
<tr>
<td><code>persister_write_avg_time</code></td>
<td>
Average wall time (milliseconds) for each disk write operation in
the last statistics interval.
</td>
</tr>
<tr>
<td><code>persister_write_bytes</code></td>
<td>
Total number of bytes written to disk by the persister.
</td>
</tr>
<tr>
<td><code>persister_write_count</code></td>
<td>
Total number of write operations by the persister.
</td>
</tr>
<tr>
<td><code>proc_total</code></td>
<td>

View File

@ -12,22 +12,22 @@ function message_rates(id, stats) {
['Get', 'get'], ['Deliver (noack)', 'deliver_no_ack'],
['Get (noack)', 'get_no_ack'],
['Return', 'return_unroutable']];
return rates_chart_or_text(id, stats, items, fmt_rate, fmt_rate_large, fmt_rate_axis, true, 'Message rates', 'message-rates');
return rates_chart_or_text(id, stats, items, fmt_rate, fmt_rate_axis, true, 'Message rates', 'message-rates');
}
function queue_lengths(id, stats) {
var items = [['Ready', 'messages_ready'],
['Unacked', 'messages_unacknowledged'],
['Total', 'messages']];
return rates_chart_or_text(id, stats, items, fmt_msgs, fmt_msgs_large, fmt_num_axis, false, 'Queued messages', 'queued-messages');
return rates_chart_or_text(id, stats, items, fmt_num_thousands, fmt_plain_axis, false, 'Queued messages', 'queued-messages');
}
function data_rates(id, stats) {
var items = [['From client', 'recv_oct'], ['To client', 'send_oct']];
return rates_chart_or_text(id, stats, items, fmt_rate_bytes, fmt_rate_bytes_large, fmt_rate_bytes_axis, true, 'Data rates');
return rates_chart_or_text(id, stats, items, fmt_rate_bytes, fmt_rate_bytes_axis, true, 'Data rates');
}
function rates_chart_or_text(id, stats, items, chart_fmt, text_fmt, axis_fmt, chart_rates,
function rates_chart_or_text(id, stats, items, fmt, axis_fmt, chart_rates,
heading, heading_help) {
var mode = get_pref('rate-mode-' + id);
var range = get_pref('chart-range');
@ -37,10 +37,10 @@ function rates_chart_or_text(id, stats, items, chart_fmt, text_fmt, axis_fmt, ch
if (keys(stats).length > 0) {
if (mode == 'chart') {
res = rates_chart(
id, id, items, stats, chart_fmt, axis_fmt, 'full', chart_rates);
id, id, items, stats, fmt, axis_fmt, 'full', chart_rates);
}
else {
res = rates_text(items, stats, mode, text_fmt);
res = rates_text(items, stats, mode, fmt, chart_rates);
}
if (res == "") res = '<p>Waiting for data...</p>';
}
@ -79,7 +79,7 @@ function node_stat_count(used_key, limit_key, stats, thresholds) {
var limit = stats[limit_key];
if (typeof used == 'number') {
return node_stat(used_key, 'Used', limit_key, 'available', stats,
fmt_num_obj, fmt_num_axis,
fmt_plain, fmt_plain_axis,
fmt_color(used / limit, thresholds));
} else {
return used;
@ -91,19 +91,20 @@ function node_stat_count_bar(used_key, limit_key, stats, thresholds) {
var limit = stats[limit_key];
if (typeof used == 'number') {
return node_stat_bar(used_key, limit_key, 'available', stats,
fmt_num_axis, fmt_color(used / limit, thresholds));
fmt_plain_axis,
fmt_color(used / limit, thresholds));
} else {
return used;
}
}
function node_stat(used_key, used_name, limit_key, suffix, stats, rate_fmt,
function node_stat(used_key, used_name, limit_key, suffix, stats, fmt,
axis_fmt, colour, help, invert) {
if (get_pref('rate-mode-node-stats') == 'chart') {
var items = [[used_name, used_key], ['Limit', limit_key]];
add_fake_limit_details(used_key, limit_key, stats);
return rates_chart('node-stats', 'node-stats-' + used_key, items, stats,
rate_fmt, axis_fmt, 'node', false);
fmt, axis_fmt, 'node', false);
} else {
return node_stat_bar(used_key, limit_key, suffix, stats, axis_fmt,
colour, help, invert);
@ -156,7 +157,7 @@ function node_stats_prefs() {
return chart_h3('node-stats', 'Node statistics');
}
function rates_chart(type_id, id, items, stats, rate_fmt, axis_fmt, type,
function rates_chart(type_id, id, items, stats, fmt, axis_fmt, type,
chart_rates) {
function show(key) {
return get_pref('chart-line-' + id + key) === 'true';
@ -177,9 +178,11 @@ function rates_chart(type_id, id, items, stats, rate_fmt, axis_fmt, type,
chart_data[id]['data'][name] = stats[key_details];
chart_data[id]['data'][name].ix = ix;
}
var value = chart_rates ? pick_rate(fmt, stats, key) :
pick_abs(fmt, stats, key);
legend.push({name: name,
key: key,
value: rate_fmt(stats, key),
value: value,
show: show(key)});
ix++;
}
@ -201,7 +204,7 @@ function rates_chart(type_id, id, items, stats, rate_fmt, axis_fmt, type,
return legend.length > 0 ? html : '';
}
function rates_text(items, stats, mode, rate_fmt) {
function rates_text(items, stats, mode, fmt, chart_rates) {
var res = '';
for (var i in items) {
var name = items[i][0];
@ -209,9 +212,10 @@ function rates_text(items, stats, mode, rate_fmt) {
var key_details = key + '_details';
if (key_details in stats) {
var details = stats[key_details];
res += '<div class="highlight">' + name;
res += rate_fmt(stats, key, mode);
res += '</div>';
res += '<div class="highlight">' + name + '<strong>';
res += chart_rates ? pick_rate(fmt, stats, key, mode) :
pick_abs(fmt, stats, key, mode);
res += '</strong></div>';
}
}
return res == '' ? '' : '<div class="box">' + res + '</div>';

View File

@ -12,11 +12,6 @@ function fmt_string(str, unknown) {
return fmt_escape_html("" + str);
}
function fmt_bytes(bytes) {
if (bytes == undefined) return UNKNOWN_REPR;
return fmt_si_prefix(bytes, bytes, 1024, false) + 'B';
}
function fmt_si_prefix(num0, max0, thousand, allow_fractions) {
if (num == 0) return 0;
@ -228,71 +223,51 @@ function fmt_percent(num) {
}
}
function fmt_rate(obj, name, mode) {
var raw = fmt_rate0(obj, name, mode, fmt_rate_num);
return raw == '' ? '' : (raw + '/s');
}
function fmt_rate_bytes(obj, name, mode) {
var raw = fmt_rate0(obj, name, mode, fmt_bytes);
return raw == '' ? '' : (raw + '/s' +
'<sub>(' + fmt_bytes(obj[name]) + ' total)</sub>');
}
function fmt_bytes_obj(obj, name, mode) {
return fmt_bytes(obj[name]);
}
function fmt_num_obj(obj, name, mode) {
return obj[name];
}
function fmt_rate_large(obj, name, mode) {
return '<strong>' + fmt_rate0(obj, name, mode, fmt_rate_num) +
'</strong>msg/s';
}
function fmt_rate_bytes_large(obj, name, mode) {
return '<strong>' + fmt_rate0(obj, name, mode, fmt_bytes) + '/s</strong>' +
'(' + fmt_bytes(obj[name]) + ' total)';
}
function fmt_rate0(obj, name, mode, fmt) {
function pick_rate(fmt, obj, name, mode) {
if (obj == undefined || obj[name] == undefined ||
obj[name + '_details'] == undefined) return '';
var details = obj[name + '_details'];
return fmt(mode == 'avg' ? details.avg_rate : details.rate);
}
function fmt_msgs(obj, name, mode) {
return fmt_msgs0(obj, name, mode) + ' msg';
}
function fmt_msgs_large(obj, name, mode) {
return '<strong>' + fmt_msgs0(obj, name, mode) + '</strong>' +
fmt_rate0(obj, name, mode, fmt_msgs_rate);
}
function fmt_msgs0(obj, name, mode) {
function pick_abs(fmt, obj, name, mode) {
if (obj == undefined || obj[name] == undefined ||
obj[name + '_details'] == undefined) return '';
var details = obj[name + '_details'];
return mode == 'avg' ? fmt_rate_num(details.avg) :
fmt_num_thousands(obj[name]);
return fmt(mode == 'avg' ? details.avg : obj[name]);
}
function fmt_msgs_rate(num) {
if (num > 0) return '+' + fmt_rate_num(num) + ' msg/s';
else if (num < 0) return '-' + fmt_rate_num(-num) + ' msg/s';
else return '&nbsp;';
function fmt_detail_rate(obj, name, mode) {
return pick_rate(fmt_rate, name, mode);
}
function fmt_detail_rate_bytes(obj, name, mode) {
return pick_rate(fmt_rate_bytes, name, mode);
}
// ---------------------------------------------------------------------
// These are pluggable for charts etc
function fmt_plain(num) {
return num;
}
function fmt_plain_axis(num, max) {
return fmt_si_prefix(num, max, 1000, true);
}
function fmt_rate(num) {
return fmt_rate_num(num) + '/s';
}
function fmt_rate_axis(num, max) {
return fmt_si_prefix(num, max, 1000, true) + '/s';
return fmt_plain_axis(num, max) + '/s';
}
function fmt_num_axis(num, max) {
return fmt_si_prefix(num, max, 1000, true);
function fmt_bytes(bytes) {
if (bytes == undefined) return UNKNOWN_REPR;
return fmt_si_prefix(bytes, bytes, 1024, false) + 'B';
}
function fmt_bytes_axis(num, max) {
@ -300,11 +275,20 @@ function fmt_bytes_axis(num, max) {
return fmt_bytes(isNaN(num) ? 0 : num);
}
function fmt_rate_bytes(num) {
return fmt_bytes(num) + '/s';
}
function fmt_rate_bytes_axis(num, max) {
return fmt_bytes_axis(num, max) + '/s';
}
function fmt_ms(num) {
return fmt_rate_num(num) + 'ms';
}
// ---------------------------------------------------------------------
function fmt_maybe_vhost(name) {
return vhosts_interesting ?
' in virtual host <b>' + fmt_escape_html(name) + '</b>'

View File

@ -137,6 +137,7 @@ var COLUMNS =
// All these are to do with hiding UI elements if
var rates_mode; // ...there are no fine stats
var user_administrator; // ...user is not an admin
var user_policymaker; // ...user is not a policymaker
var user_monitor; // ...user cannot monitor
var nodes_interesting; // ...we are not in a cluster
var vhosts_interesting; // ...there is only one vhost
@ -164,6 +165,7 @@ function setup_global_vars() {
rates_mode = overview.rates_mode;
user_tags = expand_user_tags(user.tags.split(","));
user_administrator = jQuery.inArray("administrator", user_tags) != -1;
user_policymaker = jQuery.inArray("policymaker", user_tags) != -1;
user_monitor = jQuery.inArray("monitoring", user_tags) != -1;
replace_content('login-details',
'<p>User: <b>' + user.name + '</b></p>' +

View File

@ -251,6 +251,28 @@ HELP = {
'plugins' :
'Note that only plugins which are both explicitly enabled and running are shown here.',
'io-operations':
'Rate of I/O operations. Only operations performed by the message \
persister are shown here (e.g. metadata changes in Mnesia or writes \
to the log files are not shown).\
<dl>\
<dt>Read</dt>\
<dd>Rate at which data is read from the disk.</dd>\
<dt>Write</dt>\
<dd>Rate at which data is written to the disk.</dd>\
<dt>Seek</dt>\
<dd>Rate at which the broker switches position while reading or \
writing to disk.</dd>\
<dt>Sync</dt>\
<dd>Rate at which the broker invokes <code>fsync()</code> to ensure \
data is flushed to disk.</dd>\
<dt>Reopen</dt>\
<dd>Rate at which the broker recycles file handles in order to support \
more queues than it has file handles. If this operation is occurring \
frequently you may get a performance boost from increasing the number \
of file handles available.</dd>\
</dl>',
'foo': 'foo' // No comma.
};

View File

@ -167,22 +167,22 @@
<% } %>
<% if (rates_mode != 'none') { %>
<% if (show_column('channels', 'rate-publish')) { %>
<td class="r"><%= fmt_rate(channel.message_stats, 'publish') %></td>
<td class="r"><%= fmt_detail_rate(channel.message_stats, 'publish') %></td>
<% } %>
<% if (show_column('channels', 'rate-confirm')) { %>
<td class="r"><%= fmt_rate(channel.message_stats, 'confirm') %></td>
<td class="r"><%= fmt_detail_rate(channel.message_stats, 'confirm') %></td>
<% } %>
<% if (show_column('channels', 'rate-return')) { %>
<td class="r"><%= fmt_rate(channel.message_stats, 'return_unroutable') %></td>
<td class="r"><%= fmt_detail_rate(channel.message_stats, 'return_unroutable') %></td>
<% } %>
<% if (show_column('channels', 'rate-deliver')) { %>
<td class="r"><%= fmt_rate(channel.message_stats, 'deliver_get') %></td>
<td class="r"><%= fmt_detail_rate(channel.message_stats, 'deliver_get') %></td>
<% } %>
<% if (show_column('channels', 'rate-redeliver')) { %>
<td class="r"><%= fmt_rate(channel.message_stats, 'redeliver') %></td>
<td class="r"><%= fmt_detail_rate(channel.message_stats, 'redeliver') %></td>
<% } %>
<% if (show_column('channels', 'rate-ack')) { %>
<td class="r"><%= fmt_rate(channel.message_stats, 'ack') %></td>
<td class="r"><%= fmt_detail_rate(channel.message_stats, 'ack') %></td>
<% } %>
<% } %>
</tr>

View File

@ -115,10 +115,10 @@
<td><%= fmt_client_name(connection.client_properties) %></td>
<% } %>
<% if (show_column('connections', 'from_client')) { %>
<td><%= fmt_rate_bytes(connection, 'recv_oct') %></td>
<td><%= fmt_detail_rate_bytes(connection, 'recv_oct') %></td>
<% } %>
<% if (show_column('connections', 'to_client')) { %>
<td><%= fmt_rate_bytes(connection, 'send_oct') %></td>
<td><%= fmt_detail_rate_bytes(connection, 'send_oct') %></td>
<% } %>
<% if (show_column('connections', 'heartbeat')) { %>
<td class="r"><%= fmt_time(connection.timeout, 's') %></td>

View File

@ -64,10 +64,10 @@
<% } %>
<% if (rates_mode != 'none') { %>
<% if (show_column('exchanges', 'rate-in')) { %>
<td class="r"><%= fmt_rate(exchange.message_stats, 'publish_in') %></td>
<td class="r"><%= fmt_detail_rate(exchange.message_stats, 'publish_in') %></td>
<% } %>
<% if (show_column('exchanges', 'rate-out')) { %>
<td class="r"><%= fmt_rate(exchange.message_stats, 'publish_out') %></td>
<td class="r"><%= fmt_detail_rate(exchange.message_stats, 'publish_out') %></td>
<% } %>
<% } %>
</tr>

View File

@ -20,8 +20,8 @@
<% } else { %>
<td><%= link_queue(del.queue.vhost, del.queue.name) %></td>
<% } %>
<td class="r"><%= fmt_rate(del.stats, 'deliver_get') %></td>
<td class="r"><%= fmt_rate(del.stats, 'ack') %></td>
<td class="r"><%= fmt_detail_rate(del.stats, 'deliver_get') %></td>
<td class="r"><%= fmt_detail_rate(del.stats, 'ack') %></td>
</tr>
<% } %>
</table>

View File

@ -34,9 +34,9 @@
<% } else { %>
<td><%= link_exchange(pub.exchange.vhost, pub.exchange.name) %></td>
<% } %>
<td class="r"><%= fmt_rate(pub.stats, 'publish') %></td>
<td class="r"><%= fmt_detail_rate(pub.stats, 'publish') %></td>
<% if (col_confirm) { %>
<td class="r"><%= fmt_rate(pub.stats, 'confirm') %></td>
<td class="r"><%= fmt_detail_rate(pub.stats, 'confirm') %></td>
<% } %>
</tr>
<% } %>

View File

@ -60,7 +60,7 @@
</div>
<div class="section">
<h2>Statistics</h2>
<h2>Process Statistics</h2>
<div class="hider">
<% if (!node.running) { %>
<p class="warning">Node not running</p>
@ -106,7 +106,7 @@
<td>
<% if (node.mem_limit != 'memory_monitoring_disabled') { %>
<%= node_stat('mem_used', 'Used', 'mem_limit', 'high watermark', node,
fmt_bytes_obj, fmt_bytes_axis,
fmt_bytes, fmt_bytes_axis,
node.mem_alarm ? 'red' : 'green',
node.mem_alarm ? 'memory-alarm' : null) %>
<% } else { %>
@ -121,7 +121,7 @@
<td>
<% if (node.disk_free_limit != 'disk_free_monitoring_disabled') { %>
<%= node_stat('disk_free', 'Free', 'disk_free_limit', 'low watermark', node,
fmt_bytes_obj, fmt_bytes_axis,
fmt_bytes, fmt_bytes_axis,
node.disk_free_alarm ? 'red' : 'green',
node.disk_free_alarm ? 'disk_free-alarm' : null,
true) %>
@ -137,6 +137,25 @@
</div>
</div>
<div class="section">
<h2>I/O Statistics</h2>
<div class="hider">
<% if (!node.running) { %>
<p class="warning">Node not running</p>
<% } else if (node.os_pid == undefined) { %>
<p class="warning">Node statistics not available</p>
<% } else { %>
<%= rates_chart_or_text('persister-stats-count', node, [['Read', 'persister_read_count'], ['Write', 'persister_write_count'], ['Seek', 'persister_seek_count'], ['Sync', 'persister_sync_count'], ['Reopen', 'persister_reopen_count']], fmt_rate, fmt_rate_axis, true, 'Operations', 'io-operations') %>
<%= rates_chart_or_text('persister-stats-bytes', node, [['Read', 'persister_read_bytes'], ['Write', 'persister_write_bytes']], fmt_rate_bytes, fmt_rate_bytes_axis, true, 'Data rates') %>
<%= rates_chart_or_text('persister-stats-time', node, [['Read', 'persister_read_avg_time'], ['Write', 'persister_write_avg_time'], ['Seek', 'persister_seek_avg_time'], ['Sync', 'persister_sync_avg_time']], fmt_ms, fmt_ms, false, 'Average time per operation') %>
<% } %>
</div>
</div>
<div class="section">
<h2>Memory details</h2>
<div class="hider">

View File

@ -245,6 +245,51 @@
</div>
</div>
<% if (user_policymaker) { %>
<div class="section-hidden">
<h2>Move messages</h2>
<div class="hider">
<% if (NAVIGATION['Admin'][0]['Shovel Management'] == undefined) { %>
<p>To move messages, the shovel plugin must be enabled, try:</p>
<pre>$ rabbitmq-plugins enable rabbitmq_shovel rabbitmq_shovel_management</pre>
<% } else { %>
<p>
The shovel plugin can be used to move messages from this queue
to another one. The form below will create a temporary shovel to
move messages to another queue on the same virtual host, with
default settings.
</p>
<p>
For more options <a href="#/dynamic-shovels">see the shovel
interface</a>.
</p>
<form action="#/shovel-parameters" method="put">
<input type="hidden" name="component" value="shovel"/>
<input type="hidden" name="vhost" value="<%= fmt_string(queue.vhost) %>"/>
<input type="hidden" name="name" value="Move from <%= fmt_string(queue.name) %>"/>
<input type="hidden" name="src-uri" value="amqp:///<%= esc(queue.vhost) %>"/>
<input type="hidden" name="src-queue" value="<%= fmt_string(queue.name) %>"/>
<input type="hidden" name="dest-uri" value="amqp:///<%= esc(queue.vhost) %>"/>
<input type="hidden" name="prefetch-count" value="1000"/>
<input type="hidden" name="add-forward-headers" value="false"/>
<input type="hidden" name="ack-mode" value="on-confirm"/>
<input type="hidden" name="delete-after" value="queue-length"/>
<input type="hidden" name="redirect" value="#/queues"/>
<table class="form">
<tr>
<th>Destination queue:</th>
<td><input type="text" name="dest-queue"/></td>
</tr>
</table>
<input type="submit" value="Move messages"/>
</form>
<% } %>
</div>
</div>
<% } %>
<div class="section-hidden">
<h2>Delete / purge</h2>
<div class="hider">

View File

@ -160,16 +160,16 @@
<% } %>
<% if (rates_mode != 'none') { %>
<% if (show_column('queues', 'rate-incoming')) { %>
<td class="r"><%= fmt_rate(queue.message_stats, 'publish') %></td>
<td class="r"><%= fmt_detail_rate(queue.message_stats, 'publish') %></td>
<% } %>
<% if (show_column('queues', 'rate-deliver')) { %>
<td class="r"><%= fmt_rate(queue.message_stats, 'deliver_get') %></td>
<td class="r"><%= fmt_detail_rate(queue.message_stats, 'deliver_get') %></td>
<% } %>
<% if (show_column('queues', 'rate-redeliver')) { %>
<td class="r"><%= fmt_rate(queue.message_stats, 'redeliver') %></td>
<td class="r"><%= fmt_detail_rate(queue.message_stats, 'redeliver') %></td>
<% } %>
<% if (show_column('queues', 'rate-ack')) { %>
<td class="r"><%= fmt_rate(queue.message_stats, 'ack') %></td>
<td class="r"><%= fmt_detail_rate(queue.message_stats, 'ack') %></td>
<% } %>
<% } %>
</tr>

View File

@ -64,17 +64,17 @@
<td class="r"><%= fmt_num_thousands(vhost.messages) %></td>
<% } %>
<% if (show_column('vhosts', 'from_client')) { %>
<td><%= fmt_rate_bytes(vhost, 'recv_oct') %></td>
<td><%= fmt_detail_rate_bytes(vhost, 'recv_oct') %></td>
<% } %>
<% if (show_column('vhosts', 'to_client')) { %>
<td><%= fmt_rate_bytes(vhost, 'send_oct') %></td>
<td><%= fmt_detail_rate_bytes(vhost, 'send_oct') %></td>
<% } %>
<% if (rates_mode != 'none') { %>
<% if (show_column('vhosts', 'rate-publish')) { %>
<td class="r"><%= fmt_rate(vhost.message_stats, 'publish') %></td>
<td class="r"><%= fmt_detail_rate(vhost.message_stats, 'publish') %></td>
<% } %>
<% if (show_column('vhosts', 'rate-deliver')) { %>
<td class="r"><%= fmt_rate(vhost.message_stats, 'deliver_get') %></td>
<td class="r"><%= fmt_detail_rate(vhost.message_stats, 'deliver_get') %></td>
<% } %>
<% } %>
</tr>

View File

@ -159,7 +159,19 @@
[messages, messages_ready, messages_unacknowledged]).
-define(COARSE_NODE_STATS,
[mem_used, fd_used, sockets_used, proc_used, disk_free]).
[mem_used, fd_used, sockets_used, proc_used, disk_free,
persister_read_count, persister_read_bytes, persister_read_avg_time,
persister_write_count, persister_write_bytes, persister_write_avg_time,
persister_sync_count, persister_sync_avg_time,
persister_seek_count, persister_seek_avg_time,
persister_reopen_count]).
%% Normally 0 and no history means "has never happened, don't
%% report". But for these things we do want to report even at 0 with
%% no history.
-define(ALWAYS_REPORT_STATS,
[persister_read_avg_time, persister_write_avg_time,
persister_sync_avg_time | ?COARSE_QUEUE_STATS]).
-define(COARSE_CONN_STATS, [recv_oct, send_oct]).
@ -572,8 +584,10 @@ handle_event(#event{type = consumer_deleted, props = Props}, State) ->
%% TODO: we don't clear up after dead nodes here - this is a very tiny
%% leak every time a node is permanently removed from the cluster. Do
%% we care?
handle_event(#event{type = node_stats, props = Stats, timestamp = Timestamp},
handle_event(#event{type = node_stats, props = Stats0, timestamp = Timestamp},
State) ->
Stats = proplists:delete(persister_stats, Stats0) ++
pget(persister_stats, Stats0),
handle_stats(node_stats, Stats, Timestamp, [], ?COARSE_NODE_STATS, State);
handle_event(_Event, State) ->
@ -965,7 +979,7 @@ format_detail_id(#resource{name = Name, virtual_host = Vhost, kind = Kind},
format_samples(Ranges, ManyStats, #state{interval = Interval}) ->
lists:append(
[case rabbit_mgmt_stats:is_blank(Stats) andalso
not lists:member(K, ?COARSE_QUEUE_STATS) of
not lists:member(K, ?ALWAYS_REPORT_STATS) of
true -> [];
false -> {Details, Counter} = rabbit_mgmt_stats:format(
pick_range(K, Ranges),
@ -1095,7 +1109,7 @@ gc_batch(State = #state{aggregated_stats = ETS}) ->
gc_batch(0, _Policies, State) ->
State;
gc_batch(Rows, Policies, State = #state{aggregated_stats = ETS,
gc_next_key = Key0}) ->
gc_next_key = Key0}) ->
Key = case Key0 of
undefined -> ets:first(ETS);
_ -> ets:next(ETS, Key0)

View File

@ -157,9 +157,8 @@ internal_user(User) ->
{tags, tags(User#internal_user.tags)}].
user(User) ->
[{name, User#user.username},
{tags, tags(User#user.tags)},
{auth_backend, User#user.auth_backend}].
[{name, User#user.username},
{tags, tags(User#user.tags)}].
tags(Tags) ->
list_to_binary(string:join([atom_to_list(T) || T <- Tags], ",")).

View File

@ -28,7 +28,7 @@
-export([with_channel/4, with_channel/5]).
-export([props_to_method/2, props_to_method/4]).
-export([all_or_one_vhost/2, http_to_amqp/5, reply/3, filter_vhost/3]).
-export([filter_conn_ch_list/3, filter_user/2, list_login_vhosts/1]).
-export([filter_conn_ch_list/3, filter_user/2, list_login_vhosts/2]).
-export([with_decode/5, decode/1, decode/2, redirect/2, set_resp_header/3,
args/1]).
-export([reply_list/3, reply_list/4, sort_list/2, destination_type/1]).
@ -77,7 +77,7 @@ user_matches_vhost(ReqData, User) ->
case vhost(ReqData) of
not_found -> true;
none -> true;
V -> lists:member(V, list_login_vhosts(User))
V -> lists:member(V, list_login_vhosts(User, peersock(ReqData)))
end.
%% Used for connections / channels. A normal user can only see / delete
@ -143,12 +143,15 @@ is_authorized(ReqData, Context, Username, Password, ErrorMsg, Fun) ->
not_authorised(<<"Login failed">>, ReqData, Context)
end.
%% We can't use wrq:peer/1 because that trusts X-Forwarded-For.
peer(ReqData) ->
WMState = ReqData#wm_reqdata.wm_state,
{ok, {IP,_Port}} = peername(WMState#wm_reqstate.socket),
{ok, {IP,_Port}} = peername(peersock(ReqData)),
IP.
%% We can't use wrq:peer/1 because that trusts X-Forwarded-For.
peersock(ReqData) ->
WMState = ReqData#wm_reqdata.wm_state,
WMState#wm_reqstate.socket.
%% Like the one in rabbit_net, but we and webmachine have a different
%% way of wrapping
peername(Sock) when is_port(Sock) -> inet:peername(Sock);
@ -452,6 +455,8 @@ with_channel(VHost, ReqData,
end;
{error, {auth_failure, Msg}} ->
not_authorised(Msg, ReqData, Context);
{error, access_refused} ->
not_authorised(<<"Access refused.">>, ReqData, Context);
{error, {nodedown, N}} ->
bad_request(
list_to_binary(
@ -470,8 +475,8 @@ all_or_one_vhost(ReqData, Fun) ->
VHost -> Fun(VHost)
end.
filter_vhost(List, _ReqData, Context) ->
VHosts = list_login_vhosts(Context#context.user),
filter_vhost(List, ReqData, Context) ->
VHosts = list_login_vhosts(Context#context.user, peersock(ReqData)),
[I || I <- List, lists:member(pget(vhost, I), VHosts)].
filter_user(List, _ReqData, #context{user = User}) ->
@ -533,12 +538,12 @@ intersects(A, B) -> lists:any(fun(I) -> lists:member(I, B) end, A).
list_visible_vhosts(User = #user{tags = Tags}) ->
case is_monitor(Tags) of
true -> rabbit_vhost:list();
false -> list_login_vhosts(User)
false -> list_login_vhosts(User, undefined)
end.
list_login_vhosts(User) ->
list_login_vhosts(User, Sock) ->
[V || V <- rabbit_vhost:list(),
case catch rabbit_access_control:check_vhost_access(User, V) of
case catch rabbit_access_control:check_vhost_access(User, V, Sock) of
ok -> true;
_ -> false
end].