• Log inStart now

Instrument your application with OpenTelemetry

5 min

lab

This procedure is part of a lab that teaches you how to instrument your application with OpenTelemetry.

Each procedure in the lab builds upon the last, so make sure you've completed the last procedure, Set up your lab environment, before starting this one.

Your .NET application is running and is getting a lot of traffic. You want to instrument it with OpenTelemetry because it lets you avoid being locked into a single vendor, it's open source, and it's supported by many actors in the observability space.

Here, you learn how easy it is to configure the OpenTelemetry SDK to automatically collect metrics and traces from your application and send them to New Relic so you can analyze the results later.

Instrument your application

Step 1 of 6

In the terminal window that's running your development server, press <CTRL-C>.

You should see your server shut down. Now you can add some dependencies and update your app logic.

Step 2 of 6

Add the OpenTelemetry SDK and supporting packages:

bash
$
dotnet add app package --prerelease OpenTelemetry
$
dotnet add app package --prerelease OpenTelemetry.Instrumentation.AspNetCore
$
dotnet add app package --prerelease OpenTelemetry.Exporter.OpenTelemetryProtocol
$
dotnet add app package --prerelease OpenTelemetry.Extensions.Hosting
Step 3 of 6

Create two environment variables that you use to configure your OpenTelemetry pipelines. Don't forget to replace the placeholders with real values:

bash
$
export OTEL_EXPORTER_OTLP_ENDPOINT=<REGION-BASED-OTLP-ENDPOINT>
$
export NR_LICENSE_KEY=<YOUR-NEW-RELIC-LICENSE-KEY>

The OpenTelemetry Protocol (OTLP) endpoint is the url of our OpenTelemetry receiver. Your service sends data directly to New Relic through this endpoint. We have a US endpoint and an EU endpoint, so make sure you choose the appropriate one based on your region.

There are several different types of API keys to choose from in New Relic that each serve a different purpose. To instrument your application with OpenTelemetry, you need a license key.

Step 4 of 6

In app/Program.cs, create a resource builder:

1
using OpenTelemetry.Resources;
2
3
var builder = WebApplication.CreateBuilder(args);
4
5
builder.Services.AddControllers();
6
builder.Services.AddEndpointsApiExplorer();
7
builder.Services.AddSwaggerGen();
8
9
var resourceBuilder = ResourceBuilder
10
.CreateDefault()
11
.AddService("Weather-Forecast")
12
.AddAttributes(new Dictionary<string, object> {
13
{ "environment", "production" }
14
})
15
.AddTelemetrySdk();
16
17
var app = builder.Build();
18
19
if (app.Environment.IsDevelopment())
20
{
21
app.UseSwagger();
22
app.UseSwaggerUI();
23
}
24
25
app.UseHttpsRedirection();
26
27
app.UseAuthorization();
28
29
app.MapControllers();
30
31
app.Run();
app/Program.cs

An OpenTelemetry resource describes a service as a collection of attributes.

Here, on top of the default resource attributes, you define a service name and an environment. You also call AddTelemetrySdk(), which adds a suite of standard attributes defined within OpenTelemetry's sematic conventions such as:

  • telemetry.sdk.name
  • telemetry.sdk.language
  • telemetry.sdk.version

This is important because it helps New Relic present you with an experience that's tailored to your application.

You configure your telemetry pipelines with this resource builder. That way, these attributes are associated with all metrics and traces that this service generates.

Step 5 of 6

Configure the OpenTelemetry SDK for traces:

1
using OpenTelemetry.Resources;
2
using OpenTelemetry.Trace;
3
4
var builder = WebApplication.CreateBuilder(args);
5
6
builder.Services.AddControllers();
7
builder.Services.AddEndpointsApiExplorer();
8
builder.Services.AddSwaggerGen();
9
10
var resourceBuilder = ResourceBuilder
11
.CreateDefault()
12
.AddService("Weather-Forecast")
13
.AddAttributes(new Dictionary<string, object> {
14
{ "environment", "production" }
15
})
16
.AddTelemetrySdk();
17
18
builder.Services.AddOpenTelemetryTracing(tracerProviderBuilder =>
19
{
20
tracerProviderBuilder
21
.SetResourceBuilder(resourceBuilder);
22
23
tracerProviderBuilder
24
.AddAspNetCoreInstrumentation(options =>
25
{
26
options.RecordException = true;
27
options.Filter = (context) =>
28
{
29
return context.Request.Method == "GET";
30
};
31
});
32
33
tracerProviderBuilder
34
.AddSource("WeatherForecast");
35
36
tracerProviderBuilder
37
.AddOtlpExporter(options =>
38
{
39
options.Endpoint = new Uri($"{Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT")}");
40
options.Headers = $"api-key={Environment.GetEnvironmentVariable("NR_LICENSE_KEY")}";
41
});
42
});
43
44
var app = builder.Build();
45
46
if (app.Environment.IsDevelopment())
47
{
48
app.UseSwagger();
49
app.UseSwaggerUI();
50
}
51
52
app.UseHttpsRedirection();
53
54
app.UseAuthorization();
55
56
app.MapControllers();
57
58
app.Run();
app/Program.cs

