Copy as Markdown[Open in ChatGPT](https://chatgpt.com/?q=Read%20https%3A%2F%2Fdocs-docusaurus.kinsta.page%2Fuser-guides%2Fai%2Fotel-integration%2Fcode-examples%2Fdotnet.md%20and%20help%20me%20with%20my%20question%20about%20this%20Coralogix%20documentation%20page.)[Open in Claude](https://claude.ai/new?q=Read%20https%3A%2F%2Fdocs-docusaurus.kinsta.page%2Fuser-guides%2Fai%2Fotel-integration%2Fcode-examples%2Fdotnet.md%20and%20help%20me%20with%20my%20question%20about%20this%20Coralogix%20documentation%20page.)

# .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](https://docs-docusaurus.kinsta.page/user-guides/ai/otel-integration/code-examples/.md#prerequisites-deploy-an-opentelemetry-collector).

## Install[​](#install "Direct link to 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[​](#environment-variables "Direct link to Environment variables")

```
export OPENAI_API_KEY="sk-..."

export CX_OTEL_ENDPOINT="http://<COLLECTOR_HOST>:4317"
```

## Script (`Program.cs`)[​](#script-programcs "Direct link to script-programcs")

```
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[​](#next-steps "Direct link to Next steps")

Look up which open-source library to use for your provider in [Compatibility matrix](https://docs-docusaurus.kinsta.page/user-guides/ai/otel-integration/providers/.md).
