我有一个用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;
现在我在这里面临的问题是,我的类库中有两个名为Class1
和Class2
的类文件。而parameter1
和parameter2
是公开的ClassA
中的变量。如this问题中所述,我无法访问paramter1
中的parameter2
和ClassB
。因此,当打印classB
方法的日志时,parameter1
和parameter2
始终为空。
有没有一种方法可以一次全局设置参数,每当打印日志时,它都使用相同的变量。
我的代码类似于以下内容:
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消息都必须使用它。
在这方面的任何帮助都将受到高度赞赏。
答案 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