Coder Social home page Coder Social logo

node-epimetheus's Introduction

Epimetheus

CircleCI Coveralls David

NPM

Middleware to automatically instrument node applications for consumption by a Prometheus server.

Prometheus is an open source monitoring solution that obtains metrics from servers by querying against the /metrics endpoint upon them.

Once instrumented, Epimetheus automatically serves response duration metrics, plus nodejs system metrics on the /metrics endpoint ready to be consumed by Prometheus.

Epimetheus will instrument websites and webservices that use http, express, hapi and restify.

Instrumentation

Epimetheus automatically measures a number of metrics once instrumented. The following metrics are instrumented via the /metrics endpoint:

Duration Metrics

There are two metrics measuring request duration:

  • http_request_duration_milliseconds (summary): a summary metric measuring the duration in milliseconds of all requests. It can be used to calculate average request durations.
  • http_request_buckets_milliseconds (histogram): a histogram metric used to count duration in buckets of sizes 500ms and 2000ms. This can be used to calculate apdex using a response time threshold of 500ms.

In each case, the following labels are used:

  • status: the http status code of the response, e.g. 200, 500
  • method: the http method of the request, e.g. put, post.
  • path: the path of the request. Note that /users/freddie is labelled /users/ so as not to flood prometheus with labels
  • cardinality: the cardinality of the request, e.g. /users/freddie has cardinality 'one', /users/ has cardinality 'many'

System Metrics

These are metrics provided by prom-client that instrument the nodejs heap/rss usage and cpu usage etc.

Installation

> npm install --save epimetheus

Epimetheus has only one method, instrument, and it has the following signature:

instrument(server, options)

The first argument represents the server of the middleware.

The second argument is optional, and allows some configuration of epimetheus

  • url - the url on which to serve metrics. Defaults to /metrics.

See the following examples of use with http, express, hapi and restify.

http

const http = require('http');
const epimetheus = require('../../index');

const server = http.createServer((req, res) => {
  if(req.url !== '/metrics') {
    res.statusCode = 200;
    res.end();
  }
});

epimetheus.instrument(server);

server.listen(8003, '127.0.0.1', () => {
  console.log('http listening on 8003');
});

Express

const express = require('express');
const epimetheus = require('epimetheus');

const app = express();
epimetheus.instrument(app);

app.get('/', (req, res) => {
  res.send();
});

app.listen(3000, () => {
  console.log('express server listening on port 3000');
});

Hapi

const Hapi = require('hapi');
const epimetheus = require('epimetheus');

const server = new Hapi.Server();

server.connection({
  port: 3000
});

epimetheus.instrument(this.server);

server.route({
  method: 'GET',
  path: '/',
  handler: (req, resp) => {
    resp();
  }
});

server.start(() => {
  console.log('hapi server listening on port 3000');
});

Restify

const restify = require('restify');
const epimetheus = require('epimetheus');

const server = restify.createServer();

epimetheus.instrument(this.server);

server.get('/', (req, res, done) => {
  res.send();
  done();
});

server.listen(3000, () => {
  console.log('restify server listening on port 3000');
});

Try It Out

The docker-compose.yml file in the examples directory will create a prometheus server and an example each of an http, express, hapi and restify server.

Assuming you have installed docker and docker-compose, you can try it out by doing the following:

> cd examples
> docker-compose up

You can then view the prometheus server on http://127.0.0.1:9090

Etymology

Epimetheus

Epimetheus was one of the Titans and the brother of Prometheus His name is derived from the Greek word meaning 'afterthought', which is the antonym of his brother's name, Prometheus, meaning 'forethought'.

node-epimetheus's People

Contributors

accnops avatar analytik avatar andyroyle avatar btav avatar daviddias avatar matteo-hertel avatar roylines avatar spathon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

node-epimetheus's Issues

Express instrumentable appears to be wrong

server.name is actually 'app'

node examples/express/express.js 
express listening on 8000
/Users/mfang/mysource/nmlv-networth/node_modules/epimetheus/lib/restify.js:7
    metrics.observe(request.method, request.path(), response.statusCode, start);

