.NET 8 API with Prometheus and Grafana
.NET 8 API with Prometheus and Grafana
Dear reader, Prometheus and Grafana are open-source monitoring and visualization tools commonly used together to collect, store, and display metrics and logs from various systems and applications. By integrating the Asp.net API with Prometheus, you can gather data, while Grafana provides a user-friendly interface to create dashboards and analyze the collected information. In this article we are going to talk about how to implement telemetry in Asp.net API using those tools.
Read more about: Prometheus and Grafana
Requirements:
Before you begin, make sure you have the following software installed on your machine
Create a new WebApi project and install the Prometheus package on it:
dotnet new webapi -n my-api -minimal
cd my-api
dotnet add package prometheus-net.AspNetCore
dotnet restore
Let’s do some changes to our code, using the Visual Studio Code, edit the Program.cs
You can remove unnecessary code related to ‘WeatherForecast’. Add the following line:
using Prometheus;
[...]
builder.Services.UseHttpClientMetrics();
[...]
app.UseMetricServer();
app.UseHttpMetrics();
Create a new endpoint:
app.MapGet("/random-number", () =>
{
var number = Random.Shared.Next(0, 10);
if (number >= 7)
return Results.Unauthorized();
return Results.Ok(number);
});
in the end, it will look like this:
using Prometheus;
var builder = WebApplication.CreateBuilder(args);builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.UseHttpClientMetrics();
var app = builder.Build();if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}app.UseMetricServer();
app.UseHttpMetrics();app.MapGet("/random-number", () =>
{
var number = Random.Shared.Next(0, 10);
if (number >= 7)
return Results.Unauthorized();
return Results.Ok(number);
});app.Run();
In the ‘./Properties/launchSettings.json’ file, add the “Container (Dockerfile)” node, it will look like this:
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:32818",
"sslPort": 44375
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5013",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7035;http://localhost:5013",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Container (Dockerfile)": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"environmentVariables": {
"ASPNETCORE_HTTP_PORTS": "8080"
},
"publishAllPorts": true,
"useSSL": true
}
}
}
Inside “my-api” folder, add a new Dockerfile and past this code:
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["my-api/my-api.csproj", "my-api/"]
RUN dotnet restore "./my-api/my-api.csproj"
COPY . .
WORKDIR "/src/my-api"
RUN dotnet build "./my-api.csproj" -c $BUILD_CONFIGURATION -o /app/buildFROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./my-api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=falseFROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "my-api.dll"]
Outside of ‘my-api’ folder, create a file called ‘prometheus.yml’ and past it:
global:
scrape_interval: 10s
scrape_configs:
- job_name: 'my-api-read-prometheus'
static_configs:
- targets: ['my-api:8080']
And create a file called ‘docker-compose.yml’ and past it:
version: '3.4'
services:
my-api:
image: ${DOCKER_REGISTRY-}my-api
ports:
- 8080:8080
build:
context: .
dockerfile: my-api/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_HTTP_PORTS=8080
networks:
- mynw prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
command:
- '--config.file=/etc/prometheus/prometheus.yml'
networks:
- mynw grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- ./grafana:/var/lib/grafana
depends_on:
- prometheus
networks:
- mynwnetworks:
mynw:
All configuration were done, let’s test our project.
Run the containers:
docker compose build
docker compose up
Wait until it finish, and now you can access your API, sometime you will get an HTTP 200 with a number, and sometimes a error page with 401 unauthorized.
API: http://localhost:8080/random-number
You also can see metrics from your API in the ‘/metrics ‘ endpoint:
API Metrics: http://localhost:8080/metrics
Check if your Prometheus container is connected to your API:
Expected result:
Go to Grafana: http://localhost:3000/
Log in with username and password ‘admin’, after that, and add a new data source connection:
Click on ‘Add new Data Source’ in the ‘Connection’ set the Prometheus URL: “http://prometheus:9090” (this is our container name)
Go to Dashboards > Create new Dash board> + Add Visualization
Code, add: “sum by(code) (http_request_duration_seconds_bucket)”
It is done, now you can research more about other metrics and enrich your app and dashboard.
As a Brief conclusion
Benefits of using Prometheus include the ability to understand where your app is receiving the most hits, providing clear insights into traffic and performance