Metrics

mbostock edited this page Apr 17, 2012 · 4 revisions

WikiAPI ReferenceEvaluatorMetrics

Metrics are a way of identifying events of interest, grouping them into bins, and reducing them to a single value. For example, given a set of "request" events, you might want to compute the number of requests in each five-minute interval over the last week. This metric, sum(request) tells you the rate of requests over time. For more details on how to define metrics, see the documentation on metric expressions.

Metrics are computed by the evaluator, via the metric/get endpoint. This endpoint returns an array of JSON-encoded metric values, which have two required properties:

  • time - the metric time, in ISO 8601 format, UTC.
  • value - the metric value; a number, or undefined or NaN.

If you use the HTTP GET endpoint, the metrics are returned in chronological order. For example:

[
  {"time": "2012-04-16T16:00:00.000Z", "value": 20},
  {"time": "2012-04-16T16:01:00.000Z", "value": 21},
  {"time": "2012-04-16T16:02:00.000Z", "value": 20},
  {"time": "2012-04-16T16:03:00.000Z", "value": 20},
  {"time": "2012-04-16T16:04:00.000Z", "value": 21},
  {"time": "2012-04-16T16:05:00.000Z", "value": 20},
  {"time": "2012-04-16T16:06:00.000Z", "value": 21},
  {"time": "2012-04-16T16:07:00.000Z", "value": 20},
  {"time": "2012-04-16T16:08:00.000Z", "value": 20},
  {"time": "2012-04-16T16:09:00.000Z", "value": 21},
  {"time": "2012-04-16T16:10:00.000Z", "value": 21}
]

However, if you use the WebSockets endpoint, the metrics are returned in arbitrary order, so as to give you results as quickly as possible; if some of the metrics are cached, they will be returned immediately even while Cube computes the non-cached metrics.

If you use the WebSockets endpoint, you can multiplex requests on the same socket by using a request id. For example, to get both cube_request and cube_compute metrics simultaneously:

var socket = new WebSocket("ws://localhost:1081/1.0/metric/get");

socket.onopen = function() {
  socket.send(JSON.stringify({
    "expression": "sum(cube_request)",
    "start": "2012-04-16T16:00:00Z",
    "stop": "2012-04-16T17:00:00Z",
    "step": 6e4,
    "id": "request"
  }));
  socket.send(JSON.stringify({
    "expression": "sum(cube_compute)",
    "start": "2012-04-16T16:00:00Z",
    "stop": "2012-04-16T17:00:00Z",
    "step": 6e4,
    "id": "compute"
  }));
};

socket.onmessage = function(message) {
  console.log(JSON.parse(message.data));
};

Of course, you may find it simpler to just open multiple WebSockets, rather than multiplex.

Internal Storage

Cached metrics for are typically stored in capped collections; by default, Cube creates a 10M capped collection for each event type. Metrics are indexed by expression, time, and resolution. In addition, the "i" (invalid) flag records whether a cached metric has been invalidated by the collector; these invalidated metrics are ignored by the evaluator, causing metrics to be recomputed when new events arrive.

{
  "_id" : {
    "e": "sum(cube_request)",
    "l": 10000,
    "t": ISODate("2012-04-15T18:25:30Z")
  },
  "i": false,
  "v": 4
}

To save space, Cube does not cache metrics with falsey values (zero, undefined or NaN). With sporadic events, this can trigger multiple queries for events; however, since queries are indexed by time, it is relatively fast to detect zero results for a particular time range.