Technology

Integrating Prometheus into Node/Express Js app, using the prom-client library to monitor app metrics.

Integrating Prometheus into Node/Express Js app, using the prom-client library to monitor app metrics.

Hey guys šŸ‘‹šŸ¾šŸ˜Š! This article will give a thorough explanation of application monitoring using Prometheus, and integrating Prometheus to a Node/Express.Js application leveraging the prom-client library.

What is Prometheus?

Prometheus is an open-source application designed for monitoring systems and applications. It collects real-time metrics, stores them in a time-series database, and alerts users of potential issues. This makes it particularly valuable for pinpointing problems during application outages.

Structure of Prometheus

Prometheus follows a modular architecture with several key components:

  • Prometheus Server: This is the core component, responsible for scraping metrics from targets (applications or services being monitored), storing the data in a time-series format, and analyzing it. It also offers a user interface for querying the data.
  • Data Model: Metrics are represented as time series data points, often accompanied by labels (key-value pairs) that provide additional context.
  • Alertmanager (Optional): This component handles alerts generated by Prometheus rules based on metric evaluations. It can route them to various notification channels like email or chat platforms.
  • Push Gateway (Optional): Useful for short-lived jobs or applications that cannot be directly scraped by Prometheus. The Pushgateway acts as an intermediary, allowing applications to push metrics to Prometheus on demand.
  • Client Libraries: These libraries simplify embedding metric collection code directly within the applications being monitored. They are available in various languages like Go, Python, and Java.
  • Exporters (Optional): For services that donā€™t natively support metric scraping, exporters act as translators, converting their metrics into a format consumable by Prometheus.

Integrating Prometheus in Node/Express Js app

Prometheus has multiple libraries for integration with multiple technologies and their frameworks, e.g.However Python, Java, C#, etc. However, in this article, weā€™ll go through how to setup Prometheus in a Node/Express Js application using the prom-client and swagger-stats libraries.

Installing Node Js runtime

To begin, weā€™ll make sure we have Node Js and npm running on our system. To confirm if Node Js is installed on our system, we run the following command.

We should receive an output similar to that below

We also need to verify if the npm package is available on our system we run the below command

You should receive an output similar to that below

If you have neither Node Js nor npm installed on your system, please visit the links below to see how:
https://docs.npmjs.com/downloading-and-installing-node-js-and-npm
https://nodejs.org/en/download

Creating a Node/Express Js app

Now that we have Node Js and npm installed on our system, we can go ahead and create a Node/Express Js web server.

First, we need to set up a Node Js boilerplate using npm. We can do that by running the script below to create a package.json file in our app folder.

Second, we need to install the express, cors, nodemon, and dotenv libraries in our application by running the script below.

Third, we need to create a file in our application folder structure that will be run by Node Js, weā€™ll call it index.js. Afterward, we can paste the below code to create our web server.

We edit the package.json file to automatically restart our app when changes are made using nodemon

After we modify our package.json file, we create a .env file within our app folder where we can store our environment variables like the port the app should run on. Then we paste the following line into it:

Now we can run our web server and view it on port 5000 (or on any port you specified), by executing the script below

Go to your desired web browser and enter http://localhost:5000 in the search bar. You should see something like this

Blog Image

Installing the prom-client library in our Node Js application

Now that weā€™re done setting up the web server, we install the prom-client library by running the script below

Next, we import the prom-client library into our index.js file. Copy the below code and add it to the existing index.js file

Then we create a new registry and collect the applicationā€™s default metrics

Afterward, we create a new endpoint which will be called by the Prometheus application when it scrapes your application metrics.

The index.js file should now look like this

Nodemon should automatically restart the webserver for us, if not, run Ctrl + c, OR Cmd + C in the terminal to stop the webserver, then npm start to restart the webserver. To view the application metrics, visit http://localhost:5000/metrics. You should see something similar to the image below.

Blog Image

Collecting custom application metrics

The above image displays the default metrics collected by the prom-client library, e.g. the number of active requests made to the webserver, etc. To create your custom metrics, youā€™ve got to go some steps further.

There are multiple custom metrics we can track in our application, e.g.

  • The total number of requests made to the application
  • The response rate for each HTTP request
  • The application memory in use
  • The applicationā€™s CPU utilization

I will explain how to get each custom metric mentioned above.

The total number of requests made to the application

