Metrics
=======
.. module:: vumi.blinkenlights.metrics
Metrics are a means for workers to publish statistics about their
operations for real-time plotting and later analysis. Vumi provides
built-in support for publishing metric values to Carbon (the storage
engine used by `Graphite`_).
Using metrics from a worker
---------------------------
The set of metrics a worker wishes to plublish are managed via a
:class:`MetricManager` instance. The manager acts both as a container
for the set of metrics and the publisher that pushes metric values out
via AMQP.
Example::
class MyWorker(Worker):
def startWorker(self, config):
self.metrics = yield self.start_publisher(MetricManager,
"myworker.")
self.metrics.register(Metric("a.value"))
self.metrics.register(Count("a.count"))
In the example above a :class:`MetricManager` publisher is
started. All its metric names with be prefixed with `myworker.`. Two
metrics are registered -- `a.value` whose values will be averaged and
`a.count` whose values will be summed. Later, the worker may set the
metric values like so::
self.metrics["a.value"].set(1.23)
self.metrics["a.count"].inc()
.. autoclass:: MetricManager
:members:
Metrics
-------
A :class:`Metric` object publishes floating point values under a
metric `name`. The name is created by combining the `prefix` from a
metric manager with the `suffix` provided when the metric is
constructed. A metric may only be registered with a single
:class:`MetricManager`.
When a metric value is `set` the value is stored in an internal list
until the :class:`MetricManager` polls the metric for values and
publishes them.
A metric includes a list of aggregation functions to request that
the metric aggregation workers apply (see later sections). Each metric
class has a default list of aggregators but this may be overridden when
a metric is created.
.. autoclass:: Metric
:members:
.. autoclass:: Count
:members:
:show-inheritance:
.. autoclass:: Timer
:members:
:show-inheritance:
Aggregation functions
---------------------
Metrics declare which aggregation functions they wish to have applied
but the actual aggregation is performed by aggregation workers. All
values sent during an aggregation interval are aggregated into a
single new value.
Aggregation fulfils two primary purposes:
* To combine metrics from multiple workers into a single aggregated
value (e.g. to determine the average time taken or total number of
requests processed across multiple works).
* To produce metric values at fixed time intervals (as is commonly
required by metric storage backends such as `Graphite`_ and `RRD Tool
`_).
The aggregation functions currently available are:
* :const:`SUM` -- returns the sum of the supplied values.
* :const:`AVG` -- returns the arithmetic mean of the supplied values.
* :const:`MIN` -- returns the minimum value.
* :const:`MAX` -- returns the maximum value.
All aggregation functions return the value 0.0 if there are no values
to aggregate.
New aggregators may be created by instantiating the :class:`Aggregator`
class.
.. note::
The aggregator must be instantiated in both the process that
generates the metric (usually a worker) and the process that
performs the aggregation (usually an aggregation worker).
.. autoclass:: Aggregator
:members:
Metrics aggregation system
--------------------------
The metric aggregation system consists of :class:`MetricTimeBucket`
and :class:`MetricAggregator` workers.
The :class:`MetricTimeBucket` workers pull metrics messages from the
`vumi.metrics` exchange and publish them on the `vumi.metrics.buckets`
exchange under a routing key specific to the :class:`MetricAggregator`
which should process them. Once sufficient time has passed for all
metrics for a specific time period (a.k.a. time bucket) to have
arrived at the aggregator, the requested aggregation functions are
applied and the resulting aggregated metrics are published to the
`vumi.metrics.aggregates` exchange.
A typical metric aggregation setup might consist of the following
workers:
* 2 :class:`MetricTimeBucket` workers
* 3 :class:`MetricAggregator` workers
* a final metric collector, e.g. :class:`GraphiteMetricsCollector`.
A shell script to start-up such a setup might be::
#!/bin/bash
BUCKET_OPTS="--worker_class=vumi.workers.blinkenlights.metrics.\
MetricTimeBucket --set-option=buckets:3 --set-option=bucket_size:5"
AGGREGATOR_OPTS="--worker_class=vumi.workers.blinkenlights.metrics.\
MetricAggregator --set-option=bucket_size:5"
GRAPHITE_OPTS="--worker_class=vumi.workers.blinkenlights.metrics.\
GraphiteMetricsCollector"
twistd -n start_worker $BUCKET_OPTS &
twistd -n start_worker $BUCKET_OPTS &
twistd -n start_worker $AGGREGATOR_OPTS --set-option=bucket:0 &
twistd -n start_worker $AGGREGATOR_OPTS --set-option=bucket:1 &
twistd -n start_worker $AGGREGATOR_OPTS --set-option=bucket:2 &
twistd -n start_worker $GRAPHITE_OPTS &
Publishing to Graphite
----------------------
The :class:`GraphiteMetricsCollector` collects aggregate metrics
(produced by the metrics aggregators) and publishes them to Carbon
(Graphite's metric collection package) over AMQP.
You can read about installing a configuring Graphite at
``_ but at the very least you will have to enable
AMQP support by setting::
[cache]
ENABLE_AMQP = True
AMQP_METRIC_NAME_IN_BODY = False
in Carbon's configuration file.
If you have the metric aggregation system configured as in the section
above you can start Carbon cache using::
carbon-cache.py --config --debug start
.. _Graphite: http://graphite.wikidot.com/