.NET — Microsoft.Extensions.AI
Microsoft.Extensions.AI natively implements new semconv v1.37. No opt-in needed.
Before you start
These examples export to a local OpenTelemetry Collector over OTLP/gRPC. Deploy the collector first — see Code examples → Deploy an OpenTelemetry Collector.
Install
dotnet new console -n OtelGenAiDotnet && cd OtelGenAiDotnet
dotnet add package Microsoft.Extensions.AI.OpenAI --version 10.5.1
dotnet add package Microsoft.Extensions.AI --version 10.5.2
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol --version 1.15.3
dotnet add package OpenTelemetry.Extensions.Hosting --version 1.15.3
Environment variables
Script (Program.cs)
using Microsoft.Extensions.AI;
using OpenAI;
// --- OTel imports ---
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
var cxEndpoint = Environment.GetEnvironmentVariable("CX_OTEL_ENDPOINT")
?? "http://<COLLECTOR_HOST>:4317";
var openAiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
?? throw new InvalidOperationException("OPENAI_API_KEY required");
// --- OTel setup: configure tracer provider with OTLP exporter ---
const string sourceName = "GenAI.Demo";
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService("dotnet-genai-demo")
.AddAttributes(new Dictionary<string, object> {
["cx.application.name"] = "my-genai-app",
["cx.subsystem.name"] = "my-service",
}))
.AddSource(sourceName)
.AddOtlpExporter(opts => {
opts.Endpoint = new Uri(cxEndpoint);
opts.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
})
.Build();
// --- Your app logic: create chat client with OTel auto-instrumentation ---
IChatClient chatClient = new ChatClientBuilder(
new OpenAIClient(openAiKey).GetChatClient("gpt-4o-mini").AsIChatClient())
.UseOpenTelemetry(sourceName: sourceName, // OTel: enables GenAI span emission
configure: c => c.EnableSensitiveData = true) // OTel: captures message content
.Build();
var response = await chatClient.GetResponseAsync(
new List<ChatMessage> {
new(ChatRole.System, "You are a concise assistant."),
new(ChatRole.User, "What is OpenTelemetry in one sentence?"),
},
new ChatOptions { MaxOutputTokens = 100, Temperature = 0.7f });
Console.WriteLine($"Response: {response.Text}");
Console.WriteLine($"Tokens: {response.Usage?.InputTokenCount} in, {response.Usage?.OutputTokenCount} out");
Tip
EnableSensitiveData = true is required for message content. The IChatClient abstraction works with any provider (Azure OpenAI, Ollama, etc.).
Next steps
Look up which open-source library to use for your provider in Compatibility matrix.
Theme
Light