junalmeida / autofac-azurefunctions

Autofac implementation of the dependency injection factory for non isolated Azure Functions.
MIT License
20 stars 6 forks source link

No AI performance logs on Portal for Azure Function. TelemetryProcessor list in TelemetrySink is unavailable after one request cycle #20

Closed xeo545x39 closed 3 years ago

xeo545x39 commented 3 years ago

Describe the bug When Autofac is attached and function request is invoked (simple HTTP) the first cycle is executed successfully. Any next request is failing (or logs are not written - depending on the approach) because as I've done some analysis I assume that TelemetryProcessors property or even some other part of TelemetrySink is disposed, probably improperly.

So basic issue is that telemetry client does not write the logs into Application Insights.

It was almost impossible to find out what is wrong and what is the difference between execution with and without Autofac, but I successfully done with serializing whole TelemetryClient by simple JsonConvert class. The difference has immedietaly shown - with Autofac serializer can't get TelemetryProcessors property after the first request. (documentation).

Without Autofac everything works good. The serializer is accessing this property fine and logs are written into Application Insights successfully.

It's also worth to say that I'm not adding Telemetry Client manually. As I see there is already a client added in UseAutofacServiceProviderFactory method in line containerBuilder.RegisterModule<LoggerModule>(); which is already adding some telemetry/logging stuff.

Azure Portal: 1

To reproduce

  1. Attach Autofac to existing Azure Function
  2. Register your function class in Autofac container builder (and other components)
  3. Turn on Application Insights on Azure Portal
  4. Make a request to your example endpoint
  5. Try to view your performance logs in Portal or just try to access TelemetryProcessors property
 public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddHttpClient();

            builder.UseAutofacServiceProviderFactory(
                containerBuilder => ConfigureContainer(containerBuilder, builder));

// ...

 containerBuilder.RegisterType<DebugFunction>()
                .AsSelf()
                .InstancePerTriggerRequest(); // has tried instance per lifetimescope, but no difference in this case

 public class DebugFunction
    {
        private readonly TelemetryClient _client;

        public DebugFunction(TelemetryClient client)
        {
            _client = client;
        }

         [FunctionName(nameof(GetHealthStatus))]
        public IActionResult GetHealthStatus([HttpTrigger(
                AuthorizationLevel.Anonymous,
                HttpMethods.Get,
                Route = "Debug/Health")]
            HttpRequest request)
        {
            try
            {
                return new OkObjectResult(
                    new
                    {
                        Status = "Running",
                        Timestamp = DateTime.UtcNow,
                        TelemetryClient = new
                        {
                            TelemetrySinkProcessorCount = _client.TelemetryConfiguration.DefaultTelemetrySink
                                .TelemetryProcessors.Count, // this line is failing
                            TelemetrySinkCount = _client.TelemetryConfiguration.TelemetrySinks.Count
                        }
                    });
            }
            catch (Exception ex)
            {
                return new OkObjectResult(new { error = true, exception = ex.ToString() });
            }
        }

Assembly/dependency versions:

  <PackageReference Include="Autofac" Version="6.1.0" />
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
    <PackageReference Include="Autofac.Extensions.DependencyInjection.AzureFunctions" Version="6.0.0.53" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.13" />

Additional context Response without Autofac:

{
  "status": "Running",
  "timestamp": "2021-08-10T15:57:02.9195936Z",
  "telemetryClient": {
    "telemetrySinkProcessorCount": 1,
    "telemetrySinkCount": 1
  }
}

Response with Autofac:

Newtonsoft.Json.JsonSerializationException: Error getting value from 'TelemetryProcessors' on 'Microsoft.ApplicationInsights.Extensibility.TelemetrySink'.
---> System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.ApplicationInsights.Extensibility.TelemetrySink.get_TelemetryProcessors()
at lambda_method(Closure, Object )
at Newtonsoft.Json.Serialization.ExpressionValueProvider.GetValue(Object target)
junalmeida commented 3 years ago

@xeo545x39 Does it happen if you update to latest 6.0.0.78 version?

xeo545x39 commented 3 years ago

No. After upgrade to the newest version everything is ok. The issue can be removed. Thank you very much!