question

DmitryFilonenko-6088 avatar image
0 Votes"
DmitryFilonenko-6088 asked MughundhanRaveendran-MSFT commented

Exceptions are not cought by custom TelemetryProcesor in AppInsights in isolated (out-of-process) Functions

Recently we moved from in-process Azure Functions to out-of-process Functions (FUNCTIONS_WORKER_RUNTIME = dotnet-isolated). One of the issues we encountered is integration of Functions with AppInsights. We have a custom configuration for such integration. What we want to achieve is

  • to add some custom dimensions to logs

  • to not log exceptions in certain cases

In order to do this I configure AppInsights with custom TelemetryInitializer and TelemetryProcessor. This works fine for traces and dependencies (i.e. custom dimensions are enriched with my custom key-value pairs). But it doesn't work for exceptions: they never end up in my TelemetryProcessor nor are their logs in AI complemented with my custom dimensions.

Please see comments in the code below on how it's supposed to work.

A list of NuGet packages used in our project:

 "Microsoft.ApplicationInsights.WorkerService" Version="2.18.0"
 "Microsoft.Azure.Functions.Worker" Version="1.5.1"
  "Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="4.2.1"
  "Microsoft.Azure.Functions.Worker.Extensions.Storage" Version="4.0.4"
  "Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.1.0"
  "Microsoft.Azure.Functions.Worker.Sdk" Version="1.0.4"

The code of custom initializer:

 public class FunctionTelemetryInitializer : ITelemetryInitializer
     {
         public FunctionTelemetryInitializer(Config config)
         {
             _location = config.Location;
             _applicationName = config.ApplicationName;
             _version = config.Version;
         }
    
         private IEnumerable<KeyValuePair<string, string>> Values()
         {
             return new Dictionary<string, string>
             {
                 {"location", _location},
                 {"applicationName", _applicationName},
                 {"applicationVersion", _version}
             };
         }
            
         public void Initialize(ITelemetry telemetry)
         {
             var props = telemetry.Context.GlobalProperties;
             foreach (var kvp in Values())
             {
                 if (!props.ContainsKey(kvp.Key))
                 {
                     props[kvp.Key] = kvp.Value;
                 }
             }
         }
     }

The code of custom processor:

 public class FunctionsTelemetryProcessor : ITelemetryProcessor
     {
         private ITelemetryProcessor _next;
    
         public FunctionsTelemetryProcessor(ITelemetryProcessor next)
         {
             _next = next;
         }
            
         public void Process(ITelemetry item)
         {
             if (item is TraceTelemetry trace)
             {
                 if (trace.Message.Contains("Hello"))
                     return;        //here I have breakpoint 1
             }
                
             if (item is ExceptionTelemetry exception)
             {
   //here I have breakpoint 2
                 var retryException =
                     exception.ExceptionDetailsInfoList.FirstOrDefault(s =>
                         s.TypeName.Contains(nameof(FunctionsRetryException)));
                 if (retryException != null)
                 {
                     return;
                 }
             }
             _next.Process(item);
         }
     }

Function code:

 [Function("Test")]
         public async Task Run([QueueTrigger("test", Connection = "Connection")]
             string message, FunctionContext context)
         {
             //the following line should trigger a code at the breakpoint 1 in the FunctionsTelemetryProcessor, and it does it
             _logger.LogError("Hello!");
    
             //and this line should trigger a code at the breakpoint 2 in the FunctionsTelemetryProcessor, but it does not!
             throw new FunctionsRetryException("Test!!!");
         }

Program code:

 public class Program
     {
         public static Task Main(string[] args)
         {
             var host = new HostBuilder()
                 .ConfigureFunctionsWorkerDefaults()
                 .ConfigureServices(services =>
                 {
                     var config = new ConfigurationBuilder()
                         .AddJsonFile("local.settings.json", true, true)
                         .AddEnvironmentVariables()
                         .Build()
                         .Get<FunctionsConfig>();
                        
                     services.AddSingleton<ITelemetryInitializer, FunctionTelemetryInitializer>();
                     services.AddApplicationInsightsTelemetryWorkerService();
                     services.AddApplicationInsightsTelemetryProcessor<FunctionsTelemetryProcessor>();
    
                     services.AddSingleton<Config>(config);
                 })
                 .Build();
    
             return host.RunAsync();
         }
     }

host.json:

 {
   "version": "2.0",
   "functionTimeout": "00:10:00",
   "logging": {
     "fileLoggingMode": "never",
     "logLevel": {
       "default": "Information",
       "Host.Results": "Warning",
       "Function": "Warning",
       "Host.Aggregator": "Warning"
     },
     "applicationInsights": {
       "samplingSettings": {
         "isEnabled": true,
         "maxTelemetryItemsPerSecond" : 20,
         "excludedTypes": "Request;Dependency;Exception"
       }
     }
   },
   "extensions": {
     "queues": {
       "maxPollingInterval": "00:00:02",
       "visibilityTimeout" : "00:05:00",
       "batchSize": 1,
       "maxDequeueCount": 3,
       "newBatchThreshold": 0
     }
   }
 }

Any ideas?

azure-functions
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Trying to reproduce this issue at my end

0 Votes 0 ·

0 Answers