Core Insight

Using Application Insights as a Sink for logging in ASP.NET Core

ASP.NET Core has very extensible logging interface. I provides an ILogger interface along with few default implementations that can be used to log data.

Many third party logging providers are available that ties into ILogger interface, to send your log data to the sinks of your choice but Application Insights is very easy to set up and can help you with exploring the log data using rich query language (Kusto Query Language).

Depending upon your needs, you can either choose to use the default interface or some of the more advanced logging frameworks like Serilog to capture log data.

Here I'm going to show you how to configure Application Insights as one of the Sinks for your logger. It's so simple and easy to use, you'll get addicted to it once you find your way around it. You logs will be merged with other telemetry data coming from your applications, so you'll be able to correlate multiple events generated per user request and build rich insights.

As your application complexity grows or more Microservices are added to your stack, it'll make it very easy for you to understand what's going on within the system and help you identify bugs or anomalies quickly.

First, add reference to the  following nuget packages

  • Microsoft.Extensions.Loggging.ApplicationInsights (v2.9.1)
  • Microsoft.ApplicationInsights.AspNetCore (v2.6.0 or later)

Configure Logging in Program.cs as shown below:

public class Program { public static void Main(string[] args) { var host = BuildWebHost(args); var logger = host.Services.GetRequiredService>(); logger.LogInformation("From Program. Running the host now.."); host.Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() .ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); }) .ConfigureLogging((hostingContext, logging) => { logging.AddApplicationInsights(hostingContext.Configuration.GetSection("Logging")["Application Insights:InstrumentationKey"].ToString()); logging.AddFilter("", LogLevel.Trace); logging.AddFilter("Microsoft", LogLevel.Warning); }) .Build(); }

.NET Core 2.1 (and above) provides an easy way to get access to configuration information as early as possible. Here, we were able to read Application Insights Instrumentation key while initializing the program. The instrumentation key could be different for each environment so we need to read it before configuring Applications Insights Sink for logging.

While the above configuration is good enough if you would like to capture bare minimum Telemetry data, but if you want to combine regular application monitoring (Requests, Dependencies etc., ) you've got to do few more stuff in startup.cs.

Add the following in the Configure Service method. This will enable regualr application monitoring with default configuration(ServerTelemetryChannel, Live Metrics, Request/Dependencies, Correlation etc., )

services.AppApplicationInsightsTelemetry("instrumentationkey"); services.AddSingleton( new Func( (IServiceProvider provider) => new TelemetryClient() { InstrumentationKey = "InstrumentationKey"; } ) );

Add the following in the Configure method

var appInsightsLogLevel = Configuration.GetValue("Logging:Application Insights:LogLevel:Default"); loggerFactory.AddApplicationInsights(app.ApplicationServices, appInsightsLogLevel);

That's it. Once it's done, you should be able to sprinkle your logging statements all over the codebase and let Applicaiton Insights do it's magic.

[Route("api/GetOrder")] [ApiController] public class GetOrderController : ControllerBase { public IGetOrderService _service; public IConfiguration _configuration { get; } public ILogger _logger { get; set; } public GetOrderController(ILogger logger, IGetOrderService service, IConfiguration configuration) { _logger = logger; _service = service; _configuration = configuration; } /// /// Get Order info POST method /// /// /// [HttpPost] [EnableCors("default")] [ProducesResponseType(201, Type = typeof(object))] [ProducesResponseType(400)] public async Task Post([FromBody]GetOrderInfoDTO orderInfo) { if(!ModelState.IsValid) { _logger.LogError("Invalid Request"); return BadRequest(); } try { _logger.LogInformation("Fetching Order Information"); var _orderInfo = await _service.GetOrderInfoAsync(orderInfo); if (_orderInfo == null) { _logger.LogInformation("Can't find the order. Please try again"); return NotFound(); } else { return Ok(_orderInfo); } } catch(Exception ex) { _logger.LogError(ex.Message + " " + ex.StackTrace); return BadRequest(); } } }

That's it. The Application Insights will start showing all the requests/errors in the portal.

Interested in learning more about this topic? Contact our solution experts and setup a time to talk.