Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void InitializeConfigurationAndOptions_Defaults()
var services = SetupBaseServices();

// Act
ServiceCollectionExtensions.InitializeConfigurationAndOptions(services);
ServiceCollectionExtensions.InitializeConfigurationOptionsAndOpenTelemetry(services);

// Assert
var provider = services.BuildServiceProvider();
Expand Down Expand Up @@ -64,7 +64,7 @@ public void InitializeConfigurationAndOptions_HttpTransport()
var services = SetupBaseServices().AddSingleton(Options.Create(serviceStartOptions));

// Act
ServiceCollectionExtensions.InitializeConfigurationAndOptions(services);
ServiceCollectionExtensions.InitializeConfigurationOptionsAndOpenTelemetry(services);
var provider = services.BuildServiceProvider();

// Assert
Expand All @@ -88,7 +88,7 @@ public void InitializeConfigurationAndOptions_Stdio()

// Act
Environment.SetEnvironmentVariable("AZURE_MCP_COLLECT_TELEMETRY", "false");
ServiceCollectionExtensions.InitializeConfigurationAndOptions(services);
ServiceCollectionExtensions.InitializeConfigurationOptionsAndOpenTelemetry(services);
var provider = services.BuildServiceProvider();

// Assert
Expand Down Expand Up @@ -121,7 +121,7 @@ public void InitializeConfigurationAndOptions_WithSupportLoggingFolder_DisablesT

// Act
Environment.SetEnvironmentVariable("AZURE_MCP_COLLECT_TELEMETRY", null);
ServiceCollectionExtensions.InitializeConfigurationAndOptions(services);
ServiceCollectionExtensions.InitializeConfigurationOptionsAndOpenTelemetry(services);
var provider = services.BuildServiceProvider();

// Assert
Expand All @@ -145,7 +145,7 @@ public void InitializeConfigurationAndOptions_WithSupportLoggingFolderAndEnvVarT

// Act
Environment.SetEnvironmentVariable("AZURE_MCP_COLLECT_TELEMETRY", "true");
ServiceCollectionExtensions.InitializeConfigurationAndOptions(services);
ServiceCollectionExtensions.InitializeConfigurationOptionsAndOpenTelemetry(services);
var provider = services.BuildServiceProvider();

// Assert
Expand All @@ -171,7 +171,7 @@ public void InitializeConfigurationAndOptions_WithEmptyOrWhitespaceSupportLoggin

// Act
Environment.SetEnvironmentVariable("AZURE_MCP_COLLECT_TELEMETRY", null);
ServiceCollectionExtensions.InitializeConfigurationAndOptions(services);
ServiceCollectionExtensions.InitializeConfigurationOptionsAndOpenTelemetry(services);
var provider = services.BuildServiceProvider();

// Assert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// Licensed under the MIT License.

using Azure.Mcp.Core.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Mcp.Core.Services.Telemetry;
using NSubstitute;
using Xunit;

namespace Azure.Mcp.Core.UnitTests.Extensions;
Expand All @@ -24,7 +26,7 @@ public void ConfigureOpenTelemetry_RegistersTelemetryService()
var services = new ServiceCollection();

// Act
services.ConfigureOpenTelemetry();
services.ConfigureOpenTelemetry(Substitute.For<IConfiguration>());

