如何在 ASP.NET 中使用 log4net 在日志文件中包含 SessionID?

Posted

技术标签:

【中文标题】如何在 ASP.NET 中使用 log4net 在日志文件中包含 SessionID?【英文标题】:How can I include SessionID in log files using log4net in ASP.NET? 【发布时间】:2010-09-26 14:56:35 【问题描述】:

我是 log4net 的新手,所以希望这对某人来说是一个非常简单的问题?!​​

我已经让 log4net 与 RollingLogFileAppender 一起用于我的 Web 应用程序。我正在使用日志记录来尝试查找某些性能问题的来源。为此,在日志输出中包含 ASP.NET SessionID 会很有用,这样我就可以确保我正在查看特定用户的日志条目。

有什么方法可以通过appender 的conversionPattern 设置来做到这一点?我可以使用%property?? 设置吗?

更新:这个问题仍未得到解答 - 有人有什么想法吗?

【问题讨论】:

我也遇到了同样的问题:***.com/questions/8985693/… 我有下面的答案。如果有帮助,请点赞。不了解情况的人投了反对票。 ***.com/a/24048883/3481183 您不应记录会话 ID,因为有权访问日志文件的人可能会劫持会话。至少在记录之前对会话 ID 进行哈希处理! 【参考方案1】:

Alexander K. 几乎是正确的。唯一的问题是静态请求也会发生PostAcquireRequestState 事件。在这种情况下调用 Session 将导致 HttpException

因此正确的解决方案变为:

protected void Application_PostAcquireRequestState(object sender, EventArgs e)

    if (Context.Handler is IRequiresSessionState)
    
        log4net.ThreadContext.Properties["SessionId"] = Session.SessionID;
    

【讨论】:

IReadOnlySessionState 实际上扩展了 IRequiresSessionState 所以事实证明Context.Handler is IRequiresSessionState 就足够了。 这没有回答您的问题吗?【参考方案2】:

更新(2014-06-12):从 log4net 1.2.11 开始,您可以为此目的在转换模式中使用 %aspnet-requestASP.NET_SessionId

参考资料: https://issues.apache.org/jira/browse/LOG4NET-87 http://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout.html


您应该在 Global.asax.cs 中创建 Application_PostAcquireRequestState 处理程序(在每个请求中都会调用它):

protected void Application_PostAcquireRequestState(object sender, EventArgs e)

    log4net.ThreadContext.Properties["SessionID"] = Session.SessionID;

并将 [%propertySessionID] 添加到 conversionPattern。

【讨论】:

如果请求被拆分到不同的线程中,这将失败。发生这种情况的一种方法是应用程序使用异步页面/处理程序/服务。此外,出于某种原因,WCF AJAX 服务似乎在 PostAcquireRequestState 之后为同一请求切换线程。【参考方案3】:

我也在寻找这个问题的答案,发现%aspnet-requestASP.NET_SessionId 很适合我。

【讨论】:

如果在记录消息时没有启动会话,这会导致在登录最新版本的 log4net 1.2.11.0 的过程中出现异常。您可以通过在日志文件中看到部分完整的行来发现错误,但没有换行符将其与其他日志条目分开。【参考方案4】:

如果我错了,有人纠正我,但是一个 ASP.NET 线程可以处理多个会话,所以你不能使用 Session_Start,因为它在会话开始时被调用一次。这意味着一旦其他用户访问该网站,您的 log4net.ThreadContext 可能会被新的用户信息覆盖。

您可以将以下代码放在 Application_AcquireRequestState 中,或者创建一个 HttpModule 并在 AcquireRequestState 方法中执行此操作。当 ASP.NET 运行时准备好获取当前 HTTP 请求的会话状态时,将调用 AcquireRequestState。如果您对获取用户名感兴趣,您可以在 AuthenticateRequest 中执行此操作,该操作在 ASP.NET 运行时准备好验证用户身份时(以及在 AcquireRequestState 之前)引发。

    private void AcquireRequestState(Object source, EventArgs e)
    
        HttpApplication application = (HttpApplication)source;
        HttpContext context = application.Context;
        log4net.ThreadContext.Properties["SessionId"] = context.Session.SessionID;
     

之后,您可以像这样设置您的 log4net.config(或在 web.config 中)。

<appender name="rollingFile"
      type="log4net.Appender.RollingFileAppender,log4net" >
  <param name="AppendToFile" value="false" />
  <param name="RollingStyle" value="Date" />
  <param name="DatePattern" value="yyyy.MM.dd" />
  <param name="StaticLogFileName" value="true" />

  <param name="File" value="log.txt" />
  <layout type="log4net.Layout.PatternLayout,log4net">
    <param name="ConversionPattern"
      value="%propertySessionId %d [%t] %-5p %c - %m%n" />
  </layout>
</appender>

希望这会有所帮助!

【讨论】:

对 WCF 应用程序和 context.Session 进行了尝试,这会导致 null 引用异常。【参考方案5】:

你可以试试:

<conversionPattern
    value="%date %-5level %logger $COMPUTERNAME [%propertySessionID] - %message%newline" />

...在您的 Web.config 和 Global.asax.cs 中:

protected void Session_Start(object sender, EventArgs e)

    log4net.ThreadContext.Properties["SessionID"] = Session.SessionID;
    log4net.Config.XmlConfigurator.Configure();

【讨论】:

嗯 - 这似乎有效,但看起来会话 ID 只出现在第一次回发中发生的事情。随后返回服务器的行程具有 SessionID = null。还有其他想法吗? 我不确定。我们不久前使用了这种方法,并怀疑此设置会为当时使用 Web 应用程序的 everyone 设置 SessionID 属性(即 user1 的 SessionID 属性值将被 user2 覆盖)。抱歉,我无法提供更真实的见解... 我认为这行不通。 Session_Start 仅在建立会话的第一个请求上调用。当线程终止时,分配给该 ThreadContext 的属性将终止。所以当下一个请求进来时,会话已经建立,不会在 ThreadContext 中设置任何属性。为此,您应该使用 Application_BeginRequest 事件。

以上是关于如何在 ASP.NET 中使用 log4net 在日志文件中包含 SessionID?的主要内容,如果未能解决你的问题,请参考以下文章

[Asp.Net Core]log4net组件使用

log4net 使用总结- 在ASP.NET MVC 中使用

log4net 使用总结- 在ASP.NET MVC 中使用

MVC如何使用Log4Net进行错误日志记录

ASP.NET MVC中Log4Net记录错误日志的使用

log4net 与 ASP.NET 3.5 问题