Install .NET SDK and .NET Runtime on Ubuntu
You can use the Open Telemetry .NET SDK to automatically instrument your .NET application, allowing you to collect telemetry data like traces and metrics and send them to a compatible backend such as Jaeger.
Prerequisites
.NET SDK installed on your machine.
Access to a tracing backend like Jaeger, Zipkin, or any other service that works with OpenTelemetry to export telemetry data.
Install .NET SDK and .NET Runtime on Ubuntu
Please follow below article to Install .NET SDK and .NET Runtime on Ubuntu
Install .NET SDK and .NET Runtime on Ubuntu
Create a simple .NET Application with HTTP Server
To begin, set up an environment in a new directory called dotnet-
app.
sudo mkdir dotnet-app
Within that directory, execute following command.
sudo dotnet new web
In the same directory, we found a file; replace the content of Program.cs
with the following code.
using System.Globalization;
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
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();
In the Properties
subdirectory, replace the content of launchSettings.json
with the below code.
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:8080",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Build and run the application with the below command.
sudo dotnet build
sudo dotnet run
Output
ubuntu@ip-172-31-44-31:~/dotnet-simple$ sudo dotnet build
MSBuild version 17.8.5+b5265ef37 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
dotnet-simple -> /home/ubuntu/dotnet-simple/bin/Debug/net8.0/dotnet-simple.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:01.84
ubuntu@ip-172-31-44-31:~/dotnet-simple$ dotnet run
Building...
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5277
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/ubuntu/dotnet-simple
^Cinfo: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
Enter the below URL in your web browser to verify it is working.
http://localhost:8080/rolldice OR http://server_IP:8080/rolldice
Output
ubuntu@ip-172-31-35-192:~/dotnet-simple$ sudo dotnet build
MSBuild version 17.8.5+b5265ef37 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
dotnet-simple -> /home/ubuntu/dotnet-simple/bin/Debug/net8.0/dotnet-simple.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:01.92
ubuntu@ip-172-31-35-192:~/dotnet-simple$ dotnet run
Building...
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://0.0.0.0:8080
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/ubuntu/dotnet-simple
info: Program[0]
Anonymous player is rolling the dice: 6
info: Program[0]
Anonymous player is rolling the dice: 3
info: Program[0]
Anonymous player is rolling the dice: 4
info: Program[0]
Anonymous player is rolling the dice: 5
info: Program[0]
Anonymous player is rolling the dice: 6
info: Program[0]
Anonymous player is rolling the dice: 3
info: Program[0]
Anonymous player is rolling the dice: 5
info: Program[0]
Anonymous player is rolling the dice: 5
info: Program[0]
Anonymous player is rolling the dice: 3
info: Program[0]
Anonymous player is rolling the dice: 2
Integrate OpenTelemetry for .NET Application
To add OpenTelemetry to your .NET app, install the right NuGet packages for the technologies and parts you want to monitor. There are common packages for ASP.NET Core and general .NET apps.
Use the following commands to install packages for automatic instrumentation in ASP.NET Core applications, and add the packages.
sudo dotnet add package OpenTelemetry.Extensions.Hosting
sudo dotnet add package OpenTelemetry.Instrumentation.AspNetCore
sudo dotnet add package OpenTelemetry.Exporter.Console
To set up OpenTelemetry, replace specific lines in Program.cs.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
with below code
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
const string serviceName = "roll-dice";
builder.Logging.AddOpenTelemetry(options =>
{
options
.SetResourceBuilder(
ResourceBuilder.CreateDefault()
.AddService(serviceName))
.AddConsoleExporter();
});
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource => resource.AddService(serviceName))
.WithTracing(tracing => tracing
.AddAspNetCoreInstrumentation()
.AddConsoleExporter())
.WithMetrics(metrics => metrics
.AddAspNetCoreInstrumentation()
.AddConsoleExporter());
var app = builder.Build();
Run your application once again.
sudo dotnet build
sudo dotnet run
Capture Traces, Logs and Metrics for .NET Application by OpenTelemetry
Open in another terminal, send a request using curl
or you can access using browser
curl localhost:8080/rolldice
After about 30 sec, stop the server process.
At this point, you should see trace and log output from the server and client, formatted for readability.
Resource associated with LogRecord:
service.name: roll-dice
service.instance.id: a6c600b1-5c24-4468-8b7f-e27deed442a2
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.9.0
Resource associated with Metric:
service.name: roll-dice
service.instance.id: a6c600b1-5c24-4468-8b7f-e27deed442a2
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.9.0
Unhandled exception. System.IO.IOException: Failed to bind to address http://0.0.0.0:8080: address already in use.
---> Microsoft.AspNetCore.Connections.AddressInUseException: Address already in use
---> System.Net.Sockets.SocketException (98): Address already in use
at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, Boolean disconnectOnFailure, String callerName)
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportOptions.CreateDefaultBoundListenSocket(EndPoint endpoint)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.Bind()
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.Bind()
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportFactory.BindAsync(EndPoint endpoint, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.TransportManager.BindAsync(EndPoint endPoint, ConnectionDelegate connectionDelegate, EndpointConfig endpointConfig, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<>c__DisplayClass28_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(ListenOptions[] listenOptions, AddressBindContext context, Func`2 useHttps, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>b__15_1(IHostedService service, CancellationToken token)
at Microsoft.Extensions.Hosting.Internal.Host.ForeachService[T](IEnumerable`1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List`1 exceptions, Func`3 operation)
at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
at Program.<Main>$(String[] args) in /home/ubuntu/dotnet-simple/Program.cs:line 55
When you click the refresh button, it rolls the dice and shows a number, as you saw in the output above.
Subscribe to my newsletter
Read articles from Ankita Lunawat directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Ankita Lunawat
Ankita Lunawat
I am a dedicated and experienced Cloud Engineer with two years in the industry, specializing in designing, implementing, and managing scalable and secure cloud infrastructures. With a strong foundation in AWS, Azure, and GCP, I excel at leveraging cloud services to optimize performance, enhance security, and reduce operational costs. My expertise includes automated deployment pipelines, infrastructure as code (IaC) with tools like Terraform and container orchestration using Kubernetes and Docker. Throughout my career, I've collaborated with cross-functional teams to deliver robust cloud solutions, ensuring high availability and fault tolerance. I'm passionate about staying at the forefront of cloud technology trends and continuously enhancing my skill set to provide innovative solutions that drive business success. Whether it's migrating legacy systems to the cloud or architecting new cloud-native applications, I bring a strategic approach to every project, focusing on efficiency, scalability, and reliability. In addition to my technical skills, I am an advocate for DevOps practices, promoting a culture of collaboration and continuous improvement within development and operations teams. My commitment to learning and adapting to new technologies ensures that I can meet the evolving needs of any organization and deliver top-tier cloud solutions.