// Assert - Verify that the telemetry service descriptor is registered
Assert.Contains(services, sd => sd.ServiceType == typeof(ITelemetryService));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,13 @@ public static IServiceCollection AddAzureMcpServer(this IServiceCollection servi
/// Using <see cref="IConfiguration"/> configures <see cref="McpServerConfiguration"/>.
/// </summary>
/// <param name="services">Service Collection to add configuration logic to.</param>
public static void InitializeConfigurationAndOptions(this IServiceCollection services)
public static void InitializeConfigurationOptionsAndOpenTelemetry(this IServiceCollection services)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we have to configure open telemetry in this method as well? This method now has multiple responsibilities rather than just setting options.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find a cleaner way to get the IConfiguration singleton bound here when we called OpenTelemetryExtensions.ConfigureOpenTelemetry. If you know of a way to cleanly pull that out of the IServiceCollection I'd be more than happy to revert this change as I'm not a huge fan of it either.

{
#if DEBUG
Copy link
Member

@conniey conniey Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for having DOTNET_ENVIRONMENT is so we don't have to recompile to make test changes. We can rerun the application with different settings. We shouldn't have to if/def things based on the build type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was finding the DOTNET_ENVIRONMENT was blank when running debug builds, so we fell back to Production. If you know of a better way to fallback to Development when running a debug build do let me know.

var environment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Development";
#else
var environment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production";
#endif
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile($"appsettings.{environment}.json", optional: true)
Expand All @@ -272,11 +276,8 @@ public static void InitializeConfigurationAndOptions(this IServiceCollection ser

// Assembly.GetEntryAssembly is used to retrieve the version of the server application as that is
// the assembly that will run the tool calls.
var entryAssembly = Assembly.GetEntryAssembly();
if (entryAssembly == null)
{
throw new InvalidOperationException("Entry assembly must be a managed assembly.");
}
var entryAssembly = Assembly.GetEntryAssembly()
?? throw new InvalidOperationException("Entry assembly must be a managed assembly.");

options.Version = AssemblyHelper.GetAssemblyVersion(entryAssembly);

Expand All @@ -293,5 +294,7 @@ public static void InitializeConfigurationAndOptions(this IServiceCollection ser
// over any other settings.
options.IsTelemetryEnabled = rootConfiguration.GetValue("AZURE_MCP_COLLECT_TELEMETRY", true);
});

services.ConfigureOpenTelemetry(configuration);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Runtime.InteropServices;
using Azure.Monitor.OpenTelemetry.Exporter;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
Expand All @@ -25,7 +26,7 @@ public static class OpenTelemetryExtensions
/// </summary>
private const string MicrosoftOwnedAppInsightsConnectionString = "InstrumentationKey=21e003c0-efee-4d3f-8a98-1868515aa2c9;IngestionEndpoint=https://centralus-2.in.applicationinsights.azure.com/;LiveEndpoint=https://centralus.livediagnostics.monitor.azure.com/;ApplicationId=f14f6a2d-6405-4f88-bd58-056f25fe274f";

public static void ConfigureOpenTelemetry(this IServiceCollection services)
public static void ConfigureOpenTelemetry(this IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<ITelemetryService, TelemetryService>();

Expand All @@ -46,10 +47,10 @@ public static void ConfigureOpenTelemetry(this IServiceCollection services)
services.AddSingleton<IMachineInformationProvider, DefaultMachineInformationProvider>();
}

EnableAzureMonitor(services);
EnableAzureMonitor(services, configuration);
}

private static void EnableAzureMonitor(this IServiceCollection services)
private static void EnableAzureMonitor(this IServiceCollection services, IConfiguration configuration)
{
#if DEBUG
services.AddSingleton(sp =>
Expand Down Expand Up @@ -80,7 +81,7 @@ private static void EnableAzureMonitor(this IServiceCollection services)
.AddTelemetrySdk();
});

var userProvidedAppInsightsConnectionString = Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING");
var userProvidedAppInsightsConnectionString = configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"];

if (!string.IsNullOrWhiteSpace(userProvidedAppInsightsConnectionString))
{
Expand All @@ -92,7 +93,7 @@ private static void EnableAzureMonitor(this IServiceCollection services)
#if RELEASE
Copy link
Member

@conniey conniey Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frankly, I think we could have avoided this by using default appsettings.json = false and used the running environment to set it or not. Because now if we want to test this in a debug environment, it's impossible.

// This environment variable can be used to disable Microsoft telemetry collection.
// By default, Microsoft telemetry is enabled.
var microsoftTelemetry = Environment.GetEnvironmentVariable("AZURE_MCP_COLLECT_TELEMETRY_MICROSOFT");
var microsoftTelemetry = configuration["AZURE_MCP_COLLECT_TELEMETRY_MICROSOFT"];

bool shouldCollectMicrosoftTelemetry = string.IsNullOrWhiteSpace(microsoftTelemetry) || (bool.TryParse(microsoftTelemetry, out var shouldCollect) && shouldCollect);

Expand All @@ -102,7 +103,7 @@ private static void EnableAzureMonitor(this IServiceCollection services)
}
#endif

var enableOtlp = Environment.GetEnvironmentVariable("AZURE_MCP_ENABLE_OTLP_EXPORTER");
var enableOtlp = configuration["AZURE_MCP_ENABLE_OTLP_EXPORTER"];
if (!string.IsNullOrEmpty(enableOtlp) && bool.TryParse(enableOtlp, out var shouldEnable) && shouldEnable)
{
otelBuilder.WithTracing(tracing => tracing.AddOtlpExporter())
Expand Down
3 changes: 1 addition & 2 deletions servers/Azure.Mcp.Server/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,7 @@ internal static void ConfigureServices(IServiceCollection services)
{
var thisAssembly = typeof(Program).Assembly;

services.InitializeConfigurationAndOptions();
services.ConfigureOpenTelemetry();
services.InitializeConfigurationOptionsAndOpenTelemetry();

services.AddMemoryCache();
services.AddSingleton<IExternalProcessService, ExternalProcessService>();
Expand Down
8 changes: 4 additions & 4 deletions servers/Azure.Mcp.Server/src/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
// Generally, AZURE_MCP_COLLECT_TELEMETRY will be set as an environment variable.
// For Development purposes, we never want to publish telemetry so it is explicitly
// set here.
"AZURE_MCP_COLLECT_TELEMETRY": "false",
// Disable AZURE_MCP_COLLECT_TELEMETRY_MICROSOFT to prevent development telemetry from being collected by Microsoft
// instrumentation. This is to avoid polluting production telemetry with development data.
"AZURE_MCP_COLLECT_TELEMETRY_MICROSOFT": "false",
"AZURE_MCP_ENABLE_OTLP_EXPORTER": "true",
"Logging": {
"LogLevel": {
"Default": "Debug",
Expand Down
3 changes: 1 addition & 2 deletions servers/Fabric.Mcp.Server/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,7 @@ private static void WriteResponse(CommandResponse response)
/// <param name="services">A service collection.</param>
internal static void ConfigureServices(IServiceCollection services)
{
services.InitializeConfigurationAndOptions();
services.ConfigureOpenTelemetry();
services.InitializeConfigurationOptionsAndOpenTelemetry();

services.AddMemoryCache();
services.AddSingleton<IExternalProcessService, ExternalProcessService>();
Expand Down
3 changes: 1 addition & 2 deletions servers/Template.Mcp.Server/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ private static void WriteResponse(CommandResponse response)
/// <param name="services">A service collection.</param>
internal static void ConfigureServices(IServiceCollection services)
{
services.InitializeConfigurationAndOptions();
services.ConfigureOpenTelemetry();
services.InitializeConfigurationOptionsAndOpenTelemetry();

services.AddMemoryCache();
services.AddSingleton<IExternalProcessService, ExternalProcessService>();
Expand Down