How to Create a Project with .NET, OpenTelemetry, and Docker Using .NET Aspire for Logs
Introduction
Hello, devs! Today, we’re embarking on an exciting journey: creating a simple project using .NET 8, setting up OpenTelemetry to instrument our ASP.NET Core and HTTP, and finally, deploying our application in a Docker environment.
Additionally, we’ll use .NET Aspire to monitor our application’s logs.
This tutorial is ideal for both beginners and experienced developers looking to explore new tools and practices.
Let’s go?
Initial Project Setup with .NET 8
To start, let’s create a new ASP.NET Core project using .NET 8. Open your terminal and run the following commands:
dotnet new webapi -n MyAspNetProject
cd MyAspNetProject
dotnet add package OpenTelemetry --version 1.9.0
dotnet add package OpenTelemetry.Extensions.Hosting --version 1.9.0
dotnet add package OpenTelemetry.Instrumentation.AspNetCore --version 1.9.0
dotnet add package OpenTelemetry.Instrumentation.Http --version 1.9.0
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol --version 1.9.0
These commands create a new Web API project and add the necessary OpenTelemetry packages.
Implementing OpenTelemetry in ASP.NET Core
Now, let’s configure OpenTelemetry in our project.
In the Program.cs file, add the following code:
using OpenTelemetry.Resources;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container
builder.Services.AddControllers();
// Configure OpenTelemetry
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource => resource.AddService("MyAspNetProject"))
.WithMetrics(metrics =>
{
metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter();
})
.WithTracing(tracing =>
{
tracing
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter();
});
builder.Logging.ClearProviders();
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeScopes = true;
logging.IncludeFormattedMessage = true;
logging.AddOtlpExporter();
});
var app = builder.Build();
// Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.Run();
This code configures OpenTelemetry to instrument ASP.NET Core and HTTP and export the information to OTLP (OpenTelemetry Protocol).
Creation of a sample endpoint
To instrument HTTP calls, we need to add HttpClient instrumentation. The configuration was already done in the previous step, but let’s ensure that HTTP calls are also monitored.
Create a sample controller and add an endpoint that checks if a number is prime:
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("primes")]
public class PrimeController : ControllerBase
{
[HttpGet("{number:int}")]
public IActionResult IsPrime(int number)
{
if (number < 1)
return BadRequest("The number must be greater than or equal to 1.");
bool isPrime = IsPrimeNumber(number);
return Ok(new { Number = number, IsPrime = isPrime });
}
private bool IsPrimeNumber(int number)
{
if (number < 2)
return false;
for (int i = 2; i <= Math.Sqrt(number); i++)
{
if (number % i == 0)
return false;
}
return true;
}
}
The calls to this endpoint will be exported to OTLP (OpenTelemetry Protocol).
Dockerizing the Application
To dockerize the application, create a Dockerfile in the project root:
# Use a base image of .NET
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyAspNetProject/MyAspNetProject.csproj", "MyAspNetProject/"]
RUN dotnet restore "MyAspNetProject/MyAspNetProject.csproj"
COPY . .
WORKDIR "/src/MyAspNetProject"
RUN dotnet build "MyAspNetProject.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "MyAspNetProject.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyAspNetProject.dll"]
And a docker-compose.yml file:
version: '3.4'
services:
open-telemetry-aspire:
image: ${DOCKER_REGISTRY-}my-aspnet-project
container_name: api
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- OTEL_EXPORTER_OTLP_ENDPOINT=http://aspire.dashboard:18889
networks:
- otel
aspire.dashboard:
image: mcr.microsoft.com/dotnet/nightly/aspire-dashboard:latest
container_name: dashboard
ports:
- "18888:18888"
networks:
- otel
networks:
otel:
To build and run the container, execute:
docker-compose up --build
Testing and Checking Logs in .NET Aspire
With the application running in Docker, we can test it and check if the logs are being correctly sent to .NET Aspire. Make some requests to the API and then access the .NET Aspire dashboard to view the logs:
curl http://localhost:8080/primes/7
curl http://localhost:8080/primes/-1
In the .NET Aspire dashboard, you should see the logs of the requests, including details about the OpenTelemetry instrumentation.
Conclusion and Next Steps
Congratulations, devs! You have configured an ASP.NET Core project with .NET 8, added instrumentation with OpenTelemetry, dockerized the application, and set up log monitoring with .NET Aspire.
This setup provides a comprehensive view of your application’s behavior, making it easier to monitor and resolve issues.
Explore more about OpenTelemetry and .NET Aspire to get the most out of these tools, and write in the comments what you think.
And here is a sample project with all of this: [GitHub]
See ya!