【问题标题】:StackOverflowException in Serilog EnricherSerilog Enricher 中的 StackOverflowException
【发布时间】:2018-03-08 18:08:03
【问题描述】:

我正在为 Serilog 编写一个丰富器,我想添加一个可能触发新日志事件的属性,实际上:

public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
    ISession session = /* HttpContext.Session */;
    logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ValueFromSession", session.GetString("ValueFromSession")));
    /* other properties ... */
}

我希望能够将我的 http 会话中的一个值添加到我的日志中,因此我将 LogContext.PushProperties 与自定义丰富器一起使用。每当读取过期会话时,ASP.NET Core 都会记录一个警告,这会触发我的丰富器,但是每当我尝试从丰富器中的会话中读取时,它就会警告我有关过期的会话,这会触发我的丰富器的新实例(ad infitum )。这会导致 StackOverflowException 似乎无法被 try 块捕获。

Enrich 方法中是否有任何方法可以禁用日志记录?或者我可以以某种方式检测到这种递归(解析堆栈跟踪除外)?

【问题讨论】:

  • 仔细检查有没有循环引用
  • 我的代码和 ASP.NET 之间存在间接引用,如问题中所述,但我无法删除该引用,因为我需要能够从会话中读取并且我想要 ASP .NET 警告我有关过期的会话。
  • Enrich() 中抛出的异常应该被 Serilog 捕获,并且不会导致另一个顶级异常处理程序被触发。听起来这里可能发生了其他事情;您可以在问题中添加堆栈跟踪吗?干杯!
  • 问题不在于它记录了抛出的异常,在这种特殊情况下,每当我访问HttpContext.Session 时,ASP.NET 只会记录一个警告,我希望能够在我的浓缩器中做到这一点.这种相互递归的最终结果是堆栈溢出。

标签: c# .net asp.net-core stack-overflow serilog


【解决方案1】:

我在自定义 ILogger 实现(不使用 Serilog)时遇到了这个问题。任何时候访问 Session 对象都会发生这种情况。我设法通过在启动时将带有持久密钥的 DataProtection 添加到我的应用程序来解决此问题。

services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo("keys"));

我没有深入探讨实现细节,但从我在DistributedSession 代码中看到的情况来看,当检测到旧会话密钥时,会记录“访问过期会话”消息。这里的问题是日志记录发生在 isAvailable 标志设置为 true 之前,这会导致递归。我不知道为什么添加 DataProtection 可以避免这个问题,但 DataProtection 可能会导致 _isNewSessionKey 始终为 true

GitHub 中建议的另一种解决方法是添加一个中间件来将要记录的 Session 项目保存到 HttpContext.Items。然后在您的记录器中检索这些项目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    相关资源
    最近更新 更多