捕获用户名与log4net的 [英] Capture username with log4net

查看:189
本文介绍了捕获用户名与log4net的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我写的所有log4net的事件数据库,它似乎工作得很好。为了捕捉登录的用户帐户,我用这块code的:

I currently write all log4net events to a database, and it seems to work just fine. To capture the logged in user account I use this piece of code:

HttpContext context = HttpContext.Current;
if (context != null && context.User != null && context.User.Identity.IsAuthenticated)
{
    MDC.Set("user", HttpContext.Current.User.Identity.Name);
}

在code似乎确定,除了有与他们(即我们的公共网页上的用户)关联的用户上下文的事件。在这种情况下log4net的拍摄似乎写某个用户帐户(坏)的最后记录,并写一段空(好)。任何人有此功能在所有情况下可靠地工作?我相信我看到了一张纸条,上面MDC不再推荐功能使用,但我没能找到建议任何替代方案。

The code seems ok, except for events that have no user context associated with them (ie. a user on our public web page). In that case the log4net capture seems to sometime write the last logged in user account (bad) and sometime write a null (good). Anyone got this feature to work reliably in all cases? I believe I saw a note that MDC is no longer a recommended feature to use, but I wasn't able to find any alternatives that are recommended.

请注意:我觉得很奇怪,MDC设置与帐户的名字,但如果没有用户主动从不清除。这可能是问题的一部分。但是,我没有找到任何MDC code精华,也清除了用户名。

Note: I find it odd that MDC is set with an account name, but never cleared if no user is active. That could be part of the problem. However, I didn't find any MDC code extracts that also clear the username.

推荐答案

如果可用的HttpContext的信息就足够了,也就是说,如果您发布的样品code给你正确的答案(除MDC问题),你只想宁愿只是没有写:

If the information that is available in the HttpContext is sufficient, that is, if the sample code you posted gives you the right answer (except for the MDC issue) and you would just rather just not write:

HttpContext context = HttpContext.Current; 
if (context != null && context.User != null && context.User.Identity.IsAuthenticated)
{     
  MDC.Set("user", HttpContext.Current.User.Identity.Name); 
} 

所以很多时候,那么你或许可以通过编写自己的自定义PatternLayoutConverter为log4net的,以用户名添加到自动的日志。他们是pretty容易写,你可以在你的log4net的日志记录配置,就像建在那些配置它们。

so often, then you might be able to add the username to your log "automatically" by writing your own custom PatternLayoutConverter for log4net. They are pretty easy to write and you can configure them in your log4net logging configuration just like the built in ones.

请参阅这个问题对于如何编写自定义PatternLayoutConverter一个例子:

See this question for one example of how to write a custom PatternLayoutConverter:

<一个href=\"http://stackoverflow.com/questions/3961815/custom-log4net-property-patternlayoutconverter-with-index\">Custom log4net的财产PatternLayoutConverter(索引)

在使用该链接的例子,你也许可以做这样的事情:

Using the example at that link, you might be able to do something like this:

namespace Log4NetTest
{
  class HttpContextUserPatternConverter : PatternLayoutConverter
  {
    protected override void Convert(System.IO.TextWriter writer, LoggingEvent loggingEvent)
    {
      string name = "";
      HttpContext context = HttpContext.Current;
      if (context != null && context.User != null && context.User.Identity.IsAuthenticated)
      {
        name = context.User.Identity.Name;
      }
      writer.Write(name);
    }
  }
}

您将在log4net的是这样配置的:

You would configure this in log4net something like this:

  //Log HttpContext.Current.User.Identity.Name
  <layout type="log4net.Layout.PatternLayout">
    <param name="ConversionPattern" value="%d [%t] %-5p [User = %HTTPUser] %m%n"/>
    <converter>
      <name value="HTTPUser" />
      <type value="Log4NetTest.HttpContextUserPatternConverter" />
    </converter>
  </layout>

此外,你可以创建一个使用Option参数等模式转换器(参见例如在上面的链接),从HttpContext.Current.Items拉一个特定的项目或HttpContext.Current.Session集合。

In addition, you could build other pattern converters that use the Option parameter (see the example at the link above) to pull a specific item from the HttpContext.Current.Items or HttpContext.Current.Session collections.

是这样的:

namespace Log4NetTest
{
  class HttpContextSessionPatternConverter : PatternLayoutConverter
  {
    protected override void Convert(System.IO.TextWriter writer, LoggingEvent loggingEvent)
    {
      //Use the value in Option as a key into HttpContext.Current.Session
      string setting = "";

      HttpContext context = HttpContext.Current;
      if (context != null)
      {
        object sessionItem;
        sessionItem = context.Session[Option];
        if (sessionItem != null)
        {
          setting = sessionItem.ToString();
        }
        writer.Write(setting);
      }
    }
  }
}


namespace Log4NetTest
{
  class HttpContextItemPatternConverter : PatternLayoutConverter
  {
    protected override void Convert(System.IO.TextWriter writer, LoggingEvent loggingEvent)
    {
      //Use the value in Option as a key into HttpContext.Current.Session
      string setting = "";

      HttpContext context = HttpContext.Current;
      if (context != null)
      {
        object item;
        item = context.Items[Option];
        if (item != null)
        {
          setting = item.ToString();
        }
        writer.Write(setting);
      }
    }
  }
}

您也可能会发现这些有用的链接:

You might also find these links useful:

<一个href=\"http://piers7.blogspot.com/2005/12/log4net-context-problems-with-aspnet.html\">http://piers7.blogspot.com/2005/12/log4net-context-problems-with-aspnet.html

在这里,博主提出从HttpContext的比我提出了不同的解决方案,以记录值。阅读博客文章,看看他的问题,并为他的解决方案的说明。总结该溶液中,他存储在GlobalDiagnosticContext一个对象(MDC更现代的名称)。当log4net的记录对象的值,它使用的ToString()。他的目的的实现从HttpContext的检索值:

Here, the blogger proposes a different solution to logging values from HttpContext than what I proposed. Read the blog post to see his description of the problem and for his solution. To summarize the solution, he stores an object in the GlobalDiagnosticContext (the more modern name for MDC). When log4net logs the value of the object it uses ToString(). the Implementation of his object retrieves a value from the HttpContext:

所以,你可能做这样的事情:

So, you might do something like this:

public class HttpContextUserNameProvider
{
  public override string ToString()
  {
    HttpContext context = HttpContext.Current;  
    if (context != null && context.User != null && context.User.Identity.IsAuthenticated)
    {
      return context.Identity.Name;
    }
    return "";
  }
}

您可以把这个对象在GlobalDiagnosticContext(MDC)的一个实例,早在你的程序,它总是返回正确的值,因为它正在访问HttpContext.Current。

You can put an instance of this object in the GlobalDiagnosticContext (MDC) early in your program and it will always return the right value since it is accessing HttpContext.Current.

MDC.Set("user", new HttpContextUserNameProvider());

这似乎比我所提出的要容易得多!

This seems a lot easier than what I proposed!

有关完整性,如果有人想知道如何做NLOG同样的事情,NLOG的出现使大多数/所有的可通过其aspnet- *LayoutRenderers HttpContext的信息:

For completeness, if someone wants to know how to do the same thing in NLog, NLog appears to make most/all of the HttpContext information available through its "aspnet-*" LayoutRenderers:

<一个href=\"https://github.com/nlog/nlog/wiki/Layout-Renderers\">https://github.com/nlog/nlog/wiki/Layout-Renderers

这篇关于捕获用户名与log4net的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