Get Prometheus Metrics from a Express.js app

Austin Cunningham
5 min readJul 29, 2021

Expose the metrics in Express.js app

I use Prometheus all the time for metrics and alert monitoring in Kubernetes. I decided to see how to setup monitoring in a Node/Express.js app. A quick search of npmjs and I found these two package prom-client a really detailed Prometheus client and express-prom-bundle which uses prom-client under the hood, I chose express-prom-bundle as it was a quick win and was producing metrics with a few lines of code, my repo is here. I installed the following packages in my express app

npm install prom-client express-prom-bundle — save

Then added the Prometheus middleware to all routes

Running the app


npm start
> express-prometheus@1.0.0 start /home/austincunningham/repo/express-prometheus
> node index.js
Listening at http://localhost:8080
# curl the hello world endpoint
curl localhost:8080/hello
{“hello”:”world”}%
# curl the metrics endpoint
curl localhost:8080/metrics
# HELP process_cpu_user_seconds_total Total user CPU time spent in seconds.
# TYPE process_cpu_user_seconds_total counter
process_cpu_user_seconds_total 0.120868
# I cut the metrics output short here as its a lot of text but you get the idea

Setup the Express app on Openshift

I am using crc which is local Kubernetes development environment based on Red Hat Openshift. I create a container for the app based on the following DockerFile.

I then build, test the image locally and push the image

I can then deploy this on crc/openshift with the following two files
deployment.yaml

service.yaml

Apply the files to the default project

oc project default
oc apply -f deployment.yaml
oc apply -f service.yaml
service/example-app created
# create a route to the service so you can access from the browser
oc expose service example-app

You can test the route by hitting the /metrics path in the browser you should see

Setup Prometheus Operator on Openshift

I am following the prometheus operator getting started guide. Applied the bundle from the setup on the default namespace

oc project default
oc apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/master/bundle.yaml

NOTE: Hit a issue where the prometheus-operator pod was in a crash loop backoff :(

Openshift has an operator hub so I did the following to fix the crashing operator pod. First I deleted the existing prometheus-operator deployment

oc delete deployment prometheus-operator

Logged in to crc/Openshift console as kubeadmin, in the administrator view go to OperatorHub and search for prometheus

Select the `Prometheus Operator` tile and `continue` then select `install` button

Select the default namespace from the drop down and install button again

Phew! that took longer to explain that to do.

Steps to get Prometheus to see the Express.js apps metrics

First we add the Prometheus CR(custom resource) to the default namespace to start the Prometheus instance
prometheus.yaml

And add the service
prometheus-service.yaml

Apply the files and create a route

oc apply -f prometheus.yaml
oc apply -f prometheus-service.yaml
# create a route to the service so you can access from the browser
oc expose service prometheus-operated

The way Prometheus scrapes metrics is that it uses a service monitor to check a service for a particular label. We have already created the service when we deployed the example-app with the label app: example-app in metadata.labels.

Next we create a serviceMonitor in the default namespace and with a selector for the app: example-app label. So we create the following file.
service-monitor.yaml

NOTE: metadata.labels `team: frontend` .

We upload the service-monitor.yaml file to the default namespace to create the serviceMonitor

oc apply -f service-monitor.yaml

In the prometheus.yaml CR we have already selected the service monitor this is done via serviceMonitorSelector label with the label team: frontend

Finally we need some RBAC rules which is Kubernetes version of permissions to allow Prometheus to see everything

Setup a service account, clusterRole and clusterRoleBinding. Create the following files
service-account.yaml

clusterRole.yaml

clusterRoleBinding.yaml

Apply the files to the default namespace

oc apply -f service-account.yaml 
oc apply -f clusterRole.yaml
oc apply -f clusterRoleBinding.yaml

You should be able to access the route the default namespace

You can open the Prometheus UI by adding a http:// to the Prometheus HOST/PORT returned from the oc get routes command

So how do you know if its working

It takes a little while for the Prometheus operator to reconcile and to show up the new resources. In the Prometheus ui first check the Status\Service Discovery you should see example-app show up

NOTE: be patient it can take a while to show up

Then check the Status\Targets should see the following targets up

You also should be able to see metrics from example-app in the graph tab

That it I may do a follow up on setting up Grafana to use these metrics

--

--