3

我有一系列Action我想使用Parallel.Invoke. 但是对于每一个Action我都希望有一个由 log4net 创建的单独的日志文件。在我的 log4net 配置文件中,我添加了这个:

<file type="log4net.Util.PatternString" value="3S2M3_%property{UniqueIdentifier}.log" />

如果只有一个 Action 可以执行此操作,则可以正常工作:日志文件具有正确的文件名。

Action但是,如果要执行的日志不止一个,那么所有日志条目都会在同一个日志文件中结束。

创建的代码Action是这样的:

    Dim lstActions(4) As Action
    Dim iCount As Integer = 0

    For iCount = 0 To 4
        Dim sUniqueIdentifier As String = iCount.ToString("D4")

        Dim aOrderTask As Action = Sub()
           log4net.LogicalThreadContext.Properties("UniqueIdentifier") = sUniqueIdentifier

       ' Some process that takes some time to complete
                                   End Sub
        lstActions(iCount) = aOrderTask
    Next

    Parallel.Invoke(lstActions)

创建的日志文件使用分配给UniqueIdentifier属性的值之一。我无法弄清楚这个值是如何被挑选出来的:它并不总是第一个或最后一个。在上面的示例中,仅创建了文件3S2M3_0004.log并且它包含所有日志条目。

我已经尝试过 LogicalThreadContext 和 ThreadContext 并且没有区别。

4

1 回答 1

2

log4net 在加载配置时分配日志文件名,因此您需要在运行时设置自定义名称。

需要注意的另一件事是 log4net 在记录器之间共享附加程序,因此要同时记录到不同的文件,您需要以编程方式分配附加程序,并且您必须在流程内而不是在流程外进行。

(如果你真的不想在代码中设置 appender 属性,你可以在配置中定义一个,从层次结构中获取它,然后为每个任务克隆它。无论哪种方式,任务的每个实例都需要它自己的记录器和一个独特的附加程序)

所以,给定这样的配置:

<?xml version="1.0" encoding="utf-8" ?>
<log4net debug="false">
   <root>
     <level value="DEBUG" />
   </root>

   <!-- more config -->

   <logger name="EmptyLogger" additivity="false">
   </logger>
   <!-- additivity="false" specifies not to load any appenders defined on the root logger -->
</log4net>

然后你可以有这样的代码:

Private Shared Sub ProcessThatTakesSomeTimeToComplete()
    Dim sUniqueIdentifier As New String(Guid.NewGuid().ToString("N").Take(4).ToArray())

    ' Get a uniquely-named empty logger containing no appenders
    Dim log = LogManager.GetLogger("EmptyLogger." & sUniqueIdentifier)

    ' Create an appender manually, setting the path as required
    Dim sPath As New String(Path.Combine("c:\temp", sUniqueIdentifier & ".log"))

    Dim appender = New FileAppender() With { _
         .Layout = New PatternLayout("%date [%thread] %message"), _
         .File = sPath, _
         .AppendToFile = True _
    }

    appender.ActivateOptions()

    ' Add the appender to the logger
    DirectCast(log.Logger, Logger).AddAppender(appender)

    ' And off we go.
    log.Debug("Hello from thread " + Thread.CurrentThread.ManagedThreadId)

    Thread.Sleep(100)
End Sub

进口:

Imports System.IO
Imports System.Threading
Imports log4net
Imports log4net.Appender
Imports log4net.Layout
Imports log4net.Repository.Hierarchy
于 2015-12-17T17:33:24.003 回答