Skip to content

Commit f5d54b5

Browse files
authored
Add Application Insights telemetry example (#1778)
1 parent ce0cf91 commit f5d54b5

4 files changed

Lines changed: 66 additions & 3 deletions

File tree

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
<!-- Testing dependencies -->
6565
<ItemGroup>
6666
<PackageVersion Include="Anthropic" Version="12.39.0" />
67+
<PackageVersion Include="Azure.Monitor.OpenTelemetry.AspNetCore" Version="1.6.0" />
6768
<PackageVersion Include="coverlet.collector" Version="10.0.1">
6869
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
6970
<PrivateAssets>all</PrivateAssets>

samples/AspNetCoreMcpServer/AspNetCoreMcpServer.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
</ItemGroup>
1616

1717
<ItemGroup>
18+
<PackageReference Include="Azure.Monitor.OpenTelemetry.AspNetCore" />
1819
<PackageReference Include="OpenTelemetry" />
1920
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
2021
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />

samples/AspNetCoreMcpServer/Program.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Azure.Monitor.OpenTelemetry.AspNetCore;
12
using OpenTelemetry;
23
using OpenTelemetry.Metrics;
34
using OpenTelemetry.Trace;
@@ -34,15 +35,27 @@
3435
.WithTools<WeatherTools>()
3536
.WithResources<SimpleResourceType>();
3637

37-
builder.Services.AddOpenTelemetry()
38+
var telemetry = builder.Services.AddOpenTelemetry()
3839
.WithTracing(b => b.AddSource("*")
3940
.AddAspNetCoreInstrumentation()
4041
.AddHttpClientInstrumentation())
4142
.WithMetrics(b => b.AddMeter("*")
4243
.AddAspNetCoreInstrumentation()
4344
.AddHttpClientInstrumentation())
44-
.WithLogging()
45-
.UseOtlpExporter();
45+
.WithLogging();
46+
47+
string? applicationInsightsConnectionString =
48+
builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"];
49+
50+
if (string.IsNullOrWhiteSpace(applicationInsightsConnectionString))
51+
{
52+
telemetry.UseOtlpExporter();
53+
}
54+
else
55+
{
56+
telemetry.UseAzureMonitor(options =>
57+
options.ConnectionString = applicationInsightsConnectionString);
58+
}
4659

4760
// Configure HttpClientFactory for weather.gov API
4861
builder.Services.AddHttpClient("WeatherApi", client =>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# ASP.NET Core MCP server sample
2+
3+
This sample hosts an MCP server with Streamable HTTP and configures OpenTelemetry for MCP operations, ASP.NET Core requests, outgoing HTTP requests, metrics, and structured logs.
4+
5+
## Export to Application Insights
6+
7+
Set the Application Insights connection string and run the sample:
8+
9+
```bash
10+
export APPLICATIONINSIGHTS_CONNECTION_STRING='InstrumentationKey=<your-instrumentation-key>;IngestionEndpoint=https://<region>.in.applicationinsights.azure.com/'
11+
dotnet run --project samples/AspNetCoreMcpServer
12+
```
13+
14+
PowerShell:
15+
16+
```powershell
17+
$env:APPLICATIONINSIGHTS_CONNECTION_STRING = 'InstrumentationKey=<your-instrumentation-key>;IngestionEndpoint=https://<region>.in.applicationinsights.azure.com/'
18+
dotnet run --project samples/AspNetCoreMcpServer
19+
```
20+
21+
The connection string is read through ASP.NET Core configuration. Keep it outside source control and use your deployment platform's secret configuration in production.
22+
23+
When `APPLICATIONINSIGHTS_CONNECTION_STRING` is absent or empty, the sample retains its default OTLP exporter. Configure that path with standard `OTEL_EXPORTER_OTLP_*` environment variables.
24+
25+
## Signals and MCP attributes
26+
27+
Application Insights receives the signals already emitted by the SDK and the configured ASP.NET Core/OpenTelemetry instrumentation:
28+
29+
- server activities appear as requests and client activities appear as dependencies;
30+
- structured logs appear as traces;
31+
- MCP histograms appear as custom metrics;
32+
- HTTP server and client instrumentation provides the surrounding transport spans.
33+
34+
MCP activities can include attributes such as `mcp.method.name`, `mcp.protocol.version`, `mcp.session.id`, `jsonrpc.request.id`, and `gen_ai.tool.name`. The exact attributes depend on the operation and whether sensitive-data telemetry is enabled.
35+
36+
For example, query MCP request and dependency telemetry in Logs:
37+
38+
```kusto
39+
union withsource=TelemetryType requests, dependencies
40+
| extend McpMethod = tostring(customDimensions["mcp.method.name"]),
41+
ToolName = tostring(customDimensions["gen_ai.tool.name"]),
42+
McpSession = tostring(customDimensions["mcp.session.id"])
43+
| where isnotempty(McpMethod)
44+
| project timestamp, TelemetryType, name, success, resultCode, McpMethod, ToolName, McpSession
45+
| order by timestamp desc
46+
```
47+
48+
Invalid tool calls, malformed JSON-RPC messages, and other failures appear only when the current SDK or ASP.NET Core instrumentation emits a log or activity for that path. This sample exports existing telemetry; it does not add custom protocol events or per-tool instrumentation.

0 commit comments

Comments
 (0)