全局声明log4net变量,并在所有类文件中使用它们c#

时间:2018-10-30 17:11:41

标签: c# log4net

我有一个用C#编写的类库。在该库中,我们使用log4net进行日志记录。
这个类库有2-3个类文件。一个用c#编写的Windows服务正在使用该类库。

现在,log4net已通过以下方式实现。
1.我从nuget添加了log4net的引用。
2.在每个类文件中,将其添加到顶部:

private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

3。希望打印一些其他详细信息以及默认值,因此在log4net.config文件中添加了一些参数,如下所示:

<parameterName value="@Parameter1"/>
<parameterName value="@Parameter2"/>

和布局模式:

<layout type="log4net.Layout.PatternLayout">
     <conversionPattern value="%date{dd/MM/yy HH:mm:ss} [%thread] %level  :: Parameter1 = %property{Parameter1} :: Parameter2 = %property{Parameter2}:: %logger : %message%newline"   />
</layout>

并将此行添加到ClassA的每个方法中,在该方法中,正在执行日志记录:

log4net.GlobalContext.Properties["Parameter1"] = parameter1;
log4net.GlobalContext.Properties["Parameter2"] = parameter2;

现在我在这里面临的问题是,我的类库中有两个名为Class1Class2的类文件。而parameter1parameter2是公开的ClassA中的变量。如this问题中所述,我无法访问paramter1中的parameter2ClassB。因此,当打印classB方法的日志时,parameter1parameter2始终为空。

有没有一种方法可以一次全局设置参数,每当打印日志时,它都使用相同的变量。

我的代码类似于以下内容:

public ClassA {
    public string parameter1 { get; set; } = "ABC"
    public string parameter2 { get; set; } = "XYZ"

    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    public void SomeMethod(){
        log4net.GlobalContext.Properties["Parameter1"] = parameter1;
        log4net.GlobalContext.Properties["Parameter2"] = parameter2;
        ClassB b = new ClassB();
        log.info("In Some Method");
        b.AnotherMethod();
        LogMessage("After AnotherMethod");  
    }   
}

public class ClassB(){
    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    public void AnotherMethod(){        
        log.info("Inside AnotherMethod");       
    }
}

预期输出:

30/10/18 21:57:11 [5] INFO  :: Parameter1 = 'ABC' :: Parameter2 = 'XYZ' :: ClassA : In Some Method
30/10/18 21:57:11 [5] INFO  :: Parameter1 = 'ABC' :: Parameter2 = 'XYZ' :: ClassB : Inside AnotherMethod
30/10/18 21:57:11 [5] INFO  :: Parameter1 = 'ABC' :: Parameter2 = 'XYZ' :: ClassA : After AnotherMethod

实际输出:

30/10/18 21:57:11 [5] INFO  :: Parameter1 = 'ABC' :: Parameter2 = 'XYZ' :: ClassA : In Some Method
30/10/18 21:57:11 [5] INFO  :: Parameter1 = (null) :: Parameter2 = (null) :: ClassB : Inside AnotherMethod
30/10/18 21:57:11 [5] INFO  :: Parameter1 = 'ABC' :: Parameter2 = 'XYZ' :: ClassA : After AnotherMethod

如何使参数1和2每次都打印或全局声明。因此,一旦设置,所有log4net消息都必须使用它。

在这方面的任何帮助都将受到高度赞赏。

3 个答案:

答案 0 :(得分:4)

代码中的这一行:

log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

最终会有2个不同的记录器,因此您在ClassA中为记录器设置的值与ClassB中的记录器不同。尝试将这两行更改为:

log4net.LogManager.GetLogger("MyLogger");

它应该可以工作。

如果您通读了文档,您会发现在调用this方法时,该方法使用类型名称来加载记录器“类型的全名将用作记录器的名称以进行检索”。由于您的代码中有两种不同的类型,因此最终会有两种不同的记录器。您需要使用通用名称或通用类型来获取相同的记录器实例。

您的另一个选择是在设置文件上设置值,但是我想这对您不起作用,因为它们可能是您需要在运行时设置的值。

答案 1 :(得分:2)

如果您在log4net.GlobalContext中设置属性,则所有记录器都应该可以使用它们。我不确定将parameterName元素添加到log4net.config文件中的位置或原因,但是您不需要它们。

通常,您应在应用程序启动时设置一次log4net.GlobalContext属性。如果仅在方法有效期内需要属性,则可以考虑使用log4Net.ThreadContext

This dotnetfiddle与您的代码相似,并给出您想要的结果。

答案 2 :(得分:0)

如果需要跟踪整个库中的这些参数,则可以读写设置文件。 https://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx