Export OpenTelemetry Metrics to Prometheus for .NET Application

In this article we are going to cover Export OpenTelemetry Metrics to Prometheus for .NET Application.

In this article, we will explore how to monitor HTTP metrics for a .NET application using OpenTelemetry and Prometheus. Monitoring your application’s performance is critical for maintaining reliability, diagnosing issues, and optimizing performance. We’ll cover how to instrument your .Net application using OpenTelemetry, expose metrics to Prometheus for detailed analysis, and set up Docker for containerization.

Prerequisites

Before you start, ensure you have the following installed on your system.

  • AWS Account with Ubuntu 24.04 LTS EC2 Instance.
  • .NET SDK, Docker and Prometheus installed.

Step #1:Set Up Ubuntu EC2 Instance

If you don’t have SDK, Docker and Prometheus installed on your system you can install it by using following commands.

First Update the package list.

sudo apt update
Export OpenTelemetry Metrics to Prometheus for .NET Application 1

To install the .NET SDK on your Ubuntu server, use the following command.

sudo apt install -y dotnet-sdk-8.0
Export OpenTelemetry Metrics to Prometheus for .NET Application 2

To install the Docker on your Ubuntu server, use the following command.

sudo apt install -y docker.io
Export OpenTelemetry Metrics to Prometheus for .NET Application 3

start the docker service.

sudo systemctl start docker
Export OpenTelemetry Metrics to Prometheus for .NET Application 4

enable the docker service.

sudo systemctl enable docker
Export OpenTelemetry Metrics to Prometheus for .NET Application 5

Now let’s get the prometheus using Docker.

sudo docker pull prom/prometheus
Export OpenTelemetry Metrics to Prometheus for .NET Application 6

Step #2:Set up .NET Project with OpenTelemetry

For this example, we’ll use a sample .NET application from our GitHub repository.

Clone the below our Opentelemetry GitHub repository using following command.

git clone https://github.com/devopshint/opentelemetry-prometheus-for-dotnet-app.git
Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 3

Navigate to the project directory.

cd opentelemetry-prometheus-for-dotnet-app
Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 4

Step #3:Instrumenting .NET Application with OpenTelemetry

Open the Program.cs file

nano Program.cs
Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 5

Add the following line to the top of your Program.cs file.

using System.Globalization; and using Microsoft.AspNetCore.Mvc;

using System.Globalization;
using System.Diagnostics.Metrics;
using Microsoft.AspNetCore.Mvc;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using OpenTelemetry.Instrumentation.AspNetCore;
using OpenTelemetry.Instrumentation.Http;
using Prometheus;


var builder = WebApplication.CreateBuilder(args);

const string serviceName = "roll-dice";


// Add services to the container.
builder.Services.AddControllers();

// Create a custom meter for the API
var meter = new Meter("roll-dice.Metrics", "1.0");


var httpRequestCounter = meter.CreateCounter<long>("http_requests_total", description: "Total number of HTTP requests");


builder.Logging.AddOpenTelemetry(options =>
{
    options
        .SetResourceBuilder(
            ResourceBuilder.CreateDefault()
                .AddService(serviceName))
        .AddConsoleExporter();
});

// Configure OpenTelemetry
builder.Services.AddOpenTelemetry()
    .WithTracing(tracerProviderBuilder =>
    {
        tracerProviderBuilder
            .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("roll-dice"))
            .AddAspNetCoreInstrumentation() // Tracks incoming HTTP requests
            .AddHttpClientInstrumentation()
            .AddConsoleExporter(); // Optional: For debugging
    })
    .WithMetrics(meterProviderBuilder =>
    {
        meterProviderBuilder
            .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("roll-dice"))
            .AddAspNetCoreInstrumentation() // Tracks incoming HTTP request metrics
            .AddHttpClientInstrumentation()
            .AddPrometheusExporter(); // Expose metrics to Prometheus
    });

// Add middleware to count HTTP requests
var app = builder.Build();

// Use the Prometheus middleware to expose the /metrics endpoint.
app.UseRouting();

app.UseHttpMetrics(); // Middleware for collecting HTTP metrics

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapMetrics(); // Expose the /metrics endpoint for Prometheus scraping
});



string HandleRollDice([FromServices]ILogger<Program> logger, string? player)
{
    var result = RollDice();

    if (string.IsNullOrEmpty(player))
    {
        logger.LogInformation("Anonymous player is rolling the dice: {result}", result);
    }
    else
    {
        logger.LogInformation("{player} is rolling the dice: {result}", player, result);
    }

    return result.ToString(CultureInfo.InvariantCulture);
}

int RollDice()
{
    return Random.Shared.Next(1, 7);
}

app.MapGet("/rolldice/{player?}", HandleRollDice);

app.Run();
Explanation of the OpenTelemetry Instrumentation code for .Net Application

1. Imports

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 6

These lines import the necessary namespaces, including those for OpenTelemetry, ASP.NET Core, metrics, and Prometheus. Each namespace provides classes and methods for building the application’s telemetry and HTTP functionalities.

2. Creating the Web Application

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 7

WebApplication.CreateBuilder(args) initializes the ASP.NET Core application builder.serviceName defines the name of the service, which is used later in telemetry to identify the source of traces and metrics.

3. Adding Services to the Container

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 8

Adds support for controllers to the application, enabling the MVC framework and allowing you to handle HTTP requests using controller methods.

4. Creating a Custom Meter for Metrics

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 9

Creates a custom Meter named roll-dice.Metrics to track metrics for this application.

