首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Log4Net、ThreadContext和Global.asax

Log4Net、ThreadContext和Global.asax
EN

Stack Overflow用户
提问于 2009-06-30 21:03:34
回答 2查看 7.3K关注 0票数 5

我正在开发一个Log4Net配置,它将记录所有未处理的异常。我需要某些属性,基于用户,添加到每个日志条目。我已经在我的Application_Error事件中通过以下方式成功地设置了它。这是我的完整global.asax

代码语言:javascript
复制
Imports log4net
Imports log4net.Config

    Public Class Global_asax
        Inherits System.Web.HttpApplication

        'Define a static logger variable
        Private Shared log As ILog = LogManager.GetLogger(GetType(Global_asax))

        Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
            ' Fires when the application is started
            ConfigureLogging()
        End Sub

        Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
            ' Code that runs when an unhandled error occurs
            Dim ex As Exception = Server.GetLastError()
            ThreadContext.Properties("user") = User.Identity.Name
            ThreadContext.Properties("appbrowser") = String.Concat(Request.Browser.Browser, " ", Request.Browser.Version)
            If TypeOf ex Is HttpUnhandledException AndAlso ex.InnerException IsNot Nothing Then
                ex = ex.InnerException
            End If
            log.Error(ex)
            ThreadContext.Properties.Clear()
        End Sub

        Private Sub ConfigureLogging()
            Dim logFile As String = Server.MapPath("~/Log4Net.config")
            log4net.Config.XmlConfigurator.ConfigureAndWatch(New System.IO.FileInfo(logFile))
            log4net.GlobalContext.Properties("appname") = System.Reflection.Assembly.GetExecutingAssembly.GetName.Name
        End Sub
    End Class

这似乎运行得很好。然而,我有一些问题是我无法回答的。

我通过threadcontext添加用户特定属性的方式是正确的吗?即使在加载的情况下,这是否始终记录正确的信息?什么时候使用threadlogicalcontext?有没有更好的方法来做这件事?

谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-09-15 15:02:56

像这样将特定于请求的值加载到ThreadContext中是不安全的。原因是ASP.NET共享线程来服务请求。事实上,它经常这样做。

您也可以使用LogicalThreadContext,但是它只是将值存储在用于远程处理的调用上下文中。

AFAIK没有特定于HttpContext的上下文存储,所以你可以做的是分配一个“值提供者”实例作为你的线程上下文,在运行时它将在这个类上调用.ToString()来获得值。

代码语言:javascript
复制
public class HttpContextUserProvider
{
   public override string ToString()
   {
      return HttpContext.Current.User.Identity.Name;
   }
}

它不是很理想,但它是有效的。

票数 11
EN

Stack Overflow用户

发布于 2012-12-28 04:42:56

本的答案是正确的。

然而,像其他一些用户一样,我仍然有点迷茫,不知道如何继续。这篇log4net Context problems with ASP.Net thread agility文章,特别是这篇Marek Stój's Blog - log4net Contextual Properties and ASP.NET文章,通过一些优秀的代码示例为这个问题提供了更多的上下文。

我强烈推荐Marek Stój的实现,尽管在我的例子中需要用ThreadContext.Properties["User"]替换ThreadContext.Properties["UserName"]

我将一个BeginRequest方法添加到我的Logger类中,这个类是从Application_AuthenticateRequest调用的,它加载所有相关的log4net属性。

代码语言:javascript
复制
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    Logger.BeginRequest(Request);
}

和方法代码:

代码语言:javascript
复制
public static void BeginRequest(System.Web.HttpRequest request)
{
    if (request == null) return;

    ThreadContext.Properties["ip_address"] = AdaptivePropertyProvider.Create("ip_address", IPNetworking.GetMachineNameAndIP4Address());
    ThreadContext.Properties["rawUrl"] = AdaptivePropertyProvider.Create("rawUrl", request.RawUrl);

    if (request.Browser != null && request.Browser.Capabilities != null)
        ThreadContext.Properties["browser"] = AdaptivePropertyProvider.Create("browser", request.Browser.Capabilities[""].ToString());

    if (request.IsAuthenticated && HttpContext.Current.User != null)
        ThreadContext.Properties["User"] = AdaptivePropertyProvider.Create("user", HttpContext.Current.User.Identity.Name);
}

我发现我必须传入请求对象,而不是在方法中使用HttpContext.Current.Request。否则,我将丢失用户和身份验证信息。请注意,IPNetworking类是我自己的,因此您需要提供您自己的方法来获取客户端IP。AdaptivePropertyProvider类直接来自Marek Stój。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1066062

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档