Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: How do I configure a different port for the metrics #25

Closed
poteirard opened this issue Jan 8, 2019 · 8 comments · Fixed by #101
Closed

Question: How do I configure a different port for the metrics #25

poteirard opened this issue Jan 8, 2019 · 8 comments · Fixed by #101

Comments

@poteirard
Copy link

Hello ! First of all thank you for you amazing work on this repo :)

In my company we are using Prometheus for all the java projects and I wanted to achieve the same for our node servers as well.

All the endpoints of metrics however has to be in a specific port (different from the app server). Something like my-url.com:9000/metrics.

Is it possible to achieve that with this repo?

Thank you :)

@goooseman
Copy link

It is not so obvious, because this middleware attaches to express, which is listening on one of the ports. Middleware can not expose itself to a different port. This can not be solved by extending the API of this library, but can be done on the integration side in your code.

To solve this issue, we need one more express app, which has only /metrics endpoint. But we need to register statistics from our main express app. In the end I came up with the following:

const express = require("express");
const promBundle = require("express-prom-bundle");

const metricsRequestMiddleware = promBundle({
  includePath: true,
  includeMethod: true,
  autoregister: false, // Do not register /metrics
  promClient: {
    collectDefaultMetrics: {
    },
  },
});
const { promClient, metricsMiddleware } = metricsRequestMiddleware;
// promClient here is the prom-client object 

// Metrics app to expose /metrics endpoint
const metricsApp = express();
metricsApp.use(metricsMiddleware);

module.exports = { metricsRequestMiddleware, metricsApp };
const express = require("express");
const app = express();
const { metricsRequestMiddleware } = require("@server/app/metrics");

// We are using metricsRequestMiddleware which register statistics from main express app
app.use(metricsRequestMiddleware);
const app = require("./server/app");
const { metricsApp } = require("./server/app/metrics");

const server = http.createServer(app); // Main server
const metricsServer = http.createServer(metricsApp); // Metrics server
server.listen(5000);
metricsServer.listen(9090);

@poteirard
Copy link
Author

It works like a charm. Thanks a lot for the code and the comments !

@shaharsol
Copy link

shaharsol commented Jun 11, 2020

@goooseman @poteirard just implemented this solution in my app and found out that indeed I can now access the /metrics endpoint on port 9090, however I can still access the metrics via the main app port i.e localhost:3000/metrics.
Am I missing something? Is there anyway to limit access to the metrics endpoint on the main app port?

Edit: I kinda work around this like so:

    app.use('/metrics', (req, res) => {
        res.send(401);
    });
    app.use(metricsRequestMiddleware);

But it feels hacky to me...

@shaharsol
Copy link

My other issue with that solution is that I can't seem to use the ordering of the uses to determine which route will be measured and which will not. Everything is included regardless of where I use the metricsRequestMiddleware.

@lehno
Copy link

lehno commented Jun 24, 2020

Same problem as you @shaharsol

@elaijuh
Copy link

elaijuh commented Jul 7, 2020

if (opts.autoregister && path.match(metricsMatch)) {

@shaharsol

@nasonfish
Copy link

Here's a solution that seems to work for me.

const app = express();
const metricsApp = express();

const metricsMiddleware = promBundle({
    includeMethod: true,
    includePath: true,
    autoregister: false,
});

app.use(metricsMiddleware);

// app.use(.....)
app.listen(config.PORT, () => {
    console.log('Server listening on port', config.PORT);
});

metricsApp.use(metricsMiddleware.metricsMiddleware);

metricsApp.listen(config.METRICS_PORT, () => {
    console.log('Metrics listening on port', config.METRICS_PORT);
});

It appears to register the metrics endpoint correctly in the metrics server, while collecting the actual metrics from the app.

@ath88
Copy link
Contributor

ath88 commented Jun 17, 2022

I added an option that makes this far easier. Check out #101.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants