OpenTelemetry .NET Core Configuration
Ship traces from ASP.Net Core to OpenSearch with OpenTelemetry
Use OpenTelemetry to easily send .NET Core traces to your Logit.io Stack.
Install Integration
Install
Create a new 'ASP.NET Core Empty' application and use the Nuget Package Manager or the
command line to add the following OpenTelemetry packages to the application.
Below is what the .csproj
ItemGroup
element will look like once installed.
<ItemGroup>
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0" />
</ItemGroup>
The package versions shown above were the latest at the time of writing but as the .NET Core / 5+ OpenTelemetry APIs are still in development they could have been updated in the meantime.
Configuring AppSettings
Add OpenTelemetry settings to your appsettings.json
file:
You will need to update any placeholder variables with your OpenTelemetry details.
"OpenTelemetry": {
"ServiceName": "Open Telemetry Tracing - Test App",
"OTLP_ENDPOINT_URL": "https://@opentelemetry.endpointAddress",
"Protocol": "@protocol",
"Port": "@port",
"Username": "@opentelemetry.username",
"Password": "@opentelemetry.password"
}
Using OpenTelemetry
Copy and Paste the code below into Program.cs
. This code is based on the demonstration
code used in the Microsoft article found here (opens in a new tab)
which also contains additional useful information about using OpenTelemetry with .NET.
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System.Diagnostics;
using System.Text;
using OpenTelemetry.Exporter;
var builder = WebApplication.CreateBuilder(args);
// Custom ActivitySource for the application
var greeterActivitySource = new ActivitySource("OtJa.Example");
var config = builder.Configuration;
var openTelemetryCongfig = config.GetSection("OpenTelemetry");
var serviceName = openTelemetryCongfig.GetValue<string>("ServiceName");
var tracingOtlpEndpoint = openTelemetryCongfig.GetValue<string>("OTLP_ENDPOINT_URL");
var tracingOtlpProtocol = openTelemetryCongfig.GetValue<string>("Protocol");
var tracingOtlpPort = openTelemetryCongfig.GetValue<string>("Port");
var tracingUsername = openTelemetryCongfig.GetValue<string>("Username");
var tracingPassword = openTelemetryCongfig.GetValue<string>("Password");
var otel = builder.Services.AddOpenTelemetry();
// Configure OpenTelemetry Resources with the service name
if (serviceName is null)
{
serviceName = "Logit.NetTestApp";
}
otel.ConfigureResource(resource => resource
.AddService(serviceName: serviceName));
// Add Tracing for ASP.NET Core and our custom ActivitySource and export to Jaeger
otel.WithTracing(tracing =>
{
tracing.AddAspNetCoreInstrumentation();
tracing.AddHttpClientInstrumentation();
tracing.AddSource(greeterActivitySource.Name);
if (tracingOtlpEndpoint != null)
{
tracing.AddOtlpExporter(otlpOptions =>
{
if (tracingOtlpPort is not null)
{
tracingOtlpEndpoint += ":" + tracingOtlpPort;
}
otlpOptions.Endpoint = new Uri(tracingOtlpEndpoint);
otlpOptions.Protocol = tracingOtlpProtocol!.ToLower() == "grpc" ? OtlpExportProtocol.Grpc : OtlpExportProtocol.HttpProtobuf;
string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{tracingUsername}:{tracingPassword}"));
otlpOptions.Headers = "Authorization = Basic " + credentials;
});
}
else
{
tracing.AddConsoleExporter();
}
});
builder.Services.AddHttpClient();
var app = builder.Build();
app.MapGet("/", SendGreeting);
app.MapGet("/NestedGreeting", SendNestedGreeting);
app.Run();
async Task<string> SendGreeting(ILogger<Program> logger)
{
// Create a new Activity scoped to the method
using var activity = greeterActivitySource.StartActivity("GreeterActivity");
// Log a message
logger.LogInformation("Sending greeting");
// Add a tag to the Activity
activity?.SetTag("greeting", "Hello World!");
return "Hello World!";
}
async Task SendNestedGreeting(int nestlevel, ILogger<Program> logger, HttpContext context, IHttpClientFactory clientFactory)
{
// Create a new Activity scoped to the method
using var activity = greeterActivitySource.StartActivity("GreeterActivity");
if (nestlevel <= 5)
{
// Log a message
logger.LogInformation("Sending greeting, level {nestlevel}", nestlevel);
// Add a tag to the Activity
activity?.SetTag("nest-level", nestlevel);
await context.Response.WriteAsync($"Nested Greeting, level: {nestlevel}\r\n");
if (nestlevel > 0)
{
var request = context.Request;
var url = new Uri($"{request.Scheme}://{request.Host}{request.Path}?nestlevel={nestlevel - 1}");
// Makes an http call passing the activity information as http headers
var nestedResult = await clientFactory.CreateClient().GetStringAsync(url);
await context.Response.WriteAsync(nestedResult);
}
}
else
{
// Log a message
logger.LogError("Greeting nest level {nestlevel} too high", nestlevel);
await context.Response.WriteAsync("Nest level too high, max is 5");
}
}
Run the application and two traces will have been sent to your Stack.
Launch Logit.io to view your traces
Launch APMHow to diagnose no data in Stack
If you don't see data appearing in your stack after following this integration, take a look at the troubleshooting guide for steps to diagnose and resolve the problem or contact our support team and we'll be happy to assist.
.NET Core Traces Overview
.NET Core is an open-source platform created by Microsoft for development across Linux, macOS & Windows and makes .NET run as a cross-platform framework. It can be used to write APIs, and ASP.NET websites.
Tracing & tailing logs for .NET Core can often encounter difficulties when debugging over longer time periods. If these log messages are being recorded across distributed environments then it can make centralising your logs nearly impossible for logging analysis and management at scale.
The Logit.io platform offers hosted OpenSearch (opens in a new tab) which makes visualising .NET Core log instances far more streamlined than comparable logging solutions. We believe that monitoring & analysis play a crucial role in maintaining the health of your applications across the cloud & on-premise.
If you need any help with migrating your .NET Core traces to OpenSearch we are here to help. Feel free to get in contact with our support team by sending us a message via live chat and we'll be happy to assist.