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.
- 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.
- 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);
This creates searchable properties (OrderId, Reason, UserId) in Azure, enabling powerful filtering and aggregation that simple string searching cannot match.
- 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
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
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"
}
}
}
}
- 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
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)