[![Build Status](https://travis-ci.org/dmitrymatveev/librato-express.svg)](https://travis-ci.org/dmitrymatveev/librato-express)
[![Stories in Ready](https://badge.waffle.io/dmitrymatveev/librato-express.png?label=ready&title=Ready)](https://waffle.io/dmitrymatveev/librato-express)
[![Package Quality](http://npm.packagequality.com/shield/librato-express.svg)](http://packagequality.com/#?package=librato-express)

[![NPM](https://nodei.co/npm/librato-express.png)](https://nodei.co/npm/librato-express/)

# Librato Express
[Librato](https://www.librato.com/) metrics client.


This module provides methods to perform common operations for aggregating and sending metrics results to Librato backend.
It exposed [expressjs](http://expressjs.com/) middleware as well as gives direct access to underliyng metrics keeping classes.


#### Middleware example
```javascript
var metrics = require('librato-express');
var app = require( 'express' )();

// initialize with your librato credentials
metrics.initialise({
    email : 'libratouser@somemail.com',
    token : 'libratoGeneratedToken'
});

metrics.start();

// call metrics functions on desired routes
app.use('/', metrics.middleware.routeCount({name: 'route_visited'}));
app.use('/user', metrics.middleware.routeTiming({name: 'user_load_response_time'}));
```

#### Stand-alone example
```javascript
var metrics = require('librato-express');
var counter = new metrics.Counter({name: 'some_function_call'});

metrics.initialise({
    email : 'libratouser@somemail.com',
    token : 'libratoGeneratedToken'
});
metrics.start();

function doSomething () {
	counter.increment();
	...
}
```


## Documentation

#### Main

* [`Metrics.initialise`](#main)
* [`Metrics.flush`](#main)
* [`Metrics.start`](#main)
* [`Metrics.deleteAllMetrics`](#main)

#### Middleware

* [`Metrics.middleware.routeCount`](#routeCount)
* [`Metrics.middleware.routeTiming`](#routeTiming)

#### Metrics Classes

* [`Metrics.Counter`](#counter)
* [`Metrics.Timing`](#timing)

#### Annotations

* [`Metrics.Annotation`](#annotation)

#### Worker Classes

* [`Collector`](#collector)
* [`Transport`](#transport)

## Main

<a name="main" />

### Metrics.initialise(options)
Set-up librato-express module using this function. It should be called before anything else.

* `options.email` - Librato account email.
* `options.token` - Librato provided token.
* `options.period` - Minimum frequency of sending librato metrics. Defaults to 1 second.
* `options.prefix` - Prefix to be used with all metric names. Defaults to empty string.
* `options.source` - Global metrics source property. Default: os.hostname() value.

It is possible to replace default behaviour of librato-express by providing replacement implementation for the following two components.
* `options.collector` - [`Caching object`](#collector) responsible for temporary storing metrics
before sending those to Librato.
* `options.transport` - [`Https client`](#transport).

### Metrics.flush(callback)
Dumps accumulated data to Librato.

* `callback()` - callback function.

### Metrics.start()
Starts calling `metrics.flush()` function in a forever circle.

### Metrics.deleteAllMetrics( [callback] )
Deletes all metrics from Librato that start with `Base.options.prefix`. Note:
If prefix was not specified this method will delete __all__ metrics from the account.

* `[callback()]` - optional callback function.

## Middleware

<a name="routeCount" />

### Metrics.middleware.routeCount(options[, filter])

Creates middleware function that when invoked by express router will increment a metric with a specified name.

* `options.name` - Name of the metric for Librato. Note: `options.prefix`
will be applied to this value.
* `options.period` - Period of sending this metric to Librato. Defaults to Librato default period of 60 seconds.
* `options.source` - Librato source name for this metric.
* `options.ignoreNonDirty` - If set will prevent sending to Librato if this metric did not increment. Defaults to `true`.
* `options.alert` - Object describing custom alert definition. Note that this is not a [Librato Alert](http://dev.librato.com/v1/alerts).
	* `alert.trigger(metric)` - Function accepting metric object which is about to be sent to Librato. Must return a boolean value to trigger an alert hook.
	* `alert.handler(metric)` - This function will be called if trigger returned `true`.
* `filter` - This is a __postfix__ to apply to metric name. Can be either a
`string` or a
`function`.
	* _String_ - matches property in the `request` object for the route. It can be delimited with any non-word character to match property in the nested object. Note that no type checks are performed and is solely up to a client to make sure references are present.
	* _Function_ - will receive `request` object for the route and should return a string value representing a filter key.  Returned value of`null` will cause the filter to be ignored.

```javascript
// Make sure request object has 'userID' property.
app.param('userID', function (req, res, next, value) {
	req.userID = value;
});

// Will increment metric key of "count_visit_someUserID".
app.use('/', metrics.middleware.routeCount({name: 'visit'}), 'userID');

// Will increment metric key of "count_check_MY_FILTER".
app.use('/', .middleware.routeCount({name: 'check'}, function ( request ) {
	return 'MY_FILTER';
}));
```


<a name="routeTiming" />

### Metrics.middleware.routeTiming(options[, filter])

Same as [`routeCount`](#routeCount) but will aggregate the delay values into a [gauge specific parameters](http://dev.librato.com/v1/post/metrics) set.

Time will be sampled from the position of this function in the stack and untill `express.response.send` function is finished.

* count
* min
* max
* sum_squares

## Metrics Classes

These two objects can be used outside middleware to perform same tasks (in fact that is what middleware functions use under the hood).

<a name="counter" />

### Metrics.Counter(options)
Creates a new `Counter` object. `Options` are the same as in [`routeCount`](#routeCount)

#### increment([filter])
Increment counter value.
* `filter` - Optional string value to append to metric name key.

#### deleteMetrics()
Deletes all metrics from Librato that start with the name of this metric
class instance.

<a name="timing" />

### Metrics.Timing(options)
Creates a new `Timing` object. `Options` are the same as in [`routeCount`](#routeCount)

#### measure(time[, filter])
Increment counter value.
* `time` - Time in the past to take the measurement from.
* `filter` - Same as in `Counter.increment`.

#### deleteMetrics()
Same as `Counter.deleteMetrics`.


## Annotations

<a name="annotation" />

### Metrics.Annotation(stream, options)
***

Creates new [annotation](http://dev.librato.com/v1/annotations) object assigned to a specific stream.

* `stream` - Name of the stream.
* `options.title` - Title of this annotation. Defaults to name of the stream.
* `options.source` - An optional name of the source for this annotation.
* `options.description` - An optional description.
* `options.links` - Optional list of [links](http://dev.librato.com/v1/post/annotations/:name/:id/links) for this annotation.


```javascript
var metrics = require('librato-express');
...

var ann = new metrics.Annotation('some-annotation-stream', {
	title : 'my-annotation',
	links : [{rel: 'librato', href: 'http://dev.librato.com/v1/annotations'}]
});
ann.post();

setTimeout(function () {
	ann.post(); // Lets POST re-occurring instance of this event
}, 300000);

var other = new metrics.Annotation('some-annotation-stream', {title : 'my-other-annotation'});
other.startMs(Date.now()-300000); // It actually occurred 5 minutes ago ;)
other.endMs(); // And lasted until now
other.post();
```

#### startMs([time])
Sets start time for the next occurrence of annotation. Returns [unix timestamp](http://en.wikipedia.org/wiki/Unix_time) which will be sent to Librato.

* `time` - Optional time in milliseconds. This will be converted into unix timestamp.

#### endMs([time])
Same as `startMs`.

#### post([callback])
Posts annotation to Librato. `Start` and `end` timestamps are cleared immediately after this operation.

## Worker Classes

These workers encapsulate 'behind the scenes' algorithms for the main functionality of the module. It is possible to implement custom strategies and replace default behaviour while initialising librato-express.

<a name="collector" />

### Collector()
***

Provides routines to temporary store and process metrics before sending to
Librato.

#### count(key, filter, callback)
Increment count values.

* `key` - name of Librato metric.
* `filter` - filter to apply to name.
* `callback()` - callback function.

#### timing(key, duration, filter, callback)
Add to duration values.

* `key` - name of Librato metric.
* `duration` - next duration to log.
* `filter` - filter to apply to name.
* `callback()` - callback function.

#### flush(callback)
Dump accumulated data.

* `callback({})` - Call this when finished with the metrics data object. Note: librato-express will ignore if `null` and `undefined` values.


<a name="transport" />

### Transport(options)
***

Simple HTTPS client to send data over network.

* `options.email` - Librato account email.
* `options.token` - Librato provided token.
* `options.silent` - Flag to never pass connection information to callee.

#### postMetrics(metric[, callback])
Send metric data to librato.

* `metric` - Actual data to send.
* `callback([err])` - optional callback function.

#### deleteMetrics(names[, callback])
Delete metrics from librato.

* `names` - list of name strings to send.
* `callback([err])` - optional callback function.

#### postAnnotation(stream, data[, callback])
Posts annotation.

* `stream` - name of the stream to POST into.
* `data` - annotation body.
* `callback([err])` - optional callback function