3

我有一个接收 WCF 请求的 Windows 服务进程。对于每个请求,它都会创建执行某些工作的新线程。我想为主机进程创建一个日志文件,并为每个线程实例单独的唯一日志文件。例如,我希望日志文件类似于“%date{yyyyMMdd}_%property{UniqueId}.log”。这是我到目前为止所拥有的。

<appender name="ThreadAppender" type="log4net.Appender.RollingFileAppender">
      <file type="log4net.Util.PatternString" value="c:\Logs\%date{yyyyMMdd}\%date{HHmmss}_%property{FileID}.log"/>
      <appendToFile value="true"/>
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="10MB"/>
      <rollingStyle value="Size"/>
      <staticLogFileName value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <header value="[Header]
"/>
        <footer value="[Footer]
"/>
        <conversionPattern value="[%date] [%thread] [%-5level] %logger  - %message%newline"/>
      </layout>
    </appender>
    <appender name="ServiceAppender" type="log4net.Appender.RollingFileAppender">
      <file value="C:\Logs\Service.log"/>
      <appendToFile value="true"/>
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="10MB"/>
      <rollingStyle value="Size"/>
      <staticLogFileName value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <header value="[Header]
"/>
        <footer value="[Footer]
"/>
        <conversionPattern value="[%date] [%thread] [%-5level] %logger  - %message%newline"/>
      </layout>
    </appender>
    <root>
      <level value="ALL"/>
      <appender-ref ref="ThreadAppender"/>
    </root>
    <logger name="ServiceLogger" additivity="false">
      <level value="INFO"/>
      <appender-ref ref="ServiceAppender"/>
    </logger>

然后,在我的线程中,我使用LogicalContext.Properties["FileID"] = <some id>. 我[assembly: log4net.Config.XmlConfigurator(Watch = true)]在 assemblyinfo.cs 文件中也有一行。

一切几乎都有效:)。一个问题是,当我启动 Windows 服务时,它会自动创建新的 %date{HHmmss}_(null).log 文件。我需要配置什么才能使 log4net 不会创建这个虚拟文件?另外,是否需要为 ServiceAppender 和 ThreadAppender 指定文件锁定?

4

2 回答 2

1

由于并发问题,该代码无法按预期工作。log4net.Config.XmlConfigurator.Configure 强制应用新的属性值,但它会影响所有线程,因此其他并发请求的消息将被重定向到新文件。

我唯一可行的解​​决方案是使用 ILoggerRepository。

于 2015-04-09T10:27:22.887 回答
0

在 WCF 服务中为每个线程创建唯一的日志文件

如果您不想让 log4net 创建一个 FileID 为空的文件(例如 c:\Logs\19850101\131510_null.log)
,您必须确保先设置属性,然后再配置 log4net。

在 WCF 服务中,您可以采取以下步骤:
1. 在文件“AssemblyInfo.cs”中删除对 XmlConfigurator 的调用。
2. 向您的服务添加一个全局应用程序类 (Global.asax)。
3. 将以下代码添加到新创建的类中。

    /// <summary>
    /// Begins the application request.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">A <see cref="EventArgs"/> that contains the event data.</param>
    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        log4net.LogicalContext.Properties["FileID"] = <some id>;

        // Configure log4net. Log4net will load settings and create a new 
        //   file if it does not exist yet.
        log4net.Config.XmlConfigurator.Configure();
        log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        logger.Debug(<some id>);
    }

开始记录

现在使用以下代码段在每个类中创建一个记录器:

    /// <summary>
    /// Logger that can be used to report messages, errors, etc.
    /// </summary>
    private static log4net.ILog Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

关于锁定

不确定是否需要对 ServiceAppender 和 ThreadAppender 使用锁定。
默认情况下,每个 WCF 服务都将“并发模式”设置为“单一”,将
“实例上下文模式”设置为“PerSession”。

这意味着在任何给定时间只会处理一个请求。我
在具有 1 个客户端的虚拟机上使用该服务进行了测试,并且日志记录似乎工作
正常!所以默认情况下,不需要锁定。

于 2014-02-26T15:48:35.543 回答