.net 在日志记录时更改log4net FileAppender

.net 在日志记录时更改log4net FileAppender,.net,log4net,.net,Log4net,我们正在尝试配置一个服务器进程,以便在每次收到请求时,它都将该请求记录到一个新的文件名中 这个过程通常是单线程的,但我们不能保证代码中的其他线程有时不会尝试向log4net写入内容 似乎起作用的是: 第一次收到请求时,我们将“PerRequest”FileAppender配置如下: fileAppender = new FileAppender(); log.InfoFormat("Initializing log4net per request logging"); log4net.Layou

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

这个过程通常是单线程的,但我们不能保证代码中的其他线程有时不会尝试向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 logger“配置”为只记录一个文件名,因为我们无法找到令人满意的方法将其关闭

这很有效。。。但是在重载情况下,我们开始注意到“PerRequest”日志文件通常会有大量“丢失”的日志行。e、 g.类似这样的情况:

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分配日志文件名-不可能有另一个进程尝试登录到同一文件。。。但是另一条线呢?我们不能排除这种可能性

因此,第一个问题是:是否存在 实现我们想要的更好的方法

每个请求都必须是一个单独的文件吗

如果没有,那么如何创建您自己的定制模式布局并将请求细节作为日志模式的一部分呢?谷歌发现

如果是这样,那么扩展和更改新的文件条件,使其基于请求,而不是与文件大小(或任何内容)相关,怎么样

我想你们已经试过了

因此,第一个问题是:是否存在 实现我们想要的更好的方法

每个请求都必须是一个单独的文件吗

如果没有,那么如何创建您自己的定制模式布局并将请求细节作为日志模式的一部分呢?谷歌发现

如果是这样,那么扩展和更改新的文件条件,使其基于请求,而不是与文件大小(或任何内容)相关,怎么样

我想您已经尝试过以下方面的?

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

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

有关详细信息,请参见ThreadContext和PatternLayout类

从:

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

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

有关详细信息,请参见ThreadContext和PatternLayout类


是的,我想这是最好的答案。。。但是有点垃圾,他们没有提供某种“多路复用”附加,可以根据上下文属性切换到不同的文件名。通过大量日志文件“grepping”试图将与一个特定请求相关联的所有行放在一起是一个支持噩梦。从长远来看,我们将构建一个日志服务器,为我们将事情分开。是的,但这是双向的-如果您遇到一个根本原因是多个并发会话以某种方式交互的问题,那么组合的日志将是非常宝贵的。您可以编写一个命令行工具来拆分日志文件,而不是编写一个完整的自定义日志服务器。然后,当你有一个要分析的日志时,只要把它放到.exe上,它就会把单个的日志吐出来。在旧机器上,用“命令行工具”来分割日志可能需要很长时间才能运行thoughlong=2分钟来处理一个半GB的文件。是的,我想这是最好的答案。。。但是有点垃圾,他们没有提供某种“多路复用”附加,可以根据上下文属性切换到不同的文件名。通过大量日志文件“grepping”试图将与一个特定请求相关联的所有行放在一起是一个支持噩梦。从长远来看,我们将构建一个日志服务器,为我们将事情分开。这是真的,但如果你遇到一个根本原因是多方面的问题,它会双向削减