aioriemann 1.0.0a1
async/await client for Riemann
License: MIT
Keywords: infrastructure,asyncio,service discovery,health checking,key/value store

AIO Riemann
===========

This is a client for Riemann_ build on top of async/await syntax.
It supports TCP, UDP and TLS connections.


Installation
------------

::

    pip install aioriemann


Working with client
-------------------

Now that AIORiemann is installed, let's try sending some of our own states
through the client::

    >>> from aioriemann import Riemann
    >>> client = Riemann()

We can send events with ``send()``. For example, let's log an HTTP request::

    >>> await client.send({
    ...   "host": "www1",
    ...   "service": "http req",
    ...   "metric": 2.53,
    ...   "state": "critical",
    ...   "description": "Request took 2.53 seconds.",
    ...   "tags": ["http"]
    ... })

On the dashboard, critical events (like the one we just submitted) show up in
red. All of these fields are optional, by the way. The client will assume your
events come from the local host name unless you pass ``host=None``.

Now let's ask for all events that have a service beginning with "http"::

    >>> await client.query('service =~ "http%"')
    [
        {
            "timestamp": 1330041937,
            "state": "critical",
            "service": "http req",
            "host": "www1",
            "description": "Request took 2.53 seconds.",
            "tags": ["http"],
            "ttl": 300.0,
            "metric": 2.5299999713897705
        }
    ]

There's the event we submitted.

**query()** and **send()** are wrapped in asyncio.Task. so it means that
they are scheduled automatically event without ``await`` keyword::

    >>> client.send({
    ...   "host": "www1",
    ...   "service": "http req",
    ...   "metric": 2.53,
    ...   "state": "critical",
    ...   "description": "Request took 2.53 seconds.",
    ...   "tags": ["http"]
    ... }).add_done_callback(func)
    >>> client.query('service =~ "http%"').add_done_callback(func)

And later call **join()** to ensure that tasks have been done::

    >>> await client.join()


Specifications
--------------

A TCP connection to Riemann is a stream of messages. Each message is a 4 byte
network-endian integer *length*, followed by a Protocol Buffer Message of
*length* bytes. See the `protocol buffer definition`_ for the details.

Over UDP, the length header is omitted; just send the protobuf Message directly.
UDP datagrams have a default maximum size of 16384 bytes by Riemann's default;
larger messages should go over TCP. This limit is configurable in both the
client and server; client values *must* be smaller than the server's.

The server will accept a repeated list of Events, and respond with a
confirmation message with either an acknowledgement or an error. Check the ok
boolean in the message; if false, message.error will be a descriptive string.

Because protocol buffers is a strongly typed protocol, the metric of an event
is represented as one of metric_d (floating point 64-bit), metric_f (floating
point 32-bit), or metric_sint64 (64-bit signed integer). Your client should
emit and consume all of these types. For compatibility with older versions of
Riemann, you may *also* emit a metric_f alongside the normal type; newer
versions of Riemann will prefer the higher-resolution types.

Events are uniquely identified by host and service. Both allow null. Event.time
is the time in unix epoch seconds and is optional. The server will generate a
time for each event when received if you do not provide one. I don't need time
resolution finer than 1 second presently, but if you do, my plan is to add a
nanosecond field as well.

You can also query events from the index using a basic query language. Just
submit a Message with your query in message.query.string. Search queries will
return a message with repeated Events matching that expression. A null
expression will return no states. For some example queries, see
`The query test suite`_.

You might find it useful to read the `Ruby client`_ source as a guide to
writing your own client.


Reading list
------------

* Realtime cluster monitoring with docker swarm and riemann:
  https://blog.docker.com/2016/03/realtime-cluster-monitoring-docker-swarm-riemann/

.. _Riemann: http://riemann.io
.. _`protocol buffer definition`: https://github.com/riemann/riemann-java-client/blob/master/riemann-java-client/src/main/proto/riemann/proto.proto
.. _`The query test suite`: https://github.com/riemann/riemann/blob/master/test/riemann/query_test.clj
.. _`Ruby client`: https://github.com/riemann/riemann-ruby-client