|

What is Prometheus and How to Add Prometheus To Your .NET Projects?

Requirements: Latest versions of Docker and Visual Studio

Prometheus

Hello all,

Monitoring is very essential in todays fast pacing development environments. We can divide monitoring into different aspects such as tracing, collecting metrics and visualizing metrics. For tracing, we have covered OpenTelemetry and Zipkin here. Today we will talk about collecting any metrics within our application.

There will be no new installation for your machine unless you have Docker installed. Else I strongly advise you to have Docker.

Prometheus is basically a metric collector for your applications. It doesn’t have to be a .NET application. It doesn’t even need to be an application. Prometheus also have some exporters for exporting OS metrics such as CPU, Mem, etc..

If we have already Docker Desktop up and running, let’s pull the Prometheus image.

docker pull prom/prometheus

After the pull is completed:

docker run --name prometheus -d -p 9090:9090 prom/prometheus

If you are not familiar with Docker, let’s talk about what does that command do.

“docker run prom/prometheus” is the command for starting a container from official prometheus image.

“ — — name prometheus” argument is for giving a name to our little container.

“-d” is for detached mode. It means the container will run in the background and it won’t stop when you quit your terminal.

“-p 9090:9090” first 9090 is your machine’s port and the second one is container’s port. It means you are exposing container’s 9090 port to your machine’s 9090 port, so you can reach Prometheus interface from your web browser as “localhost:9090”

Enough with the Docker command. Let’s continue with Prometheus. From your Docker interface (or as an output to “docker ps” command) you should see Prometheus container is up and running. Let’s hit your favorite web browser to investigate Prometheus further. Go to “localhost:9090” from you web browser.

An empty screen welcomes us. In this screen we can write some queries and get some results. Again, to write any query, we should have some metrics. Actually the very container you have run have some metrics already even though we won’t care about those metrics. You can hit “localhost:9090/metrics” to see which metrics are exposed by the Prometheus server (your container itself)

Prometheus Server related metrics

The metrics are related to Prometheus Server itself. It’s like a self healthcheck. But how exactly does Prometheus work?

I encourage you to discover “Targets” page located in Prometheus UI.

Navigate to the Targets page
Targets for Prometheus Server

Prometheus already harvests its own metrics. Because you can see the endpoint’s state is UP. And if you hit the “Configuration” page, you will see the configuration for Prometheus.

Navigate to Configuration Screen
Targets in default Configuration

So now we know that, which endpoints are listened to, comes from the configuration in Prometheus Server.

Prometheus basically operates like this. There is a Prometheus server which has all the metrics listened to.

Prometheus exporters are remote endpoints on different hosts which are all basically a bunch of texts served from the memory. Each client should be targeted by configuration in Prometheus Server. If that exporter is not in targets list, there is no one listening to that target.

An exporter could be a Windows exe, or it could be another service within our .NET application which run on different port. Whatever that exporter is, I have to enter the remote address in that configuration file. After we prepare our .NET application, we will return to here.

We create a new project for our little experiment to see how we configure Prometheus. Open Visual Studio and create a new API project. But feel free to do the same for ASP projects.

Structure of our initial project

Let’s add the NuGet packages for Prometheus. The package we will be using is prometheus-net and prometheus-net.AspNetCore from sandersaares.

Install prometheus-net packages from sandersaares

In your Program.cs file, add this code below to prepare a Prometheus client up and running. The snippet should be before builder.Build() is executed.

.....
builder.Services.AddMetricServer(
options => {
options.Port = 1234;
});
....
....
var app = builder.Build();

Let’s run our project to see if Prometheus is awakened. It does not matter if you run your project with Kestrel or IIS Express at this point. This is your development environment. We specified port 1234 to run our Prometheus endpoint at. You may change this port. I’ll assume you have used 1234 as your Prometheus port.

After our project is initialized, let’s go to localhost:1234/metrics to check Prometheus endpoint.

Prometheus endpoint at localhost:1234/metrics

If you can see this screen, it means you have succeeded running Prometheus in your project. Well done.

As soon as I refresh the page, it has some default metrics counted already. They are actually because I am refreshing a page in my .NET project while refreshing the Prometheus metrics page. They are counted as default by prometheus-net.AspNetCore.

Default metrics exposed by prometheus-net.AspNetCore

We can also make our own special metrics using Prometheus-net documentations. I will cover it on another article.

Let’s summarize what we have done until here. We have run a Prometheus Server as a Docker container. We have created a sample project which is counting my requests by default. But our Prometheus server is not informed about that new Prometheus endpoint. So how do we do that? We should get back to Prometheus server configuration.

We did see localhost:9090 (that localhost is not your machine, it is the container which Prometheus server runs) in targets, is configured by default on our Prometheus server for self observing purposes. We should also add our application as target to Prometheus Server. Open a cmd window and write this:

docker exec -it prometheus sh

This command will be activate a shell in Prometheus container which we will be able to edit configuration file. After it, cmd (or PowerShell) window should look like this:

PS C:\Users\idylmz> docker exec -it prometheus sh
/prometheus $

If we see /prometheus, we are in the container. Now go and edit /etc/prometheus/prometheus.yml.

vi /etc/prometheus/prometheus.yml

For those who are not familiar to vim, I will walk you through.

With vim, we are basically using our terminal window as a text editor. So there is no mouse pointer to help us, we must use our keyboard’s arrows.

By using our keyboard arrows, we will go to the end of the last line which is:

- targets: ["localhost: 9090"]

If we press “i” in vim, it means we will be inserting some new characters. We’ll be continuing this line as follows:

- targets: ["localhost:9090", "host.docker.internal:1234"]

host.docker.internal is our Docker host which we are running Docker from. Since we are running our sample app on our host machine, we should be call our host as this. 1234 port is the port that our app is using for exposing prometheus metrics. To save our file and quit vim, first we press ESC to quit from insert mode. Then press “:wq!” and enter to save and quit from vim without any “Are you sure” prompt.

:wq! command should appear on the bottom left of the screen.

After editing our Prometheus config, we should restart the container to make changes to take effect.

This is how our commands looked so far.

First we exit the shell in our container.

exit

Then we restart the container once we returned to our host machine.

docker restart prometheus

Let’s see our targets if it did changed at all.

If everything did go well and the project is running, this is the screen we should be seeing.

You can see our host is recognized by Prometheus Server and the metrics are started to collect.

With these steps, you’re now equipped to start monitoring your .NET applications with Prometheus. From here, you can dive deeper into custom metrics, querying, and visualizing your data to make the most of your monitoring setup. Stay tuned for more articles where I’ll cover these topics in detail — happy coding, and may your metrics be ever insightful!

Similar Posts

  • |

    Monitoring Java Applications with JMX

    https://github.com/idylmz/JMXExampleProject Years ago, when I joined a team working on resilience, we were asked to monitor a product developed in Java — without using an APM agent. Everyone on the team had the same question in mind: “How are we going to see what’s going on inside this application without installing an agent?” Since the product was…

  • |

    Master Your Alerts with Prometheus and Alertmanager

    To ensure that applications and services run smoothly, collecting metrics alone is not sufficient. What really matters is being notified when something unusual happens in those metrics. This is where the Prometheus + Alertmanager duo comes into play. In this article, I will focus more on the alerts that can be defined directly in Prometheus….

Leave a Reply

Your email address will not be published. Required fields are marked *