Introduction
In the world of software programming, you certainly faced issues related to performance and spent a considerable amount of time looking for the root cause.
Especially when you use third-party libraries and you don't have an idea about how they were developed. To avoid this, you can anticipate the monitoring of your web API and provide the administrators of your services enough information about the state during the execution.
Telemetry is a very rich field. In this article, I will give you the first concepts that will help you implement your telemetry in your Web API
What is telemetry?
Telemetry is the ability of a service to provide accurate data about its performance and the resources that it consumes. This will help to identify issues and make data-driven improvements.
In Asp .net Core API there are several ways to provide data about performance. You can simply do it by exporting your data into Txt files or event log viewer, you can also inspect the calls using the browser debugger. But telemetry will allow you to control your API, analyze exactly the piece of code that you need, and present the data more elegantly with tools that provide clear dashboards. Some of these tools are prometheus, jaeger, Grafana, signoz ...
The way it works is that you should include a telemetry "exporter" in your API, and then it will be able to expose the telemetry data in a usable way by the external tools.
Let's see how to do it.
Prerequisite
- Visual Studio 2022
- OpenTelemtry Nuget Packages
- Jaeger for Windows can be downloaded from the following URL-https://www.jaegertracing.io/download/.
Create a new project
Open Visual Studio 2022 then create a new ASP net core web Api project
Follow the instructions then choose the right installed version of .net core.
I'm using 7.0 but it should work with a lower version
Nuget packages
To be able to use the feature that openTelemtry offers with Jaeger, you need to install some packages related to telemetry.
You can copy and paste the following one to your .csproj and the packages will be restored automatically when you build.
<PackageReference Include="OpenTelemetry" Version="1.2.0-rc4" />
<PackageReference Include="OpenTelemetry.Api" Version="1.2.0-rc4" />
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.2.0-rc4" />
<PackageReference Include="OpenTelemetry.Exporter.Jaeger" Version="1.2.0-rc4" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.2.0-rc4" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.0.0-rc9.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.0.0-rc9.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc9.1" />
Call the instrumentation and exporter methods
Once you referenced the needed packages, you need to initialize the OpenTelemetry tracing and instrumentation by doing the following calls in your program.cs
As you can see, we are initializing a Jaeger exporter, which means that our service will expose the telemetry data in a way that Jaeger can understand it
builder.Services.AddOpenTelemetryTracing(options =>
options.AddConsoleExporter()
.AddSource(TestTelemetryController.TelemtrySource)
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService(TestTelemetryController.TelemtrySource)
.AddTelemetrySdk())
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation()
.AddJaegerExporter()
);
builder.Services.AddOpenTelemetryMetrics(options =>
options.AddHttpClientInstrumentation()
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService(TestTelemetryController.TelemtrySource)
.AddTelemetrySdk())
.AddMeter("Meter1")
.AddOtlpExporter()
);
Create your controller and trace the calls
Now you can create your controller and monitor the activity of your code.
You can add tags with data to trace the behavior of a specific part in your controller and then you will be able to visualize it in Jaeger due to the Jaeger exporter.
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System.Diagnostics;
using System.Diagnostics.Metrics;
namespace TelemtryUsingJaeger.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TestTelemetryController : ControllerBase
{
//You can move this into a helper or any other class
public const string TelemetrySource = "TestTelemetry";
[HttpGet]
public void Get()
{
//Create the Activity source
ActivitySource _source = new ActivitySource(TelemetrySource);
using (var activity = _source.StartActivity("FirstCallActivity"))
{
//Add a tag to store the data in the activity
//For example the time before the current call
DateTime d1 = DateTime.Now;
activity?.SetTag("TimeOfCall", d1.ToString());
//This sleep will simulate the processing of your method
//It could be a third party that you want to monitor
Thread.Sleep(1000);
DateTime d2 = DateTime.Now;
//Add a tag to store the data in the activity
//For example the time after the current call
activity?.SetTag("TimeAfterCall", d2.ToString());
//A calculation can be added also
activity?.SetTag("CallDuration", d2 - d1);
}
//Do the same previous thing with a second activity
using (var activity = _source.StartActivity("SecondCallActivity"))
{
DateTime d1 = DateTime.Now;
activity?.SetTag("TimeOfCall", d1.ToString());
Thread.Sleep(1500);
DateTime d2 = DateTime.Now;
activity?.SetTag("TimeAfterCall", d2.ToString());
activity?.SetTag("CallDuration", d2 - d1);
}
}
}
}
Launch jaeger
When you download Jaeger, you should have the following folder, navigate to it using the command line then launch thejaeger-all-in-one.exe.
If you get a security alert, click "Allow".
You should have the service listening on port16686
Now go to the browser and typehttp://localhost:16686/search, you should get the Jaeger UI.
Perform a call from the API
Now call the monitored method using your swagger, all the traces that we did in the code should appear in Jaeger
Check Jaeger
Now if you recheck Jaeger, you will find the data related to our API.
Let's check in detail the call that has 3 spans and we will see that every span corresponds to an operation that we specified in our code.
We can see that the three spans are the main Api call and the two activities that we set explicitly in the code.
We can also the tags that we set in the code with their values
Conclusion
Telemetry is one of the tools that allows you to have a clear visibility of the performance of the technical activities of your API.
If you know other ways to do it feel free to suggest them in the comments