3

An Application Insights event is not created when calling logger.LogError("My error.") from my web API. I'm confirming this in two ways:

  • F5 debugging in Visual Studio 2017 (v15.5.7) does not show any Application Insights events in the Output/Events pane.
  • No events flow to my Application Insights instance in Azure.

I suspect my problem is due the application's logging factory not being configured correctly with ApplicationInsightsLoggerProvider. It was my understanding from reading articles and source code, I should:

  1. AddApplicationInsightsTelemetry on my services collection to ensure TelemetryClient is registered. See ApplicationInsightsExtensions
  2. AddApplicationInsights on my ILoggerFactory to register the provider and use the client mentioned above. See ApplicationInsightsLoggerFactoryExtensions

I'm doing something wrong I'm sure, but I cannot determine what it is. I've boiled my code down to the skeleton below, and I am able to repro my issue still.

I came across a similar question on StackOverflow, however, the answer did not solve my case.

WebApplication.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net461</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.2" />
  </ItemGroup>

</Project>

Program.cs

public class Program
    {
        public static void Main( string[] args )
        {
            BuildWebHost( args ).Run();
        }

        public static IWebHost BuildWebHost( string[] args ) =>
            WebHost.CreateDefaultBuilder( args )
                .UseStartup<Startup>()
                .Build();
    }

appsettings.json

{
    "ApplicationInsights": {
        "InstrumentationKey": "omitted for StackOverflow"
    }
}

Startup.cs

public class Startup
{
    public Startup( IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory )
    {
        this.LoggerFactory = loggerFactory ?? throw new ArgumentNullException( nameof( loggerFactory ) );

        this.Configuration = new ConfigurationBuilder()
            .SetBasePath( hostingEnvironment.ContentRootPath )
            .AddJsonFile( "appsettings.json", optional: true, reloadOnChange: true )
            .AddEnvironmentVariables()
            .Build();
    }

    IConfiguration Configuration { get; set; }

    ILoggerFactory LoggerFactory { get; }

    public void Configure( IApplicationBuilder app, IHostingEnvironment env )
    {
        app.UseMvc();
    }

    public void ConfigureServices( IServiceCollection services )
    {
        services.AddApplicationInsightsTelemetry( this.Configuration );
        this.LoggerFactory.AddApplicationInsights( services.BuildServiceProvider(), LogLevel.Information );

        services.AddMvc();
    }
}

MyController.cs

[Route( "[controller]" )]
public class MyController : Controller
{
    public MyController( ILogger<MyController> logger )
    {
        this.Logger = logger ?? throw new ArgumentNullException( nameof( logger ) );
    }

    ILogger<MyController> Logger { get; }

    [HttpGet]
    public void Get()
    {
        // *************************************************************************
        // This line is not being captured as an Application Insights Event.
        // *************************************************************************
        this.Logger.LogError( "My error." );
        // *************************************************************************
    }
}
Scott Lin
  • 1,532
  • 1
  • 18
  • 28

2 Answers2

3

I learned ILoggerFactory loggerFactory can be dependency injected into Startup.Configure(). After calling AddApplicationInsights on this instance of the logger factory instead of the one saved from my Startup constructor, everything worked as expected.

Only Startup class needed to be modified from my original question. Here's it is for completeness of this answer.

public Startup( IHostingEnvironment hostingEnvironment )
{
    this.Configuration = new ConfigurationBuilder()
        .SetBasePath( hostingEnvironment.ContentRootPath )
        .AddJsonFile( "appsettings.json", optional: true, reloadOnChange: true )
        .AddEnvironmentVariables()
        .Build();
}

IConfiguration Configuration { get; set; }

public void Configure( IApplicationBuilder app, ILoggerFactory loggerFactory )
{
    loggerFactory.AddApplicationInsights( app.ApplicationServices, LogLevel.Information );
    app.UseMvc();
}

public void ConfigureServices( IServiceCollection services )
{
    services.AddApplicationInsightsTelemetry( this.Configuration );
    services.AddMvc();
}

Learning opportunity!

If someone more familiar with Application Insights and AspNetCore 2.0 can explain to me why this works compared to the original question's code, I'd be very curious to know! :)

Scott Lin
  • 1,532
  • 1
  • 18
  • 28
1

The correct way (as you found out already) to configure AI logging is to call extension method AddApplicationInsights() in Configure method. When you called this method from ConfigureServices() instead, I believe AILoggingProvider got a TelemetryClient which was not configured yet. https://github.com/Microsoft/ApplicationInsights-aspnetcore/blob/develop/src/Microsoft.ApplicationInsights.AspNetCore/Logging/Implementation/ApplicationInsightsLoggerFactoryExtensions.cs#L65

cijothomas
  • 2,818
  • 1
  • 13
  • 25