A counter metric called http_requests_total is defined to track the total number of HTTP requests.

5. Configuring OpenTelemetry for Logging

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 10

Configures OpenTelemetry to handle logging with the service name roll-dice.AddConsoleExporter() sets up console logging to output telemetry data, which is useful for debugging.

6. Configuring OpenTelemetry for Tracing and Metrics

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 11

Configures OpenTelemetry tracing and http metrics:

  • Tracing: Instruments HTTP requests, tracks HTTP client interactions, and exports trace data to the console.
  • Metrics: Instruments HTTP request metrics and exposes them to Prometheus using the AddPrometheusExporter() method.

7. Building the Application and Configuring Middleware

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 12

app.UseRouting() sets up request routing.app.UseHttpMetrics() integrates Prometheus HTTP metrics, which automatically tracks details about incoming HTTP requests.

8. Exposing the /metrics Endpoint

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 13

Maps endpoints for the controllers.MapMetrics() exposes the /metrics endpoint, allowing Prometheus to scrape metric data from the application.

9. Handling the /rolldice Endpoint

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 14

HandleRollDice method:

  • Handles requests to the /rolldice endpoint.
  • Rolls a dice using the RollDice() method and logs the result.
  • If a player name is provided, it logs the name; otherwise, it logs that an anonymous player is rolling the dice.

RollDice method:

  • Generates a random number between 1 and 6, simulating a dice roll.

app.MapGet("/rolldice/{player?}", HandleRollDice);: Maps the /rolldice endpoint to the HandleRollDice method, making the dice-rolling logic accessible via HTTP requests.

10. Running the Application

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 15

Starts the web application and begins listening for incoming HTTP requests.

Next open the MyPrometheusApp.csproj file.

nano MyPrometheusApp.csproj
Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 16

Update the packages to the latest versions.

“OpenTelemetry.Instrumentation.AspNetCore” Version=”1.7.0″ and “OpenTelemetry.Instrumentation.Http” Version=”1.7.0″

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.8" />
    <PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.9.0-beta.2" />
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.6.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.7.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.7.0" />
    <PackageReference Include="prometheus-net.AspNetCore" Version="6.0.0" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
  </ItemGroup>

</Project>
Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 17
Explanation of the code:

This project file sets up the .NET web application to leverage modern observability tools and web standards.

  1. Project Definition: This part specifies that the project uses the Microsoft.NET.Sdk.Web SDK, which is specifically designed for building web applications using ASP.NET Core. It includes all the necessary tools and dependencies for web projects.
  2. PropertyGroup Section:
    • TargetFramework: This property specifies the .NET version the application is targeting, which in this case is .NET 8.0. It defines the version of the runtime and libraries that the application will use.
    • Nullable: Setting this to enable enables nullable reference types in C#. It ensures that the code explicitly handles null values, reducing null reference errors and increasing code safety.
    • ImplicitUsings: When set to enable, this feature automatically includes common using directives, so you don’t need to write them at the top of each file. This simplifies the code by implicitly including commonly used namespaces.
  3. ItemGroup Section: This section lists all the external dependencies (NuGet packages) that the project requires.

Next open the prometheus.yml

nano prometheus.yml
Export OpenTelemetry Metrics to Prometheus for .NET Application 7

change the targets

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'MyPrometheusApp'
    scrape_interval: 5s
    metrics_path: '/metrics'
    static_configs:
      - targets: ['<EC2-instance-IP>:8080']
Export OpenTelemetry Metrics to Prometheus for .NET Application 8

Step #4:Build and Run .NET Application with OpenTelemetry

To compile and run your application, use the following commands.

Build the application.

dotnet build
Export OpenTelemetry Metrics to Prometheus for .NET Application 9

Run the application.

dotnet run
Export OpenTelemetry Metrics to Prometheus for .NET Application 10

This will start the application, and it will expose the /metrics endpoint for  Prometheus to scrape.

You can test your application by accessing the endpoint that returns the http metrics (e.g., http://<EC2-Instance-IP>:8080/metrics).

http://<EC2-Instance-IP>:8080/metrics
Export OpenTelemetry Metrics to Prometheus for .NET Application 11

Navigate to the project directory.

cd opentelemetry-prometheus-for-dotnet-app
Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus 4

Run the Prometheus container.

sudo docker run -p 9090:9090 -v ~/opentelemetry-prometheus-for-dotnet-app/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
Export OpenTelemetry Metrics to Prometheus for .NET Application 12

Once the container is running, you can access the Prometheus web interface by visiting http://<EC2-Instance-IP>:9090.

Export OpenTelemetry Metrics to Prometheus for .NET Application 13

To check if Prometheus is correctly scraping metrics from your .NET application, navigate to the “Targets” page in the Prometheus UI. Click on “Status” in the menu bar and then “Targets. “Ensure that your job MyPrometheusApp is listed and marked as “UP.”

Export OpenTelemetry Metrics to Prometheus for .NET Application 14

Conclusion:

In conclusion, today we have successfully deployed a .NET application that exposes HTTP metrics using OpenTelemetry and monitored it using Prometheus running in Docker. This setup allows you to monitor the performance and health of your .Net application effectively. It helps to ensure that your application performs reliably and efficiently, making it easier to diagnose issues and improve its overall performance.

Related Articles:

Collect HTTP Metrics for .NET Application using OpenTelemetry and Prometheus

Reference:

Official Opentelemetry Page

Prasad Hole

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Share via
Copy link
Powered by Social Snap