prom-client returning empty object for default metrics in NodeJS application

5.2k views Asked by At

I have a NodeJS application, and I want to expose the default metrics. I have the following implementation. I am using the prom-client package.

let express = require('express');
let app = express();

const client = require('prom-client');

// Create a Registry which registers the metrics
const register = new client.Registry()

// Add a default label which is added to all metrics
register.setDefaultLabels({
    app: 'example-nodejs-app'
})

// Enable the collection of default metrics
client.collectDefaultMetrics({ register })

app.get('/metrics', function (req, res) {
    // Return all metrics the Prometheus exposition format
    res.set('Content-Type', register.contentType)
    res.send(register.metrics())
})

let server = app.listen(8080, function () {
    let port = server.address().port
    console.log("Application running on port: %s", port)
})

When I navigate to http://localhost:8080/metrics, I get an empty object ({}) as a response. When I check my Prometheus Targets, I see the following error.

"INVALID" is not a valid start token

enter image description here

I am newly using the prom-client from npm. How can I make this work?

2

There are 2 answers

0
Keet Sugathadasa On BEST ANSWER

Found out the issue. What you need to realize is, register.metrics() returns a promise. Hence, using await register.metrics() will return the expected response for default metrics. The updated code snippet is given below.

let express = require('express');
let app = express();

const client = require('prom-client');

// Create a Registry which registers the metrics
const register = new client.Registry()

// Add a default label which is added to all metrics
register.setDefaultLabels({
    app: 'example-nodejs-app'
})

// Enable the collection of default metrics
client.collectDefaultMetrics({ register })

app.get('/metrics', async function (req, res) {
    // Return all metrics the Prometheus exposition format
    res.set('Content-Type', register.contentType);
    let metrics = await register.metrics();
    res.send(metrics);
})

let server = app.listen(8080, function () {
    let port = server.address().port
    console.log("Application running on port: %s", port)
})

Now, navigate to http://localhost:8080/metrics in your browser and see the default metrics.

2
Michael Hausenblas On

As far as I can tell from your code, you are missing two non-optional things to make it work: 1. define a metric, 2. update it (for example, increase a counter metric).

Something along the line of:

  1. Metric definition:
const acounter = new prom.Counter({
  name: 'my_counter_total',
  help: 'The number of things I want to count'
});
  1. Metric update (on whatever URL path, query or method you want/need to):
app.get('/moar', function (req, res) {
  acounter.inc();
})