DEV Community

Pavan Manjunath
Pavan Manjunath

Posted on

📝Mastering Structured Logging in .NET Core with Serilog, App Insights, and Log Analytics

Achieving deep observability is non-negotiable for modern applications. This guide details the gold standard pipeline for robust structured logging in .NET Core: integrating Serilog with Azure Application Insights and the underlying Log Analytics Workspace.

  1. The Core Observability Stack: Roles Defined Understanding the relationship between these three services is paramount:

Simply put: Serilog formats the data, App Insights collects the application context, and Log Analytics stores and queries the final dataset.

  1. Why Structured Logging? Structured logging is key to turning log lines into valuable data points. Instead of logging raw text, Serilog uses message templates to capture data properties.

Example Log:

Log.Error("Order {OrderId} failed because of a {Reason} for user {UserId}.", 456, reason, userId);
Enter fullscreen mode Exit fullscreen mode

This creates searchable properties (OrderId, Reason, UserId) in Azure, enabling powerful filtering and aggregation that simple string searching cannot match.


  1. Implementation Steps

Step 3.1: Install Packages
Add the necessary NuGet packages:

dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.ApplicationInsights
dotnet add package Microsoft.ApplicationInsights.AspNetCore
dotnet add package Serilog.Settings.Configuration
Enter fullscreen mode Exit fullscreen mode

Step 3.2: Configure in Program.cs
Configure Serilog early in your application lifecycle. This setup ensures that your structured logs flow directly into Application Insights while preventing duplicate logs from the default provider.

// 1. Create a bootstrap logger (optional, but good for startup errors)
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateBootstrapLogger();

var builder = WebApplication.CreateBuilder(args);

// 2. Register App Insights SDK (Crucial!)
// The Serilog Sink needs this service configured.
builder.Services.AddApplicationInsightsTelemetry(builder.Configuration["ApplicationInsights:ConnectionString"]);

// 3. Clear default providers to prevent duplicate logs
builder.Logging.ClearProviders(); 

// 4. Configure Serilog to use the Application Insights Sink
builder.Host.UseSerilog((context, services, configuration) => configuration
    .ReadFrom.Configuration(context.Configuration)
    .ReadFrom.Services(services)
    .Enrich.FromLogContext()
    .WriteTo.Console() 
    .WriteTo.ApplicationInsights(
        services.GetRequiredService<TelemetryConfiguration>(), 
        // This converter ensures logs land in the 'traces' table
        TelemetryConverter.Traces
    ));

// ... rest of builder code
Enter fullscreen mode Exit fullscreen mode

Step 3.3: Configure appsettings.json
Ensure your Application Insights connection string is defined, and set your desired logging levels:

{
  "ApplicationInsights": {
    "ConnectionString": "InstrumentationKey=..." 
  },
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Querying and Diagnostics Once deployed, your structured logs land in the traces table within your Log Analytics Workspace.

Use Kusto Query Language (KQL) to perform diagnostics:

// Find all error logs related to a specific user and project the custom property
traces 
| where customDimensions.UserId == "123" 
| where severityLevel == 3 // Severity 3 is Error
| project timestamp, message, customDimensions.OrderId, customDimensions.Reason
| order by timestamp desc
Enter fullscreen mode Exit fullscreen mode

This integrated approach allows you to correlate your custom application events (traces) with system telemetry (requests, exceptions) using the common operation_Id property, giving you a full, end-to-end view of every transaction.

Mastering this pipeline is key to moving from reactive bug fixing to proactive system health monitoring!

Top comments (0)