AddOpenTelemetryTracing() takes a delegate that builds a tracer provider that, in turn, automatically provides traces to your OpenTelemetry exporter.

First in configuring your tracer provider, you specify the resource builder you created in the last step. This ties the attributes you previously defined to all traces from your service. Next, with tracerProviderBuilder.AddAspNetCoreInstrumentation(), you configure the SDK to listen to auto-instrumentation. You also tell it to record exceptions and only track GET requests. Finally, you configure the OTLP exporter to export traces to New Relic using the environment variables you defined earlier.

Step 6 of 6

Configure the OpenTelemetry SDK for metrics:

1
using OpenTelemetry.Metrics;
2
using OpenTelemetry.Resources;
3
using OpenTelemetry.Trace;
4
5
var builder = WebApplication.CreateBuilder(args);
6
7
builder.Services.AddControllers();
8
builder.Services.AddEndpointsApiExplorer();
9
builder.Services.AddSwaggerGen();
10
11
var resourceBuilder = ResourceBuilder
12
.CreateDefault()
13
.AddService("Weather-Forecast")
14
.AddAttributes(new Dictionary<string, object> {
15
{ "environment", "production" }
16
})
17
.AddTelemetrySdk();
18
19
builder.Services.AddOpenTelemetryTracing(tracerProviderBuilder =>
20
{
21
tracerProviderBuilder
22
.SetResourceBuilder(resourceBuilder);
23
24
tracerProviderBuilder
25
.AddAspNetCoreInstrumentation(options =>
26
{
27
options.RecordException = true;
28
options.Filter = (context) =>
29
{
30
return context.Request.Method == "GET";
31
};
32
});
33
34
tracerProviderBuilder
35
.AddSource("WeatherForecast");
36
37
tracerProviderBuilder
38
.AddOtlpExporter(options =>
39
{
40
options.Endpoint = new Uri($"{Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT")}");
41
options.Headers = $"api-key={Environment.GetEnvironmentVariable("NR_LICENSE_KEY")}";
42
});
43
});
44
45
builder.Services.AddOpenTelemetryMetrics(meterProviderBuilder =>
46
{
47
meterProviderBuilder
48
.SetResourceBuilder(resourceBuilder);
49
50
meterProviderBuilder
51
.AddAspNetCoreInstrumentation();
52
53
meterProviderBuilder
54
.AddOtlpExporter(options =>
55
{
56
options.Endpoint = new Uri($"{Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT")}");
57
options.Headers = $"api-key={Environment.GetEnvironmentVariable("NR_LICENSE_KEY")}";
58
options.AggregationTemporality = AggregationTemporality.Delta;
59
});
60
});
61
62
var app = builder.Build();
63
64
if (app.Environment.IsDevelopment())
65
{
66
app.UseSwagger();
67
app.UseSwaggerUI();
68
}
69
70
app.UseHttpsRedirection();
71
72
app.UseAuthorization();
73
74
app.MapControllers();
75
76
app.Run();
app/Program.cs

Besides configuring a MetricsProviderBuilder, this is mostly the same as how you configured tracing.

There is one important detail, however. Currently, New Relic only supports sending metrics over OTLP using delta aggregation temporality. The SDK's default aggregation temporality is cumulative, so you specify Delta here.

Restart your application

Now that you've changed the application logic, you need to restart your local server. Make sure you do this in the same terminal window where you set your environment variables.

Step 1 of 2

Restart it:

bash
$
dotnet restore app
$
dotnet build app
$
dotnet run --project app
Determining projects to restore...
All projects are up-to-date for restore.
Microsoft (R) Build Engine version 17.0.0+c9eb9dd64 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
All projects are up-to-date for restore.
opentelemetry-dotnet-lab-materials -> /workspace/opentelemetry-dotnet-lab-materials/app/bin/Debug/net6.0/app.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:01.16
Building...
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:7072
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: /workspace/opentelemetry-dotnet-lab-materials/app/
info: Microsoft.Hosting.Lifetime[0]

Now, your server is running again. However, because you shut it down, your load generator might have failed, having been unable to find your app. If it's no longer running, restart that too.

Step 2 of 2

In the terminal window where you ran your load generator, restart it:

bash
$
python simulator.py

You've instrumented your application to send metrics and traces to New Relic using our OTLP receiver. You've also restarted your service and load generator. Now, it's time to view your data.

lab

This procedure is part of a lab that teaches you how to instrument your application with OpenTelemetry. Now that you've set up your environment, view your telemetry data in New Relic.

Copyright © 2024 New Relic Inc.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.