NLog 4.6.6
I have tried everything to get a specific logger disabled and can't get it to work. I'm wondering if it's a bug in NLog. Based on documentation:
There is one more level, Off. Since it is the highest value and is not used for entries, it disables logging when used as the minimum log level.
and:
In case a rule is marked as final and contains any level-declaring attributes, the final attribute applies only to the specified levels.
So if I do the internet-recommended route (even this SO answer), it still gets logged.
<logger name="Example.*" minlevel="Off" final="true" />
<logger name="*" minlevel="Trace" writeTo="file" />
It is important for the answer to show the logger as disabled -- in order to short-circuit expensive debug code -- and not just dump it into the Null target.
A little farther down on the documentation linked in the question in the examples, there is this:
<logger name="Name.Space.*" minlevel="Debug" maxlevel="Error" final="true" />
<logger name="*" writeTo="f1" />
Configures to ignore messages from any class in the Name.Space
namespace with level between Debug and Error (which is Debug, Info,
Warn, Error). The first rule selects loggers, but since there is no
writeTo, these messages are not logged. And, since this rule contains
'final=true', the last rule does not apply to loggers matching the
first rule.
I tried the following and it worked:
<logger name="Example.*" minlevel="Trace" final="true" />
<logger name="*" minlevel="Trace" writeTo="file" />
The key was to just specify the lowest level (Trace) as minlevel, not Off. And that matches the rules of what the documentation says.
I'm guessing this has changed over the versions and hence the confusion.
Related
I'd like to setup a way to easily include/exclude certain log messages from an all encompassing log file. Throughout my code I've logged messages based on a "Context" property, which I was then going to use in when conditions to include/exclude the message.
Here is my setup:
<logger writeTo=""
final="true">
<filters>
<when condition="equals('${event-properties:item=Context}', 'Database')"
action="Log"/>
</filters>
</logger>
<logger name="*"
minlevel="Trace"
writeTo="default"/>
My hope was that I could include/exclude any messages with Context='Database' in the first logger and then change the writeTo attribute to either include the message (i.e. writeTo="default") or exclude (i.e. writeTo="").
The issue seems to be that the first logger is including ALL messages and since final is set to true, no messages are allowed to follow through to the catch all logger? Only logs matching the condition in the logger one are written as expected, however ALL logs are being "finalized" by it.
Any ideas a to what is wrong with my configuration?
Maybe try this instead (Remove final="true" and instead use action="LogFinal")
<targets>
<target xsi:type="Null" name="BlackHole" />
</targets>
<rules>
<logger writeTo="BlackHole">
<filters>
<when condition="equals('${event-properties:item=Context}', 'Database')"
action="LogFinal"/>
</filters>
</logger>
</rules>
Looks like you have to specify an actual target to make the custom logger-filters work (Not dependent on LogLevel).
In an NLog.config file I had to add a new rule to log errors to the event log.
There was already a line specifying an error target:
<logger name="*" minlevel="Error" writeTo="AzureTableStorage" />
So I just added eventlog to the writeTo parameter.
<logger name="*" minlevel="Error" writeTo="AzureTableStorage,eventlog" />
And here is eventlog
<target xsi:type="EventLog"
name="eventlog"
source="MyApp"
layout="${message}${newline}${exception:format=ToString}"/>
However some of the other targets (AzureTableStorage, trace, loggly) all have a blue underline on them and the tooltip says
This is an invalid xsi:type http://www.nlog-project.org/schemas/NLog.trace
In another project the same targets do not have this error.
What do I need to do to remove this error?
This is a error from the XSD, which should be seen as warning. The XSD is generated with all the possible targets (in the NLog main package) and thus doesn't have the custom targets.
These kind of errors could be ignored and NLog won't stop working if the XML config contains these kind of "errors".
I have a logger that configured to multiple targets. Can I filter targets with some conditions?
<logger name="actionsLogger" minlevel="Info" writeTo="fileTarget,rmqTarget1,rmqTarget2" />
I need to always write actions to fileTarget and in some cases to rmqTarget1 and rmqTarget2. Maybe solution is to create multiple loggers with their own targets. But I can't change source code of the project and recompile.
Thanks for the reply. I have found the solution. FilteringWrapper - https://github.com/NLog/NLog/wiki/FilteringWrapper-target. It applies filter for target instead of filter for logger.
<target
xsi:type="FilteringWrapper"
condition="'${event-context:item=Status}'=='Success'"
name="rabbitMQFilteringTarget">
<target
xsi:type="RabbitMQ"
name="rabbitMQTarget"
...
</target>
</target>
Take a look at Conditions on the NLog wiki.
Conditions are filter expressions used with the when filter. They consist of one or more tests. They are used in the when filter to determine if an action will be taken.
You can do this with conditions:
<logger name="actionsLogger" minlevel="Info" writeTo="fileTarget" />
<logger name="actionsLogger" minlevel="Info" writeTo="rabbitMQTarget">
<filters defaultAction="Log">
<when condition="'${event-property:item=Status}'=='Success'" action="Ignore" />
</filters>
</logger>
I have an app where sometimes I'd like to log in Debug mode. Unfortunately i link with a third party lib that I can't rebuild. It was built to use log4net and on the Debug mode it is very verbose.
I don't want to get any notifications from that library. I do however want to get log notifications from all other code that wants to write.
Is there a way to exclude a namespace or library from logging when using either the SMTPAppender or RollingFile Appender writers?
You could use a filter, e.g.
<filter type="log4net.Filter.LoggerMatchFilter">
<!-- allows this sub-namespace to be logged... -->
<loggerToMatch value="Noisy.Namespace.But.Important" />
</filter>
<filter type="log4net.Filter.LoggerMatchFilter">
<!-- ...but not the rest of it -->
<loggerToMatch value="Noisy.Namespace" />
<acceptOnMatch value="false" />
</filter>
More details from this article.
Im imagine that you are using a configuration where you set only the root level of your logging infrastructure:
<root>
<level value="DEBUG" />
<appender-ref ref="A1" />
</root>
However it is possible to define other levels of logging using the logger names. If you or the third party app followed standard practices, your loggers are named after the class they live with its namespace, so you will have loggers called
MyApp.Main
MyApp.Business
MyApp.Business.Messages
ThirdParty.API
etc...
What you can do in this case is declare the logging at the namespace level you're interested in. For example to log only what lives under MyApp.Main add the following
<logger name="MyApp.Main">
<level value="DEBUG" />
<appender-ref ref="A1" />
</logger>
and remove any appender from the root level. Then you only log the loggers that live under the MyApp name. See the documentation for more info.
If you are unlucky and the loggers don't conform to this hierarchy, you can still filter them out by using a LoggerMatchFilter in your appender; this lets you either define what logger can pass, or what loggers cannot. There are lots of filters, feel free to explore them
I'm writing a simple test project to experiment with log4net and I've hit a wall right off the bat. No matter what I do in my config file, the my logger is initialized with all "IsXXXXEnabled" flags set to false. Here is my very simple app.config:
<log4netgroup>
<log4net xsi:noNamespaceSchemaLocation="http://csharptest.net/downloads/schema/log4net.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<param name="LogName" value="Application" />
<param name="ApplicationName" value="HelloProgram" />
<threshold value="DEBUG"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger - %newline%message" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="EventLogAppender" />
</root>
<logger name="HelloLogger">
<level value="DEBUG" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
</log4netgroup>
Here is the trivial test in Main:
ILog Log = LogManager.GetLogger("HelloLogger");
if(Log.IsErrorEnabled)
Console.WriteLine("The logger is working!");
else
Console.WriteLine("Nope");
The output is "Nope". I tried switching the threshold and level values to "ALL", but nothing changed. This seems so simple, what am I missing to enable everything?
Thanks
Fixed it! I don't know why this call is not mentioned in the log4net manual or why I specifically need it, but adding this assembly to my project enabled all log levels:
[assembly:XmlConfigurator(Watch = true)]
Found here:
How do I configure log4net so that log.IsDebugEnabled is true?
You should configure the root logger:
<root>
<level value="DEBUG" />
<appender-ref ref="EventLogAppender" />
</root>
Any non-root loggers (the ones you create with <logger name="...">) apply only to classes whose namespace-qualified name has the logger name as a prefix. So the logger you have created will only apply to a classes that is outside of a namespace and whose name is HelloLogger, or to any classes residing in a namespace called HelloLogger (and possibly within namespaces nested inside that one). (When I say that a logger "applies to" a class X, I mean that that that's the logger you will get when you call LogManager.GetLogger(typeof(X)).)
Edit: You also need to call log4net.Config.XmlConfigurator.Configure(); in order to get log4net to read App.config. Also, delete the outermost <log4netgroup> element and rename the config section name: <section name="log4net" .../>.
Configuring the root logger is not strictly necessary, but the argument of Aasmund is certainly valid. I think the problem is that you try to use the EventLogAppender. For simple tests you should use the ConsoleAppender as this is probably the simplest appender that you can make work in a console application.
The EventLogAppender requires some additional steps to setup: You need to create an event source and that requires administrative rights. The Appender attempts to do this on the fly, but it usually fails silently if UAC is turned on. To see if that is a problem you can try to turn on internal debugging.
Usually you would create an event source with an installation program.
If you are using a separate configuration file for log4net, do this: after following all the other setup instructions, make sure that u right click on the file in the visual studio solution explorer, select properties, expand the "Advanced" option group, set the "Copy To Output Directory" value as "Copy always". That will do the magic... :) cheers!!