Awesome DotNet日志记录框架:Serilog到Application Insights
概述
在现代.NET应用开发中,日志记录是确保应用可靠性和可观测性的关键组件。Serilog作为.NET生态系统中最受欢迎的日志记录框架之一,结合Microsoft Application Insights的强大监控能力,为开发者提供了完整的日志管理和分析解决方案。
本文将深入探讨如何将Serilog与Application Insights集成,构建高效、可扩展的日志记录体系。
日志记录框架对比
下表展示了.NET生态系统中主要日志记录框架的特性对比:
| 框架 | 结构化日志 | 性能 | 扩展性 | 云原生支持 | 学习曲线 |
|---|---|---|---|---|---|
| Serilog | ✅ 优秀 | ⚡️ 高 | 🌟 极强 | ✅ 完善 | 中等 |
| NLog | ⚪ 中等 | ⚡️ 高 | ✅ 强 | ✅ 良好 | 中等 |
| log4net | ❌ 有限 | 🔶 中等 | ✅ 强 | 🔶 一般 | 简单 |
| Microsoft.Extensions.Logging | ✅ 良好 | ⚡️ 高 | ✅ 强 | ✅ 优秀 | 简单 |
Serilog核心概念
结构化日志记录
// 传统日志记录
logger.Info("User {UserName} logged in at {LoginTime}", "john.doe", DateTime.Now);
// 结构化日志记录(Serilog优势)
logger.Information("User {UserName} logged in from {IPAddress} with role {Role}",
"john.doe", "192.168.1.100", "Administrator");
丰富的事件属性
// 使用Enrich丰富日志上下文
Log.Logger = new LoggerConfiguration()
.Enrich.WithProperty("Application", "MyApp")
.Enrich.WithProperty("Environment", "Production")
.Enrich.WithMachineName()
.Enrich.WithThreadId()
.CreateLogger();
Application Insights集成
安装必要包
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.Sinks.ApplicationInsights" Version="3.1.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
基础配置
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog((context, services, configuration) =>
{
var telemetryConfiguration = TelemetryConfiguration.CreateDefault();
telemetryConfiguration.InstrumentationKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext()
.WriteTo.ApplicationInsights(
telemetryConfiguration,
TelemetryConverter.Traces);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
高级配置模式
多Sink配置策略
环境特定配置
public static void ConfigureSerilog(IConfiguration configuration, string environmentName)
{
var loggerConfig = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.WithProperty("Environment", environmentName);
if (environmentName == "Development")
{
loggerConfig.WriteTo.Console(
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}");
}
else
{
var telemetryConfig = TelemetryConfiguration.CreateDefault();
telemetryConfig.InstrumentationKey = configuration["ApplicationInsights:InstrumentationKey"];
loggerConfig.WriteTo.ApplicationInsights(telemetryConfig, TelemetryConverter.Traces);
}
Log.Logger = loggerConfig.CreateLogger();
}
性能优化策略
异步批量处理
.WriteTo.ApplicationInsights(
telemetryConfiguration,
TelemetryConverter.Traces,
restrictedToMinimumLevel: LogEventLevel.Information,
formatProvider: null,
logEventSizeLimit: 32000,
batchSizeLimit: 100,
period: TimeSpan.FromSeconds(15),
queueLimit: 10000)
日志级别过滤
// 生产环境配置
.MinimumLevel.Information()
.Override("Microsoft", LogEventLevel.Warning)
.Override("System", LogEventLevel.Warning)
.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
监控和告警配置
Application Insights查询示例
// 查找错误日志
traces
| where severityLevel == 3
| project timestamp, message, customDimensions
| order by timestamp desc
// 性能分析
requests
| join (traces | where message contains "Performance")
on operation_Id
| project duration, operation_Name, message
// 用户行为分析
pageViews
| join (traces | where message contains "UserAction")
on operation_Id
| summarize count() by user_AuthenticatedId, tostring(customDimensions["ActionType"])
告警规则配置
{
"alertRule": {
"name": "HighErrorRate",
"description": "Alert when error rate exceeds 5%",
"condition": {
"windowSize": "PT5M",
"allOf": [
{
"metricName": "traces/count",
"dimensions": [
{
"name": "severityLevel",
"operator": "Include",
"values": ["3"]
}
],
"operator": "GreaterThan",
"threshold": 50,
"timeAggregation": "Count"
}
]
},
"actions": [
{
"actionGroupId": "/subscriptions/xxx/resourceGroups/xxx/providers/microsoft.insights/actionGroups/xxx"
}
]
}
}
最佳实践指南
日志结构化规范
| 字段名 | 类型 | 描述 | 示例 |
|---|---|---|---|
| Timestamp | DateTime | 事件时间戳 | 2024-01-15T10:30:00Z |
| Level | string | 日志级别 | Information, Error |
| MessageTemplate | string | 消息模板 | "User {UserId} performed {Action}" |
| Properties | object | 结构化属性 | { "UserId": 123, "Action": "Login" } |
| Exception | object | 异常信息 | Exception details |
| CorrelationId | string | 请求关联ID | guid |
性能考量指标
关键性能指标:
- 日志生成延迟:< 1ms
- 批量处理大小:100-1000条/批次
- 网络传输频率:15-30秒/次
- 存储成本:根据保留策略优化
故障排除指南
常见问题及解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 日志未发送到AI | 配置错误 | 检查InstrumentationKey |
| 性能下降 | 同步写入 | 启用异步批量处理 |
| 数据丢失 | 网络问题 | 配置重试机制 |
| 存储成本高 | 日志级别过低 | 调整MinimumLevel |
诊断工具使用
// 启用详细日志记录
Serilog.Debugging.SelfLog.Enable(msg =>
{
Debug.WriteLine(msg);
Console.WriteLine(msg);
});
// 健康检查端点
app.MapGet("/health/logging", async context =>
{
var canWrite = await Log.Logger.BindProperty("HealthCheck", "test", out _);
context.Response.StatusCode = canWrite ? 200 : 503;
await context.Response.WriteAsync(canWrite ? "Healthy" : "Unhealthy");
});
安全考虑
敏感信息处理
// 数据脱敏配置
.Destructure.With<SecureDataDestructuringPolicy>()
public class SecureDataDestructuringPolicy : IDestructuringPolicy
{
public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory,
out LogEventPropertyValue result)
{
if (value is CreditCard card)
{
result = new ScalarValue(card.MaskedNumber);
return true;
}
result = null;
return false;
}
}
访问控制策略
// 基于角色的日志访问
public class AuthorizedLogViewer
{
private readonly ILogger _logger;
public AuthorizedLogViewer(ILogger logger, IAuthorizationService authService)
{
_logger = logger;
}
public async Task<LogEvents> GetLogs(LogQuery query, ClaimsPrincipal user)
{
var authResult = await _authService.AuthorizeAsync(user, query, "ViewLogsPolicy");
if (!authResult.Succeeded)
{
throw new UnauthorizedAccessException();
}
return await _logService.QueryAsync(query);
}
}
总结
Serilog与Application Insights的结合为.NET应用程序提供了企业级的日志记录解决方案。通过结构化日志记录、强大的查询能力和完善的监控功能,开发者可以:
- 快速定位问题:利用丰富的查询功能快速找到问题根源
- 性能优化:通过日志分析识别性能瓶颈
- 用户体验改善:跟踪用户行为模式优化产品功能
- 成本控制:智能的日志存储和保留策略
遵循本文的最佳实践,您可以构建出既高效又可靠的日志记录体系,为应用程序的稳定运行提供有力保障。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



