我想根据我调用的方法记录两个不同的级别。我正在使用拦截,所以我试图用propery过滤器达到目标。这是我的配置:
<log4net>
<appender name="DoWorkFileAppender" type="log4net.Appender.RollingFileAppender">
<datePattern value="yyyyMMdd'_dowork.log'" />
...
<filter type="log4net.Filter.PropertyFilter">
<key value="realMethod" />
<stringToMatch value="DoWorkTest" />
<acceptOnMatch value="true" />
</filter>
</appender>
<appender name="WebsiteFileAppender" type="log4net.Appender.RollingFileAppender">
<datePattern value="yyyyMMdd'_website.log'" />
...
<filter type="log4net.Filter.PropertyFilter">
<key value="realMethod" />
<stringToMatch value="DoWorkTest" />
<acceptOnMatch value="false" />
</filter>
</appender>
<root>
<appender-ref ref="WebsiteFileAppender">
<threshold value="ERROR" />
</appender-ref>
<appender-ref ref="DoWorkFileAppender">
<threshold value="INFO" />
</appender-ref>
</root>
</log4net>
现在,如果我调用metod DoWorkTest
,一切正常并且消息只写在*_dowork.log
文件中。但是,如果我调用另一个与方法anotherMethod
不匹配的方法,则会在两个文件中写入消息。
我尝试用以下代码替换节点root
:
<root>
<level value="ALL" />
</root>
<logger name="WebSiteLogger">
<level value="ERROR" />
<appender-ref ref="WebsiteFileAppender" />
</logger>
<logger name="PaymentsLogger">
<level value="INFO" />
<appender-ref ref="DoWorkFileAppender" />
</logger>
但是使用此代码没有过滤器匹配。 我有什么要纠正的?谢谢。
答案 0 :(得分:3)
好的,你的问题让我很感兴趣,所以我花了一些时间尝试。据我了解,您需要能够根据方法名称进行过滤。问题是可以基于命名空间和类创建日志,但不能创建方法名称,除非您对其进行硬编码。
在这种情况下,你最终会得到类似的东西:
private void MyMethod()
{
log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString()
+ "." + System.Reflection.MethodBase.GetCurrentMethod().Name);
log.Error("Logging an error from MyMethod");
}
这将允许您根据方法名称进行过滤:
这是appender的过滤器,只记录来自MyMethod的调用:
<filter type="log4net.Filter.LoggerMatchFilter">
<!-- ...accept only logs from MyMethod -->
<loggerToMatch value="Log4netTest.Form1.MyMethod" />
<acceptOnMatch value="true" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
这是另一个过滤器,它不记录MyMethod日志:
<filter type="log4net.Filter.LoggerMatchFilter">
<!-- ...don't accept logs from MyMethod -->
<loggerToMatch value="Log4netTest.Form1.MyMethod" />
<acceptOnMatch value="false" />
</filter>
现在这可以完成工作,但是如果你想要一种更通用的方法来根据方法名称进行记录,请尝试这样的事情:
private void LogErrorByMethod(string message)
{
StackTrace stackTrace = new StackTrace();
StackFrame frame = stackTrace.GetFrame(1);
string fmname = frame.GetMethod().Name;
string dt = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + fmname;
log4net.ILog log2 = log4net.LogManager.GetLogger(dt);
log2.Error(message);
}
然后您可以通过任何方法拨打电话,您的日志将按照方法排序:
private void MyMethod()
{
LogErrorByMethod("Logging from MyMethod");
}
private void Method2()
{
LogErrorByMethod("Logging from Method2");
}
您必须为不同级别使用不同的方法,或传入级别枚举并使用开关,但您可以使用堆栈跟踪找出调用的方法,并基于该方法创建记录器
使用LogByMethod还允许您在模式中使用%logger属性在日志消息中包含方法名称,但如果您想更加明确,可以添加自定义属性:
string fmname = frame.GetMethod().Name;
log4net.GlobalContext.Properties["methodname"] = fmname;
然后你的模式可以包括:
...如果您已经记录了%logger,那么这是多余的,但它允许您自动将方法名称分开,如下所示:
<parameter>
<parameterName value="@method" />
<dbType value="String" />
<size value="100" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{methodname}" />
</layout>
</parameter>
最后,仅仅因为我在滚动,我想到了一种能够按方法名称记录的另一种方法来进行过滤。试试这个,你根本不需要appender中的过滤器:
<logger name="Log4netTest.Form1.Method1" additivity="False">
<level value="INFO"/>
<appender-ref ref="RollingFileAppenderMethod1"/>
</logger>
<root>
<level value="INFO"/>
<appender-ref ref="RollingFileAppenderAllOtherMethods"/>
</root>