Is Your Express App as Smooth as Butter with Prometheus?

Unlocking Express Performance: Your App’s Secret Weapon

Is Your Express App as Smooth as Butter with Prometheus?

Taking care of your Express app’s performance is super important to make sure everything runs well. One nifty tool to help with this is Prometheus, a well-loved monitoring and alerting system in the industry. Here’s a rundown on how using Prometheus middleware can help collect useful metrics from your Express app, ensuring everything runs as smooth as butter.

First off, why Prometheus? It’s simple – it’s one of the go-to tools in the industry for tracking various metrics related to how well your application performs. It’s great for keeping an eye on key stats like request rates, error rates, and how long responses take. These indicators are crucial for understanding your app’s behavior when under different loads.

To kick things off, you’ll first want to install the Prometheus middleware package. Although there are several packages out there, we’ll focus on express-prometheus-middleware because it’s easy to use and packed with features.

npm install express-prometheus-middleware

Once that’s installed, you can set it up in your Express app with a few lines of code. Here’s a basic setup example:

const express = require('express');
const promMid = require('express-prometheus-middleware');

const app = express();
const PORT = 9091;

app.use(promMid({
  metricsPath: '/metrics',
  collectDefaultMetrics: true,
  requestDurationBuckets: [0.1, 0.5, 1, 1.5],
  requestLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
  responseLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
}));

app.get('/hello', (req, res) => {
  res.json({ message: 'Hello World!' });
});

const server = app.listen(PORT, () => {
  console.info(`Server is up and running @ http://localhost:${PORT}`);
});

In this example, the middleware is set to expose metrics at the /metrics endpoint. With collectDefaultMetrics set to true, basic metrics like CPU usage and memory usage are collected automatically, making it convenient to start monitoring straight away.

Need more customization on the metrics side? No problem. You can tweak the metrics collection to match your requirements. For example, setting up custom buckets for request and response lengths, or excluding certain routes from being tracked.

app.use(promMid({
  metricsPath: '/metrics',
  collectDefaultMetrics: true,
  requestDurationBuckets: [0.1, 0.5, 1, 1.5],
  requestLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
  responseLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
  extraMasks: [/\/api\/v1\/users\/\d+/], // Mask certain routes
  authenticate: (req) => req.headers['x-api-key'] === 'your-api-key', // Add authentication
}));

When it comes to monitoring, certain metrics provided by the middleware are particularly useful. These include:

  • http_requests_in_progress: Gauges current HTTP requests in progress.
  • http_requests_total: Counts the total number of HTTP requests.
  • http_response_latency_ms: Summarizes the duration of responses in milliseconds.
  • http_response_latency_histogram: Histograms response durations in milliseconds in buckets.
  • http_errors_total: Counts total server-side errors.
  • http_errors_client_total: Counts total client-side errors.

For those seeking advanced configurations, there’s room to grow. Options like normalizePath can standardize URL paths before they’re added to metrics, and exclude can be used to skip certain routes.

app.use(promMid({
  metricsPath: '/metrics',
  collectDefaultMetrics: true,
  normalizePath: true,
  exclude: (req) => req.method === 'POST' && req.path === '/accounts',
}));

To collect custom metrics beyond the basics, you can dive deep using the prom-client library directly within your Express app. Here’s a quick snippet on how that looks:

const Prometheus = require('prom-client');
const gauge = new Prometheus.Gauge({
  name: 'myamazingapp_interesting_datapoint',
  help: 'A very helpful but terse explanation of this metric',
  collect() {
    this.inc();
  },
});

app.use(promMid({
  metricsPath: '/metrics',
  collectDefaultMetrics: true,
}));

app.listen(PORT, () => {
  console.log('Server has been started');
});

After getting your app up and running, you can easily view metrics by hitting the /metrics endpoint. This opens up a treasure trove of data that Prometheus can scrape and parse for you.

curl http://localhost:9091/metrics

Expect the output to look something like:

# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1643723905
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 14
# HELP http_request_duration_milliseconds Request duration in milliseconds.
# TYPE http_request_duration_milliseconds summary
http_request_duration_milliseconds{quantile="0.01",code="200",handler="/hello",method="get"} 114.4
http_request_duration_milliseconds{quantile="0.05",code="200",handler="/hello",method="get"} 143.4
...

In the end, integrating Prometheus middleware with your Express app is an easy yet powerful way to monitor and enhance performance. By collecting and analyzing key metrics, you can uncover precious insights about your app’s behavior in various scenarios. This will empower you to make informed decisions to optimize its performance even further. Plus, with the flexibility to customize and add your own metrics, you can tailor the monitoring setup to fit like a glove.