Issues with OpenTelemetry Integration in .NET 8 Azure Function App

santosh kumar patro 0 Reputation points
2025-04-23T08:30:12.98+00:00

A .NET 8 Function App has been developed using the isolated worker model, following the guidelines in the Microsoft documentation: OpenTelemetry with Azure Functions.

After deploying the application in a DEV environment and performing validation, it was discovered that no requests are being logged for the Function App; only entries for itemType: trace, dependency, and exception are visible. Additionally, all trace, dependency, and exception logs lack the operation_Name column. In contrast, when comparing with an API, entries include itemType: request, trace, dependency, and exception, and the operation_Name column is present.

For further details, refer to this Stack Overflow post: OpenTelemetry Integration Issue.

Could assistance be provided to understand the reasons for the issues encountered with this setup?

Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
5,692 questions
{count} votes

Accepted answer
  1. RithwikBojja 1,375 Reputation points Microsoft External Staff
    2025-04-24T07:37:00.03+00:00

    Hi @santosh kumar patro ,

    To get requests to also be logged and Operation name in requests, you can use below code which works:

    Program.cs:

    
    using Microsoft.Extensions.Hosting;
    
    using Microsoft.Extensions.DependencyInjection;
    
    using Microsoft.Extensions.Configuration;
    
    using Microsoft.Extensions.Logging;
    
    using OpenTelemetry.Resources;
    
    using OpenTelemetry.Trace;
    
    using OpenTelemetry.Metrics;
    
    using Azure.Monitor.OpenTelemetry.Exporter;
    
    using System.Diagnostics;
    
    using Microsoft.Azure.Functions.Worker.Middleware;
    
    using Microsoft.Azure.Functions.Worker;
    
    var tester = new HostBuilder()
    
        .ConfigureFunctionsWebApplication(o =>
    
        {
    
            o.UseMiddleware<OperationNameMiddleware>(); 
    
        })
    
        .ConfigureAppConfiguration(config =>
    
        {
    
            config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    
                  .AddEnvironmentVariables();
    
        })
    
        .ConfigureServices((context, services) =>
    
        {
    
            var config = context.Configuration;
    
            var telemetryConfig = new RithServiceCldOps();
    
            config.Bind("TestRith", telemetryConfig);
    
            string globalServiceName = "RithwikApp";
    
            var resourceAttributes = new Dictionary<string, object> {
    
                { "service.name", "RithwikApp" },
    
                { "service.namespace", "FunctionAPP" },
    
                { "service.instance.id", "RIthInstance" }
    
            };
    
            services.Configure<LoggerFilterOptions>(rich =>
    
            {
    
                LoggerFilterRule brch = rich.Rules.FirstOrDefault(rule => rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
    
                if (brch is not null)
    
                {
    
                    rich.Rules.Remove(brch);
    
                }
    
            });
    
            var resourceBuilder = ResourceBuilder.CreateDefault().AddAttributes(resourceAttributes);
    
            var globalActivitySource = new ActivitySource("MyCompany.MyApp");
    
            services.AddSingleton(globalActivitySource);
    
            services.AddOpenTelemetry()
    
                .ConfigureResource(resource => resource.AddService(globalServiceName).AddAttributes(resourceAttributes))
    
                .WithTracing(b =>
    
                {
    
                    b
    
                        .AddSource("Microsoft.Azure.Functions.Worker")
    
                        .AddSource("MyCompany.MyApp")
    
                        .AddHttpClientInstrumentation()
    
                        .AddAzureMonitorTraceExporter(o =>
    
                        {
    
                            o.ConnectionString = telemetryConfig.testconstring;
    
                        });
    
                })
    
                .WithMetrics(b =>
    
                {
    
                    b
    
                        .AddHttpClientInstrumentation()
    
                        .AddRuntimeInstrumentation()
    
                        .AddAzureMonitorMetricExporter(o =>
    
                        {
    
                            o.ConnectionString = telemetryConfig.testconstring;
    
                        });
    
                });
    
            services.AddLogging(loggingBuilder =>
    
            {
    
                loggingBuilder.ClearProviders();
    
                loggingBuilder.AddOpenTelemetry(logs =>
    
                {
    
                    logs.IncludeFormattedMessage = true;
    
                    logs.IncludeScopes = true;
    
                    logs.ParseStateValues = true;
    
                    logs.AddAzureMonitorLogExporter(o =>
    
                    {
    
                        o.ConnectionString = telemetryConfig.testconstring;
    
                    });
    
                    logs.SetResourceBuilder(resourceBuilder);  // Add resource builder to logging
    
                });
    
            });
    
        });
    
    tester.Build().Run();
    
    public class RithServiceCldOps
    
    {
    
        public string testconstring { get; set; } = string.Empty;
    
    }
    
    public class OperationNameMiddleware : IFunctionsWorkerMiddleware
    
    {
    
        private readonly ActivitySource _activitySource;
    
        public OperationNameMiddleware(ActivitySource activitySource)
    
        {
    
            _activitySource = activitySource;
    
        }
    
        public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    
        {
    
            var functionName = context.FunctionDefinition.Name;
    
            using var activity = _activitySource.StartActivity(
    
                $"FunctionApp:{functionName}",
    
                ActivityKind.Server,
    
                Activity.Current?.Context ?? default);
    
            if (activity != null)
    
            {
    
                activity.DisplayName = $"FunctionApp:{functionName}";
    
                activity.AddTag("function.name", functionName);  
    
                Console.WriteLine($"Activity Started: {activity.DisplayName}"); 
    
            }
    
            using (var traceActivity = _activitySource.StartActivity("ProcessingStepX", ActivityKind.Internal))
    
            {
    
                traceActivity?.AddTag("step", "X");
    
                traceActivity?.SetStatus(ActivityStatusCode.Ok);
    
            }
    
            await next(context);
    
            if (activity != null)
    
            {
    
                Console.WriteLine($"Activity Ended: {activity.DisplayName}");
    
            }
    
        }
    
    }
    
    

    Output:

    enter image description here

    But, we cannot send Operation Name to Traces table using Open Telemetry. But we can check the data in custom dimensions as below:

    enter image description here

    If you want Operation Name, then you need to use Classic one not the Open telemetry:

    
    AddApplicationInsightsTelemetryWorkerService();
    
    ConfigureFunctionsApplicationInsights();
    
    

    If this answer was helpful, please click "Accept the answer" and mark Yes, as this can help other community members.

    enter image description here

    If you have any other questions or are still experiencing issues, feel free to ask in the "comments" section, and I'd be happy to help.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.