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>
Related
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.
I have two layouts in nlog.config. once is Default layout and other one is ErrorLayout in which have additional properties.
the problem is i want to add target and i want to use both layout for LogLevel.Error i have to use ErrorLayout and for the other levels i have to use DefaultLayout. i don't want to create two target because two targets creating two different file and store logs into it.
but i want to both layout into one target.
can I able to do that? How ?
can anyone help me to do this ?
Another option is you use two targets, targeting the same file. If you don't enable keepfileopen, then this is also a good solution.
For example:
<nlog>
<targets>
<target type="file" name="erp" layout="${message}" fileName="log-${shortdate}.log" />
<target type="file" name="erp-error" layout="${message} ${exception:format=tostring}" fileName="log-${shortdate}.log" />
</targets>
<rules>
<logger name="*" minLevel="Error" writeTo="erp-error" final="true" /> <!-- after match events won't be processed futher due to the final attribute -->
<logger name="*" minLevel="Debug" writeTo="erp" />
</rules>
</nlog>
Right now your DefaultLayout and ErrorLayout are quite simple, so you can just do this:
<nlog>
<variable name="DefaultLayout" value="${message}" />
<variable name="ErrorLayout" value="${message} ${exception:format=tostring}" />
<variable name="DynamicLayout= value="${when:when=level<=LogLevel.Info:inner=${DefaultLayout}:else=${ErrorLayout}}" />
<targets>
<target type="file" name="erp" layout="${DynamicLayout}" fileName="log-${shortdate}.log" />
</targets>
<rules>
<logger name="*" minLevel="Debug" writeTo="erp" />
</rules>
</nlog>
See also https://github.com/nlog/NLog/wiki/When-Layout-Renderer
Notice NLog might perform poorly if you include heavy layoutrenders in the ErrorLayout. Ex. like ${callsite}
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).
I am in search of method or ways to log data into multiple tables using NLog. I have more than one log tables with different structures in my case. And, I would like to log two different datas in these two tables.
Please let me know if there is a way to configure NLog to handle two different tables while logging.
You need two database targets, one for each table.
e.g.
<targets>
<target name="table1" xsi:type="Database"
... />
<target name="table2" xsi:type="Database"
... />
</targets>
<rules>
<logger name="logger1" minlevel="Info" writeTo="table1" />
<logger name="logger2" minlevel="Info" writeTo="table2" />
</rules>
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!!