Stat Class
A lightweight component for gathering and emitting application statistics
This is both a collector and emitter for application stats.
It's designed with low development and runtime cost in mind, encouraging usage with minimum concern for overhead.
Stat Collector
As a collector, it's a place to send application stats as they're discovered.
Example for incrementing a stat in your application:
var stat = require('monitor').getStatLogger('myModule');
...
stat.increment('requests.inbound');
The above is a request to increment the myModule.requests.inbound
stat.
It peforms work only if someone is listening for that event.
Stat Emitter
As an emitter, Stat is a place to gather stats as they're collected.
When listening for stats, wildcards can be used to register for many stats within a group. For example, the following call:
var Stat = require('monitor').Stat;
Stat.on('myModule.*.timer', myFunction);
Will call myFunction
when all myModule.*.timer
stats are emitted.
Listeners are invoked with 4 arguments:
- module - The statLogger module name
- name - The name of the stat that just fired
- value - The numeric value passed
- type - An enumeration of the types of stats:
'c' - Counter. Add (or subtract) the value to (or from) the prior value
'g' - Gague. Value is to be recorded as provided
'ms' - Timer. Millisecond amount of time something took.
Wildcards
The following wildcards are allowed for registering events. They're modeled after the graphite wildcard syntax (from the graphite docs):
Delimiter
The period (.) character is literal, and matches name segment separators.
Asterisk
The asterisk (*) matches zero or more characters. It is non-greedy, so you can have more than one within a single path element.
Example: servers.ix*ehssvc*v.cpu.total.* will return all total CPU metrics for all servers matching the given name pattern.
An asterisk at the far right of the pattern matches everything to the right,
including all path segments. For example, servers.*
matches all
names beginning with servers.
.
Character list or range
Characters in square brackets ([...]) specify a single character position in the path string, and match if the character in that position matches one of the characters in the list or range.
A character range is indicated by 2 characters separated by a dash (-), and means that any character between those 2 characters (inclusive) will match. More than one range can be included within the square brackets, e.g. foo[a-z0-9]bar will match foopbar, foo7bar etc..
If the characters cannot be read as a range, they are treated as a list - any character in the list will match, e.g. foo[bc]ar will match foobar and foocar. If you want to include a dash (-) in your list, put it at the beginning or end, so it's not interpreted as a range.
Value list
Comma-separated values within curly braces ({foo,bar,...}) are treated as value lists, and match if any of the values matches the current point in the path. For example, servers.ix01ehssvc04v.cpu.total.{user,system,iowait} will match the user, system and I/O wait total CPU metrics for the specified server.
Javascript Regex
For finer grained expression matching, a javascript style regex can be
specified using the /.../
syntax. This style spans the entire identifier.
You can ignore case using the /.../i
syntax. If the first character of the
string is a slash, it considers the string a javascript regular expression.
Choosing Good Names
It's a good idea to pick a good naming scheme with each dot-delimited segment having a consistent, well-defined purpose. Volatile segments should be as deep into the hierarchy (furthest right) as possible. Keeping the names less volatile makes it easier to turn recording on for all statistics.
Constructor
Methods
_buildRegex
-
str
Build a regex from a user entered string following the pattern described in the class definition. Loosely:
If it looks like a JS regexp, process it as a regexp Change all '.' to '.' Change all '' to '[^.]' (unless it's at the end, then convert to '.*') Change all {one,two} to (one|two) Leave all [...] alone - they work as-is
If an error occurs, throw an exception
Parameters:
-
str
StringString to build the regular expression from
Returns:
decrement
-
name
-
[value=1]
Decrement a counter by a specified value
Assuming someone is listening to this stat, this is an instruction for that listener to subtract the specified value (usually 1) to their prior value for this stat.
This is known as server-side setting, as the server (listener) is responsible for maintaining the prior and new value for the stat.
gauge
-
name
-
value
Set the stat to the specified value
This is an instruction to any (all) listener(s) to set the stat to a specific value.
This is known as client-side setting, because the client determines the value of the stat.
increment
-
name
-
[value=1]
Increment a counter by a specified value
Assuming someone is listening to this stat, this is an instruction for that listener to add the specified value (usually 1) to their prior value for this stat.
This is known as server-side setting, as the server (listener) is responsible for maintaining the prior and new value for the stat.
time
-
name
-
duration
Record the specified duration (in milliseconds) for the stat
This is like Stat.gauge() in that it is a client-side setting of a specified value. The difference is the scale of the value is specified as milliseconds.
This may be one of the most widely used stat methods. It can (should?) be used upon callback from asynchronous methods.
Pattern:
var stat = require('monitor').getStatLogger('myModule');
...
var stamp = Date.now();
SomeAsyncFunction(arg1, function(error) {
stat.time('SomeAsyncFunction.time', Date.Now() - stamp);
...continue with error handling & callback handling
});
Parameters:
-
name
StringDot.separated name of the stat
-
duration
IntegerNumber of milliseconds this stat took to complete