在记录时更改log4net FileAppender

时间:2009-09-24 10:30:29

标签: .net log4net

我们正在尝试配置服务器进程,以便每次收到请求时,都会将该请求记录到新文件名。

该过程通常是单线程的,但我们无法保证代码中某处的其他线程有时不会尝试向log4net写入内容。

似乎有效的是:

我们第一次收到请求时,我们按如下方式配置“PerRequest”FileAppender:

fileAppender = new FileAppender();
log.InfoFormat("Initializing log4net per request logging");
log4net.Layout.PatternLayout layout = new Layout.PatternLayout("%date %property{processid} %property{username} %-5level %logger - %message%newline");
fileAppender.Layout = layout;
layout.ActivateOptions();
fileAppender.AppendToFile = true;
fileAppender.Name = "PerRunLogger";
fileAppender.File = makeNewRequestLogName(); // Returns a unique filename (uses a Guid)
log.InfoFormat("Configured PerRequest logger to log to '{0}'", fileAppender.File);
fileAppender.ActivateOptions();
log4net.Config.BasicConfigurator.Configure(fileAppender);

然后,每当我们收到新请求时,我们都会执行以下操作:

fileAppender.File = makeNewRequestLogName();
log.InfoFormat("Configured PerRequest logger to log to '{0}'", fileAppender.File);
fileAppender.ActivateOptions();

在请求结束时,我们“配置”PerRequest记录器以记录到单个文件名,因为我们找不到令人满意的方法来关闭它。

这很好用......但是在负载很重的情况下,我们开始注意到“PerRequest”日志文件通常会有大量“缺失”的日志行。例如像这样的东西:

2009-09-23 19:17:17,133 4332 hollingp DEBUG PostProcessInfrastructure.PostProcessRunner - Started post processing
* normal log lines here, omitted for brevity *
2009-09-23 19:17:36,414 4332 hollingp DEBUG PluginRegistry.PostProcessVersions.PostProcessPluginCacheVersion - About to run pub_GetPostProcessingVersion stored proc

*Normally lots of log lines here, but every now and then, NOTHING *

2009-09-23 19:17:37,742 4332 hollingp DEBUG PostProcessInfrastructure.PostProcessRunner - Finished post processing

对于我们在日志文件中看到的内容没有很好的解释 - 没有代码路径(即使抛出异常)也可以解释“缺失”的日志行 - 某些东西(相当多)实际的东西)应该记录在19:17:36的线和19:17:37的线之间的那个线程。

不可否认,整个技术都有点狡猾,但我们想不到另一种方法。

所以第一个问题是:有没有更好的方法来实现我们想要的目标?

第二个问题是:任何人都可以解释可能发生的事情吗?怀疑是需要执行一些线程安全/锁定,但在哪里?如果是这种情况需要锁定什么?

没有其他进程尝试登录同一文件的风险,因为正如代码中的注释所示,我们使用GUID分配日志文件名 - 其他进程无法尝试登录到同一个文件...但另一个线程?我们无法排除这一点。

2 个答案:

答案 0 :(得分:2)

  

所以第一个问题是:有没有   更好的方式来实现我们想要的目标?

每个请求是否必须是单独的文件?

如果没有,那么创建自己的自定义模式布局并使请求详细信息成为日志模式的一部分呢? An example Google找到了。

如果是,请如何扩展RollingFileAppender并更改新文件条件,以便不是与文件大小(或其他)相关,而是基于请求?

我认为你已经尝试过LockingModel

答案 1 :(得分:2)

来自log4net FAQ

  

许多开发人员面临着区分源自同一类但不同客户端请求的日志输出的问题。他们提出了巧妙的机制来将日志输出扇出到不同的文件。在大多数情况下,这不是正确的方法。

     

使用上下文属性或堆栈(ThreadContext)更简单。通常,在开始处理客户端请求时,会有ThreadContext.Properties [“ID”] =“XXX”客户端特定信息,例如客户端的主机名,ID或任何其他区别信息。此后,日志输出将自动包含上下文数据,以便您可以区分不同客户端请求的日志,即使它们输出到同一文件。

     

有关更多信息,请参阅ThreadContext和PatternLayout类。