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
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.
Add the OpenTelemetry SDK and supporting packages:
$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
Create two environment variables that you use to configure your OpenTelemetry pipelines. Don't forget to replace the placeholders with real values:
$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.
In app/Program.cs, create a resource builder:
1using OpenTelemetry.Resources;2
3var builder = WebApplication.CreateBuilder(args);4
5builder.Services.AddControllers();6builder.Services.AddEndpointsApiExplorer();7builder.Services.AddSwaggerGen();8
9var resourceBuilder = ResourceBuilder10 .CreateDefault()11 .AddService("Weather-Forecast")12 .AddAttributes(new Dictionary<string, object> {13 { "environment", "production" }14 })15 .AddTelemetrySdk();16
17var app = builder.Build();18
19if (app.Environment.IsDevelopment())20{21 app.UseSwagger();22 app.UseSwaggerUI();23}24
25app.UseHttpsRedirection();26
27app.UseAuthorization();28
29app.MapControllers();30
31app.Run();
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.
Configure the OpenTelemetry SDK for traces:
1using OpenTelemetry.Resources;2using OpenTelemetry.Trace;3
4var builder = WebApplication.CreateBuilder(args);5
6builder.Services.AddControllers();7builder.Services.AddEndpointsApiExplorer();8builder.Services.AddSwaggerGen();9
10var resourceBuilder = ResourceBuilder11 .CreateDefault()12 .AddService("Weather-Forecast")13 .AddAttributes(new Dictionary<string, object> {14 { "environment", "production" }15 })16 .AddTelemetrySdk();17
18builder.Services.AddOpenTelemetryTracing(tracerProviderBuilder =>19{20 tracerProviderBuilder21 .SetResourceBuilder(resourceBuilder);22
23 tracerProviderBuilder24 .AddAspNetCoreInstrumentation(options =>25 {26 options.RecordException = true;27 options.Filter = (context) =>28 {29 return context.Request.Method == "GET";30 };31 });32
33 tracerProviderBuilder34 .AddSource("WeatherForecast");35
36 tracerProviderBuilder37 .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
44var app = builder.Build();45
46if (app.Environment.IsDevelopment())47{48 app.UseSwagger();49 app.UseSwaggerUI();50}51
52app.UseHttpsRedirection();53
54app.UseAuthorization();55
56app.MapControllers();57
58app.Run();
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.
Configure the OpenTelemetry SDK for metrics:
1using OpenTelemetry.Metrics;2using OpenTelemetry.Resources;3using OpenTelemetry.Trace;4
5var builder = WebApplication.CreateBuilder(args);6
7builder.Services.AddControllers();8builder.Services.AddEndpointsApiExplorer();9builder.Services.AddSwaggerGen();10
11var resourceBuilder = ResourceBuilder12 .CreateDefault()13 .AddService("Weather-Forecast")14 .AddAttributes(new Dictionary<string, object> {15 { "environment", "production" }16 })17 .AddTelemetrySdk();18
19builder.Services.AddOpenTelemetryTracing(tracerProviderBuilder =>20{21 tracerProviderBuilder22 .SetResourceBuilder(resourceBuilder);23
24 tracerProviderBuilder25 .AddAspNetCoreInstrumentation(options =>26 {27 options.RecordException = true;28 options.Filter = (context) =>29 {30 return context.Request.Method == "GET";31 };32 });33
34 tracerProviderBuilder35 .AddSource("WeatherForecast");36
37 tracerProviderBuilder38 .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
45builder.Services.AddOpenTelemetryMetrics(meterProviderBuilder =>46{47 meterProviderBuilder48 .SetResourceBuilder(resourceBuilder);49
50 meterProviderBuilder51 .AddAspNetCoreInstrumentation();52
53 meterProviderBuilder54 .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
62var app = builder.Build();63
64if (app.Environment.IsDevelopment())65{66 app.UseSwagger();67 app.UseSwaggerUI();68}69
70app.UseHttpsRedirection();71
72app.UseAuthorization();73
74app.MapControllers();75
76app.Run();
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.
Restart it:
$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 .NETCopyright (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.dllBuild succeeded. 0 Warning(s) 0 Error(s)Time Elapsed 00:00:01.16Building...info: Microsoft.Hosting.Lifetime[14] Now listening on: https://localhost:7072info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down.info: Microsoft.Hosting.Lifetime[0] Hosting environment: Developmentinfo: 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.
In the terminal window where you ran your load generator, restart it:
$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.