This tracks the total number of HTTP requests the web server has received since it was spun up. To track said metric, we create an object, a class for assigning labels to the metrics, and a counter that will be responsible for incrementing the total number of HTTP requests received, upon each new request.

The above piece of code creates a new instance from the Counter class exposed by the prom-client library.

Next, we register the metric, so the prom-client library can begin tracking the metric

Now, we create an Express Js middleware that will be responsible for incrementing the counter upon every HTTP request.

The above code creates a middleware, i.e. a function that will be executed before any incoming HTTP request is processed in the specified route. N.B:Ā It must be called before the route handlers. The req_url variable stores the URL of the incoming HTTP request. The original_res_send_function stores the original function in the res.send property. The res_send_interceptor overrides the existing res.send function, and increments the total number of HTTP requests made to the web server. Note that it also keeps track of the response method, pathname/endpoint, and status code. These are called labels and are used to filter metrics of the same name in Prometheus. For instance, if a GET request is made to the /login endpoint with a response code of 200, and a POST request is made to the /signup endpoint with a response code of 400, they both will be stored under the same metric name, but with different labels, i.e. For the initial request, it will be stored as node_http_request_total{path="/login", status_code="200", method="GET"}, while for the 2nd request, it will be stored as node_http_request_total{path="/signup", status_code="400", method="POST"}.

At the end, your index.js file should look similar to that below

Next, visit http://localhost:5000/, and refresh the page 5ā€“6 times, then visit http://localhost:5000/metrics, and scroll to the bottom of the page. You should see something similar to the one below, with the newly registered metric node_http_request_total

The response rate for each HTTP request

Next, weā€™re gonna look at how to get the time in milliseconds it takes each request to get completed.

We begin by creating a new instance of the prom-client histogram class, that will store the rates of various requests made to the server in buckets. This will help us calculate things like the 95th percentile of the HTTP response rate.

In the piece of code above, we registered multiple buckets ranging from 0.0, which means 0 seconds to 10.0 which means 10 seconds. This is to store HTTP response rates in various buckets. An epitome is, if a HTTP request takes 4 seconds to process, the total time of the HTTP response will be stored in the buckets 4.0 to 10.

Next, we register the metric, by adding the below code

Then, we modify the Express Js middleware we created earlier

The above code still contains the same middleware from the previous section, except a few changes were made to it, i.e. The code responsible for starting and ending the histogramā€™s timer for each HTTP request was added.

Your index.js file should now look similar to the code below

Finally, visit http://loalhost:5000 on your browser, reload the page 2 or more times, and now visit http://loalhost:5000/metrics. You should see an output similar to that below

The application memory in use

Next, weā€™ll keep track of the applicationā€™s memory which is currently in use.

We begin with importing the memoryUsage function from the Node Js process library, creating a new instance of the prom-clientGuage class and registering the new metric. Afterward, we modify the Express Js middleware by adding a piece of code responsible for keeping a record of the current applicationā€™s memory in use on every request made to the web server.

The final code in the index.js file should look similar to that below

Lastly, visit http://loalhost:5000 on your browser, reload the page, and visit http://loalhost:5000/metrics. You should see an output similar to that below

Blog Image

The applicationā€™s CPU utilization

Finally, for the last metric on this list, weā€™ll monitor the amount of the CPU the application is currently using.

We begin by installing the os library

Next, we import the cpus function from the os library

Afterward, we create a function responsible for calculating the current amount of the CPU the app is utilizing

Then, we create and register a new instance of the Guage class offered by the prom-client library, and register it amongst other metrics.

Next, we modify the Express Js middleware by adding a few lines of code responsible for updating the prom-client Guage with the current CPU usage on every HTTP request.

Your final index.js file should look similar to that below

Lastly, visit http://loalhost:5000 on your browser, reload the page, and visit http://loalhost:5000/metrics. You should see an output similar to that below

Blog Image

Conclusion

Thanks for reading this article, hope it helped you on your journey to Node Js application monitoring using Prometheus. Iā€™ll be sure to create another article on how to implement these using a shorter approach via the swagger-stats library sooner or later. For those who still have a hard time understanding how to use Prometheus alongside Node/Express Js, you can explore the below links:
https://www.techtarget.com/searchapparchitecture/tip/5-application-performance-metrics-all-dev-teams-should-track (other useful metrics to track)
https://github.com/RisingStack/example-prometheus-nodejs (analyzing, and displaying said metrics on the Prometheus client)