prom-client version

It appears that this library is incompatible with latest version of prom-client (well, it's documented only in package.json and there is no explanation in the commit that sets it to < 7 ( c2b7412). Let's determine what is the issue with latest prom-client (v9.1.0) and see how it can be fixed.

Is epimetheus still actively supported ?

looks like no code changes have been submitted since more than a year ago, there is no support for Hapi v17 even when there is a PR with support waiting to be merged. Is this project still active ? is there any other alternative in case this one is dead on the water ?

thanks

/metrics endpoint throws 404

Using epimetheus v1.0.55 with hapi 16.6.3 but /metrics endpoint is not really getting exposed, got a 404. Is this expected ?

const Hapi = require('hapi');
const epithemeus = require('epimetheus');

const server = new Hapi.Server();
const connection = server.connection({ port: 8080, labels: ['api'] });
epithemeus.instrument(server);

.........

// routes
connection.route({
    method: 'GET',
    path: '/',
    handler: (request, reply) => { reply(); },
});

connection.route({
    method: 'GET',
    path: '/flags',
    handler: (request, reply) => { reply(featureFlag.listFlags()); },
});

connection.route({
    method: 'POST',
    path: '/foo',
    handler: foo,
});

Make prom-client a peer dependency

To make it easier to add additional metrics from outside this module it would be good if this module like eg. https://github.com/SimenB/node-prometheus-gc-stats added prom-client as a peer-dependency rather than as an ordinary dependency.

Reason for doing so is that it is important that all modules that interacts with the prom-client module are interacting with the same instance of the module and this will only happen if they all require the same installed modules โ€“ and the only way to really guarantee that is to have all modules require the dependency of the top project.

With the current setup there will be multiple instances of prom-client if the different modules have different version requirements from prom-client or if someone uses npm 2 or for some other reason doesn't flatten the dependency tree.

Cannot read property 'statusCode' of null

From time to time we see this error in our logs:

Debug: internal, implementation, error 
    TypeError: Cannot read property 'statusCode' of null
    at server.on (..../node_modules/epimetheus/lib/hapi.js:23:74)

As this happens intermittently I am suspecting this happens when the client closed the connection prematurely. The Hapi docs state:

response - the response object when set. The object can be modified but must not be assigned another object. To replace the response with another from within an extension point, use reply(response) to override with a different response. Contains null when no response has been set (e.g. when a request terminates prematurely when the client disconnects).

Is it possible to account for null responses?

http_* metrics

It seems like the metrics exposed right now do not adhere to best-practice. I'd like to discuss this before proposing any changes :)

Incompatible with supertest

When this module is enabled following the instructions for Express the tests that my team has written using supertest begin to hang. The interesting thing is that it hangs after the tests have run (as if something is locking), and before the coverage is reported.

Listen on separate port

To avoid exposing the metrics to anyone accessing the site, it would be nice to be able to instrument the server without adding the /metrics route to it.

node_* metrics

As prometheus-gc-stats as well as prom-client use nodejs_*, and node exporter owns the node_* namespace, it's probably a good idea to rename node_* to nodejs_*.

Crash when reading metrics endpoint

Good morning, I tried running the hapi example and got the following error on startup:

hapi server listening on port 8002
Debug: internal, implementation, error
    TypeError: Uncaught error: undefined is not a function
    at Array.map (native)
    at Object.Registry.metrics (/Users/peajo07/projects/demos/prom/node/node_modules/prom-client/lib/registry.js:52:5)
    at Object.summary (/Users/peajo07/projects/demos/prom/node/node_modules/prom-client/lib/register.js:15:13)
    at handler (/Users/peajo07/projects/demos/prom/node/node_modules/epimetheus/lib/hapi.js:10:42)
    at Object.internals.handler (/Users/peajo07/projects/demos/prom/node/node_modules/hapi/lib/handler.js:99:36)
    at request._protect.run (/Users/peajo07/projects/demos/prom/node/node_modules/hapi/lib/handler.js:30:23)
    at module.exports.internals.Protect.internals.Protect.run (/Users/peajo07/projects/demos/prom/node/node_modules/hapi/lib/protect.js:59:12)
    at exports.execute (/Users/peajo07/projects/demos/prom/node/node_modules/hapi/lib/handler.js:24:22)
    at each (/Users/peajo07/projects/demos/prom/node/node_modules/hapi/lib/request.js:382:16)
    at iterate (/Users/peajo07/projects/demos/prom/node/node_modules/items/lib/index.js:36:13)

Any idea what I'm doing wrong?

thanks,
Jake

Hapi v17 Support

Overview

If you are not aware yet, Hapi v17 is making the transition from callbacks to async/await, as well as deprecating some other rarely used functionality. This is a breaking change that may make your plugin no longer compatible with the Hapi API.

Changelog

Draft release notes can be found here: hapijs/hapi#3658

Target Release

The target release date for v17 is the beginning of November.

Tasks

  • Reply to this to acknowledge that you are actively maintaining this module and are willing to update it
  • Update plugin to be fully async/await compatible using the v17 branch from Hapi for testing

    Possible dev flow for updating

    • Clone Hapi
    • npm link within the Hapi repo
    • npm link hapi within your plugin repo
    • Your plugin will now be using v17 of Hapi branch for tests
  • Release new major version of your plugin on npm. Please use a major version increment as this will be a breaking change and it would be terrible for it to sneak into current versions of Hapi.

Notes

  • Support is being dropped for all versions of Node <8.0.0.
  • Hapi v16 will continue to be supported for as long as there exists a Node LTS actively being supported that is not compatible with v17.
  • Targeted release date is November 1st, 2017. Please try to have your plugin updated before then.
  • This issue is being opened because your plugin is listed on the official hapi website

Smarter path label flooding avoidance

@diasdavid and I have a little service running that we instrument with epimetheus. There's two little issues:

  • Every possible request coming from the internet is counted, e.g. path="/phpmyadmin" or path="/wp-login.php"
  • We have only one route, which is at the root and parameterized (/{email}). Every possible parameter is counted, e.g. path="/[email protected]" and path="/[email protected]".

I'd propose using request.route.path instead of the actual path, which would end up as e.g. a path="/{email}" label. If the route is undefined, we'd fall back to path="".

We're using HAPI here, and I'm not sure whether the other server libraries expose the route of a request.

Normalizing path in Express

Hi,

First of all, thanks for this neat library! It helped me get a kick start with exporting metrics to Prometheus.

However, in our projects, we often use parameters in Express routes, and these paths don't get normalized right now, so for example if you have a route like /user/:userId and then people make requests to /user/milan and /user/milan123, this creates new labels in Prometheus, which I gather is an antipattern - it works well only for a limited number of labels.

I'm currently working around it by not reporting path at all, and putting hostname there instead, as we run a bunch of microservices, so that's more useful for us. Not sure if this is a very common use case.

Any thoughts? I don't expect you to solve our problems of course :D Was just wondering if you encountered this; I'll hopefully prioritize this and work on getting it fixed in the next few days or weeks.

Memory leak

I implemented this in a project a couple weeks ago and started seeing gradual increases in memory usage. After doing a little digging I found that this package seemed to be causing a memory leak that eventually crashes the server. Have you experienced this before or seen any other cases of this happening?

I am using a pretty standard implementation of the package, and I am using it alongside prom-client which is also a very standard implementation. The only extra configuration is that the metrics are being served off of a specific port and from a different url than the default /metrics route.

Environment

Node: 6.10.0
NPM: 3.10.0
prom-client: 9.1.0
epimetheus: 1.0.46

Any leads or suggestions would be much appreciated. Thanks!

error in promtheus config

I cloned the repo and ran docker-compose up in the example dir and got this error:

prometheus_1  | time="2017-08-29T05:36:56Z" level=error msg="Error loading config: couldn't load configuration (-config.file=/etc/prometheus/prometheus.yml): unknown fields in scrape_config: target_groups" source="main.go:160"

I will investigate and report back.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.