DEV Community

Cover image for Migrating Azure Functions Monitoring to OpenTelemetry
Tatsuro Shibamura for Polymind Inc.

Posted on

Migrating Azure Functions Monitoring to OpenTelemetry

A while ago, version 3.0 of the Application Insights SDK was released, and its internal implementation was migrated to be based on OpenTelemetry. While it is generally recommended to use the OpenTelemetry Distro directly, being able to support OpenTelemetry just by updating the Application Insights SDK is a clear advantage.

Along with this change, one of the Application Insights SDKs used in Azure Functions .NET Isolated—Microsoft.ApplicationInsights.WorkerService—has also been updated to version 3.0. If you are managing both Azure Functions and ASP.NET Core projects in a single solution, you may often update them together.

In a typical .NET Worker application, this update does not cause any issues. However, in Azure Functions, simply updating the package leads to runtime exceptions like the one below. Since the build succeeds without errors, this can be particularly tricky to notice.

This issue occurs because the Microsoft.Azure.Functions.Worker.ApplicationInsights package—required for Azure Functions' built-in Application Insights integration—has a strong dependency on the v2 SDK. While this would be resolved if the package were updated for v3, it appears from GitHub issues that there are no plans to provide a v3-compatible version. Therefore, in the long term, migrating to an OpenTelemetry-based approach will be necessary.

Comment for #3322

We do not plan to release a new version of Microsoft.Azure.Functions.Worker.ApplicationInsights that is compatible with the 3.0 release of Microsoft.ApplicationInsights.WorkerService. Our current package relies heavily on Telemetry Initializers and Telemetry Processors, and the new 3.0 SDK no longer supports these extensibility points. Supporting it would require a full rewrite of the Functions worker package. The same limitation may also affect customers who depend on Initializers or Processors in their applications. Our recommendation is to move to OpenTelemetry‑based monitoring. This is the direction we are investing in, and we are committed to improving observability by aligning with the OpenTelemetry ecosystem. You can follow Functions OpenTelemetry guidance here: https://learn.microsoft.com/en-us/azure/azure-functions/opentelemetry-howto?tabs=app-insights%2Cihostapplicationbuilder%2Cmaven&pivots=programming-language-csharp

Azure Functions now supports OpenTelemetry, but if you create a project from the default template, it still uses the Application Insights SDK. Therefore, some additional steps are required to switch.

You can follow the official documentation below for the migration steps, but there are a few pitfalls I encountered during the process.

https://learn.microsoft.com/en-us/azure/azure-functions/opentelemetry-howto

Removing Application Insights Packages

First, check your existing Azure Functions project. You will likely find the following two Application Insights-related packages installed. Remove them:

  • Microsoft.ApplicationInsights.WorkerService
  • Microsoft.Azure.Functions.Worker.ApplicationInsights

These packages depend on the Application Insights SDK and are no longer needed.

Adding OpenTelemetry Packages

Instead, install the following OpenTelemetry-related packages:

  • Microsoft.Azure.Functions.Worker.OpenTelemetry
  • Azure.Monitor.OpenTelemetry.Exporter
  • OpenTelemetry.Extensions.Hosting

In ASP.NET Core, a single package is often sufficient, but in Azure Functions, you need to install them individually.

Updating Program.cs

At this point, your project will no longer build. Remove the existing Application Insights initialization code in Program.cs and replace it with the following:

using Azure.Monitor.OpenTelemetry.Exporter;

using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Azure.Functions.Worker.OpenTelemetry;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

builder.ConfigureFunctionsWebApplication();

builder.Services.AddOpenTelemetry()
    .UseFunctionsWorkerDefaults()
    .UseAzureMonitorExporter();

builder.Build().Run();
Enter fullscreen mode Exit fullscreen mode

If you need customization, you can pass options to UseAzureMonitorExporter.

Local Development Pitfall

After this change, the project builds successfully. However, when running locally, you may encounter an error indicating that the Application Insights connection string is missing, causing the application to fail at startup.

With the Application Insights SDK, telemetry was automatically disabled if no connection string was provided. However, with the OpenTelemetry Distro, it is now required.

To avoid forcing Application Insights in local development, you could disable it using preprocessor directives. However, I personally found that approach messy.

Instead, I added a dummy connection string like this:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=00000000-0000-0000-0000-000000000000"
  }
}
Enter fullscreen mode Exit fullscreen mode

This allows the application to start correctly in a local development environment.

Verifying Telemetry

Finally, connect to Application Insights and verify that telemetry is being sent correctly.

You will notice that property names follow the OpenTelemetry schema. However, telemetry generated by the Azure Functions host remains unchanged.

Real-World Example

Here is the Pull Request where I migrated Acmebot to an OpenTelemetry-based setup:

Add OpenTelemetry support and remove Application Insights initializer #996

This pull request updates the application's telemetry and monitoring stack by migrating from Application Insights to OpenTelemetry with Azure Monitor Exporter. This modernizes observability, aligns with current best practices, and simplifies related configuration and code. The most important changes are grouped below.

Migration to OpenTelemetry and Azure Monitor Exporter:

  • Removed dependencies on Microsoft.ApplicationInsights.WorkerService and Microsoft.Azure.Functions.Worker.ApplicationInsights, and added new dependencies for Azure.Monitor.OpenTelemetry.Exporter, Microsoft.Azure.Functions.Worker.OpenTelemetry, and OpenTelemetry.Extensions.Hosting in Acmebot.App.csproj.
  • Replaced Application Insights telemetry setup in Program.cs with OpenTelemetry initialization using AddOpenTelemetry(), UseFunctionsWorkerDefaults(), and UseAzureMonitorExporter().
  • Updated host.json to set "telemetryMode": "OpenTelemetry" and removed Application Insights-specific logging configuration.

Codebase cleanup:

  • Removed the custom ApplicationVersionInitializer class and its registration, as it was specific to Application Insights. [1] [2]

General code and dependency updates:

  • Updated using statements in Program.cs to remove Application Insights references and add OpenTelemetry/Azure Monitor references as needed.

The changes are relatively simple—for example, removing ITelemetryInitializer. Equivalent functionality is now built in, so it is no longer necessary.

Final Thoughts

Migrating applications that rely heavily on ITelemetryProcessor or other advanced customizations may require more effort. However, it seems feasible to migrate even filtering logic to OpenTelemetry.

If I get the time, I plan to write another post covering those advanced scenarios.

Top comments (0)