其他
在 ASP.NET Core Razor Pages…
为 ASP.NET Core 应用配置 Serilog 结构化日志、关联 ID、请求日志、健康检查与 OpenTelemetry 分布式追踪。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 47/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 47/100 ×0.15
适用场景
在 ASP.NET Core Razor通用
解决思路
- 引入 NuGet 包:Serilog.AspNetCore、Serilog.Expressions,可选 Serilog.Sinks.Seq。
- 在 Program.cs 开头启用 Serilog 自诊断 SelfLog.Enable(msg => Console.Error.WriteLine($"[SERILOG] {msg}")),并创建 bootstrap logger:MinimumLevel.Override("Microsoft", LogEventLevel.Information)、Enrich.FromLogContext()、WriteTo.Console(formatProvider: CultureInfo.CurrentCulture)、CreateBootstrapLogger()。
- 用 try/catch/finally 包裹应用启动:try 中 Log.Information("Starting web application...") 并构建运行应用;catch 中 Log.Fatal(ex, "Application terminated unexpectedly");finally 中 await Log.CloseAndFlushAsync()。
- 在服务注册扩展方法 ConfigureSerilog 中调用 services.AddSerilog,配置 ReadFrom.Configuration(configuration)、Enrich.FromLogContext()、Enrich.WithMachineName()、Enrich.WithEnvironmentName(),用 ExpressionTemplate 输出 Console,并写入 Seq(读取 configuration["Seq:ServerUrl"] 与 configuration["Seq:ApiKey"])。
- 在 appsettings.json 的 Serilog 节点配置 Using、MinimumLevel(Default 为 Information,Microsoft/Microsoft.AspNetCore/System 覆盖为 Warning)、WriteTo Console 的 outputTemplate、Enrich 列表(FromLogContext、WithMachineName、WithThreadId)以及 Properties.Application。
- 实现 RequestContextLoggingMiddleware:从请求头 X-Correlation-Id 读取关联 ID,缺失时回退到 httpContext.TraceIdentifier;通过 Response.OnStarting 把关联 ID 写回响应头;用 LogContext.PushProperty 推入 CorrelationId、RequestPath、RequestMethod 后调用 _next。
- 提供 UseRequestContextLogging 扩展方法,并在 Program.cs 中于管道早期调用 app.UseRequestContextLogging(),随后调用 app.UseSerilogRequestLogging()。
- 配置 UseSerilogRequestLogging:在 EnrichDiagnosticContext 中设置 UserId、ClientIp、UserAgent;在 GetLevel 中把异常或 5xx 记为 Error,耗时超过 1000ms 记为 Warning,其余为 Information。
- 在 PageModel 中使用 logger.BeginScope 推入 OrderId、UserId 等上下文属性,在加载成功、未找到(LogWarning)和异常(LogError 后 rethrow)时分别记录日志。
- 实现 MediatR 的 RequestLoggingBehavior<TRequest, TResponse>:记录开始日志,用 Stopwatch 计时,成功且超过 500ms 阈值记 Warning,否则记 Information,异常时 LogError 并 rethrow。
- 在 AddMediatR 中通过 cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(RequestLoggingBehavior<,>)) 注册该行为。
- 配置健康检查:AddHealthChecks().AddDbContextCheck<AppDbContext>(name: "database", tags: new[] { "db", "critical" }).AddCheck<EmailServiceHealthCheck>(...).AddRedis(...)。
- 映射健康检查端点:app.MapHealthChecks("/up") 作为简单端点;app.MapHealthChecks("/health", new HealthCheckOptions { ResponseWriter = HealthCheckResponseWriter.WriteResponse, AllowCachingResponses = false }).RequireAuthorization("HealthCheckPolicy") 作为详细端点。
- 实现自定义 IHealthCheck(如 EmailServiceHealthCheck),调用服务 PingAsync,成功返回 Healthy,失败返回 Unhealthy,异常时返回带异常的 Unhealthy。
- 实现 HealthCheckResponseWriter.WriteResponse,设置 ContentType 为 application/json,输出 Status、TotalDuration 以及每个检查的 Name、Status、Duration、Exception、Data。
- 对热路径使用 LoggerMessage 源生成器:定义 static partial class LoggerMessages,用 [LoggerMessage(EventId, Level, Message)] 标注 partial 方法(如 UserSignedUp、SlowQueryDetected、EmailSendFailed、OrderProcessed),调用时传入 ILogger 与参数。
- 配置 OpenTelemetry:builder.Services.AddOpenTelemetry().WithTracing 中添加 AddAspNetCoreInstrumentation、AddHttpClientInstrumentation、AddEntityFrameworkCoreInstrumentation、AddSource("MyApp") 与 AddOtlpExporter(Endpoint 指向 http://localhost:4317);WithMetrics 中添加 AddAspNetCoreInstrumentation、AddRuntimeInstrumentation、AddPrometheusExporter;随后调用 app.UseOpenTelemetryPrometheusScrapingEndpoint()。
- 在业务服务中用 ActivitySource(如 new("MyApp.Orders"))创建自定义 Activity,设置 SetTag(order.id、order.total),用 AddEvent 标记各阶段,成功 SetStatus(ActivityStatusCode.Ok),异常 SetStatus(ActivityStatusCode.Error, ex.Message) 并 rethrow。
- 在 Razor Pages 的 ErrorModel.OnGet 中,从 Activity.Current?.Id ?? HttpContext.TraceIdentifier 获取 RequestId,通过 IExceptionHandlerPathFeature 取出异常与路径并用 logger.LogError 记录,仅在 IsDevelopment() 时把# ex.ToString() 赋给 ErrorMessage 展示。
- 避免反模式:不要用静态 Logger 访问(Log.ForContext),应注入 ILogger<T>;不要在日志中使用字符串插值,应使用结构化参数或 LoggerMessage;不要捕获异常后静默吞掉,必须记录并视情况 rethrow。
适用边界 · 注意事项
- 不使用 ASP.NET Core / .NET 8+ 的项目不适用。
- 不打算接入 Serilog、Seq、OpenTelemetry 等外部日志与追踪系统的简单应用无需完整套用。
- 纯前端或非 Razor Pages 的 .NET 应用场景不适用。