delete stats via management console: move to lib/, docs, generalize, tests

This commit is contained in:
Jason Carver 2013-02-25 22:09:26 -08:00 коммит произвёл Jason Carver
Родитель d07b90ed67
Коммит 2d9b0de787
3 изменённых файлов: 137 добавлений и 48 удалений

68
lib/mgmt_console.js Normal file
Просмотреть файл

@ -0,0 +1,68 @@
/**
* delete_stats - delete all matching statistics
*
* Side effect notes: this function works by altering stats_type in place,
* and calls stream.write(str) to display user feedback.
*
* @param stats_type array of all statistics of this type (eg~ timers) to delete from
* @param cmdline array of all requested deletions, which can be fully qualified,
* or end in a .* to delete a folder, like stats.temp.*
* @param stream buffer output for for all outgoing user feedback
*/
exports.delete_stats = function(stats_type, cmdline, stream) {
//for each metric requested on the command line
for (var index in cmdline) {
//get a list of deletable metrics that match the request
deletable = existing_stats(stats_type, cmdline[index]);
//warn if no matches
if (deletable.length == 0) {
stream.write("metric " + cmdline[index] + " not found\n");
}
//delete all requested metrics
for (var del_idx in deletable) {
delete stats_type[deletable[del_idx]];
stream.write("deleted: " + deletable[del_idx] + "\n");
}
}
stream.write("END\n\n");
}
/**
* existing_stats - find fully qualified matches for the requested stats bucket
*
* @param stats_type array of all statistics of this type (eg~ timers) to match
* @param bucket string to search on, which can be fully qualified,
* or end in a .* to search for a folder, like stats.temp.*
*
* @return array of fully qualified stats that match the specified bucket. if
* no matches, an empty array is a valid response
*/
function existing_stats(stats_type, bucket){
matches = []
//typical case: one-off, fully qualified
if (bucket in stats_type) {
matches.push(bucket);
}
//special case: match a whole 'folder' (and subfolders) of stats
if (bucket.slice(-2) == ".*") {
var folder = bucket.slice(0,-1);
for (var name in stats_type) {
//check if stat is in bucket, ie~ name starts with folder
if (name.substring(0, folder.length) == folder) {
matches.push(name);
}
}
}
return matches;
}
exports.existing_stats = existing_stats;

Просмотреть файл

@ -7,6 +7,7 @@ var dgram = require('dgram')
, logger = require('./lib/logger')
, set = require('./lib/set')
, pm = require('./lib/process_metrics')
, mgmt = require('./lib/mgmt_console')
// initialize data structures with defaults for statsd stats
@ -131,51 +132,6 @@ var stats = {
// Global for the logger
var l;
function delete_stats(stats_type, cmdline, stream) {
//for each metric requested on the command line
for (var index in cmdline) {
//get a list of deletable metrics that match the request
deletable = stats_to_delete(stats_type, cmdline[index]);
//warn if no matches
if (deletable.length == 0) {
stream.write("metric " + cmdline[index] + " not found\n");
}
//delete all requested metrics
for (var del_idx in deletable) {
delete stats_type[deletable[del_idx]];
stream.write("deleted: " + deletable[del_idx] + "\n");
}
}
stream.write("END\n\n");
}
function stats_to_delete(stats_type, bucket){
deletable = []
//typical case: one-off deletion
if (bucket in stats_type) {
deletable.push(bucket);
}
//special case: delete a whole 'folder' (and subfolders) of stats
if (bucket.slice(-2) == ".*") {
var folder = bucket.slice(0,-1);
for (var name in stats_type) {
//check if stat is in bucket, ie~ name starts with folder
if (name.substring(0, folder.length) == folder) {
deletable.push(name);
}
}
}
return deletable;
}
config.configFile(process.argv[2], function (config, oldConfig) {
conf = config;
l = new logger.Logger(config.log || {});
@ -352,15 +308,15 @@ config.configFile(process.argv[2], function (config, oldConfig) {
break;
case "delcounters":
delete_stats(counters, cmdline, stream);
mgmt.delete_stats(counters, cmdline, stream);
break;
case "deltimers":
delete_stats(timers, cmdline, stream);
mgmt.delete_stats(timers, cmdline, stream);
break;
case "delgauges":
delete_stats(gauges, cmdline, stream);
mgmt.delete_stats(gauges, cmdline, stream);
break;
case "quit":

Просмотреть файл

@ -0,0 +1,65 @@
var mgmt = require('../lib/mgmt_console');
module.exports = {
stat_matches: function(test) {
test.expect(8);
stat_vertical = {'a.b':1,'a.c':1,'c':1};
//test function
f = function (bucket) { return mgmt.existing_stats(stat_vertical, bucket) }
//empties
test.deepEqual(f('d'), []);
test.deepEqual(f('a'), []);
test.deepEqual(f('c.a'), []);
test.deepEqual(f('c.*'), []);
test.deepEqual(f(''), []);
//single matches
test.deepEqual(f('a.b'), ['a.b']);
test.deepEqual(f('c'), ['c']);
//multiple matches
test.deepEqual(f('a.*'), ['a.b', 'a.c']);
test.done();
},
stat_deletes: function(test) {
test.expect(6);
var stream = {
buffer : '',
clear : function() { this.buffer = '' },
write : function(to_write) { this.buffer += to_write },
};
stats_fixture =
//delete missing
stat_vertical = {'a.b':1,'a.c':1,'d':1};
stream.clear();
mgmt.delete_stats(stat_vertical, ['e'], stream);
test.deepEqual(stat_vertical, stats_fixture);
test.equal(stream.buffer, 'metric e not found\nEND\n\n');
//delete fully qualified
stat_vertical = {'a.b':1,'a.c':1,'d':1};
stream.clear();
mgmt.delete_stats(stat_vertical, ['a.b'], stream);
test.deepEqual(stat_vertical, {'a.c':1,'d':1});
test.equal(stream.buffer, 'deleted: a.b\nEND\n\n');
//delete folder
stat_vertical = {'a.b':1,'a.c':1,'d':1};
stream.clear();
mgmt.delete_stats(stat_vertical, ['a.*'], stream);
test.deepEqual(stat_vertical, {'d':1});
test.equal(stream.buffer, 'deleted: a.b\ndeleted: a.c\nEND\n\n');
test.done();
},
}