gpt4 book ai didi

c# - 如何在 SeriLog Sink 中获取当前的 HttpContext?

转载 作者:太空狗 更新时间:2023-10-29 20:22:55 25 4
gpt4 key购买 nike

我正在创建自己的 SeriLog 接收器实现 ILogEventSink使用 Building a Simple Sink示例,目的是记录用户声明中的一些信息。要访问 Core 中的 HttpContext,我通常会注入(inject)一个 IHttpContextAccessor 的实例。但该示例显示了在扩展方法中创建接收器的实例,例如

public class MySink : ILogEventSink
{
private readonly IFormatProvider _formatProvider;

public MySink(IFormatProvider formatProvider)
{
_formatProvider = formatProvider;
}

public void Emit(LogEvent logEvent)
{
// How to get HttpContext here?
}
}

public static class MySinkExtensions
{
public static LoggerConfiguration MySink(
this LoggerSinkConfiguration loggerConfiguration,
IFormatProvider formatProvider = null)
{
return loggerConfiguration.Sink(new MySink(formatProvider));
}
}

...然后使用水槽...

var log = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.MySink()
.CreateLogger();

如何在接收器的 Emit 方法中访问当前的 HttpContext?或者是否可以让 DI 框架创建接收器?!

我有一个 MVC 站点使用 Serilog.AspNetCore v2.1.0 针对 .Net 4.6.2 运行时运行 Asp.Net Core 2 框架。

更新 - 解决方法

在@tsimbalar 的指针之后,我创建了类似于下面代码的中间件。在我的 StartUp.Configure方法我使用 app.UseMiddleware<ClaimsMiddleware>(); 添加它应用身份验证步骤发生后(否则将不会加载声明)。

public class ClaimsMiddleware
{
private static readonly ILogger Log = Serilog.Log.ForContext<ClaimsMiddleware>();
private readonly RequestDelegate next;

public ClaimsMiddleware(RequestDelegate next)
{
this.next = next ?? throw new ArgumentNullException(nameof(next));
}

public async Task Invoke(HttpContext httpContext)
{
if (httpContext == null) throw new ArgumentNullException(nameof(httpContext));

// Get values from claims here
var myVal = httpContext
.User
.Claims
.Where(x => x.Type == "MyVal")
.Select(x => x.Value)
.DefaultIfEmpty(string.Empty)
.SingleOrDefault();

using (LogContext.PushProperty("MyVal", myVal))
{
try
{
await next(httpContext);
}

// Never caught, because `LogException()` returns false.
catch (Exception ex) when (LogException(httpContext, ex)) { }
}
}

private static bool LogException(HttpContext httpContext, Exception ex)
{
var logForContext = Log.ForContext("StackTrace", ex.StackTrace);

logForContext.Error(ex, ex.Message);

return false;
}
}

最佳答案

更新我想你可能想看看这篇文章:http://mylifeforthecode.github.io/enriching-serilog-output-with-httpcontext-information-in-asp-net-core/

想法是注册一个自定义中间件,它将在请求期间将所有上下文 信息添加到当前LogContext

为了让它工作,你必须配置你的记录器

Log.Logger = new LoggerConfiguration()
// snip ....MinimumLevel.Debug()
.Enrich.FromLogContext()
// snip ...
.CreateLogger();

Nicholas Blumhardt 的这篇文章也可能有所帮助:https://blog.getseq.net/smart-logging-middleware-for-asp-net-core/


警告 - 以下解决方案在这种情况下不起作用

如果记录器提前注册(在 Program.Main() 中),下面的解决方案将无法工作

首先,如果您想添加附加到已记录事件的额外信息,我相信您想要的是 Enricher。 .

然后你可以:

  • 注册IHttpContextAccessor进入您的 ServiceCollection(例如,使用 AddHttpContextAccessor()):services.AddHttpContextAccessor();
  • 创建 ILogEventEnricher 的实现,在其构造函数中接受 IHttpContextAccessor
  • 配置记录器时,注入(inject) IHttpContextAccessor(通过将 IHttpContextAccessor 类型的参数添加到 Startup.Configure()
  • 将此增强器添加到您的记录器

enricher 可能类似于 https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/ClaimValueEnricher.cs .

你会像这样配置你的记录器:

var logger = new LoggerConfiguration()
.EnrichWith(new MyEnricher(contextAccessor))
.WriteTo.Whatever()
.CreateLogger();

关于c# - 如何在 SeriLog Sink 中获取当前的 HttpContext?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47071487/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com