Reputation: 23
I am trying to implement NLog in WPF application.
We need to have two file log target,
1) for debug or developer purpose which is going some "Infologs"
folder
2) for error or exception purpose which is going to some
"Errorlogs" folder in
base directory. Below is my code and configuration in nlog.config for same.
<variable name="ErrorLayout" value="${longdate} | ${logger} | ${level} |
${message} ${exception:format=message,stacktrace:separator=/}" />
<variable name="InfoLayout" value="${longdate} | ${logger} | ${level} |
${message}"/>
<variable name="ErrorDir" value="${basedir}/Errorlogs/${longdate}">
</variable>
<variable name="InfoDir" value="${basedir}/Infologs/${longdate}"></variable>
<target xsi:type="File" name="fileLogException" archiveEvery="Month"
createDirs="true" lineEnding="Default" layout="${ErrorLayout}"
fileName="${ErrorDir}.log"/>
<target xsi:type="File" name="fileLogInfo" archiveEvery="Month"
createDirs="true" lineEnding="Default" layout="${InfoLayout}"
fileName="${InfoDir}.log"/>
<logger name="*" minlevel="Error" writeTo="fileLogException"/>
<logger name="*" minlevel="Info" writeTo="fileLogInfo"/>
Expected result:
_logger.Info("Sample informational message");//This should write to only fileLogInfo
_logger.Error("Sample error message"); //this should write to only fileLogException
_logger.Fatal("Sample fatal error message"); //this should write to only fileLogException
Current result:
_logger.Info() write to --> fileLogInfo
_logger.Error() & _logger.Fatal() both write to --> fileLogInfo and fileLogException
Any help please , Thanks
Upvotes: 2
Views: 2553
Reputation: 13763
There are multiple approaches here. Option 3. is the best solution for your current case, in my opinion.
final
attribute(this is the same answer as Julian's)
<logger name="*" minlevel="Error" writeTo="fileLogException" final="true"/>
<logger name="*" minlevel="Info" writeTo="fileLogInfo"/>
Adding the attribute to fileLogException
means that when a message is written to fileLogException
, NLog will not look for any other logs afterwards.
Note that NLog evaluates loggers from top to bottom. final
will only prevent lower loggers from receiving the same log message.
This is a solution, but it can cause issues in the future. If you remove the fileLogException
(or change the order of loggers), then the content of the fileLogInfo
will change (because no messages are being halted by fileLogException
anymore).
When should you use this option?
When you want to intercept messages and prevent them from being added to other logs.
For your current example, this seems usable at first sight. This is mainly because you are not separating loggers based on their name. But when you start considering loggers withname
requirements and not just level requirements, e.g.
<logger name="MyApplication.Repositories.*" final="true" writeTo="fileLogRepository" />
<logger name="MyApplication.Importers.*" final="true" writeTo="fileLogImport" />
<logger name="*" writeTo="fileLogAllUnloggedMessages" />
it becomes more obvious when you should and shouldn't use this. In the above example, the bottom log will catch all messages except messages which have already been logged by any previous logger (which was marked as
final
, of course).
maxLevel
attributeJust like you've used minLevel
, there is also a maxLevel
attribute.
<logger name="*" minlevel="Error" writeTo="fileLogException"/>
<logger name="*" minlevel="Trace" maxLevel="Info" writeTo="fileLogInfo"/>
fileLogException
logs all messages with a level of Error
and above, whereas fileLogInfo
logs all messages with a level between Trace
and Info
(= Trace
, Debug
and Info
).
When should you use this option?
When you want to strictly define your logger to only ever include messages between a range of accepted log levels.
I changed the level values to prove a point, that it selects all messages with a level that's between the upper limit (maxLevel
) and lower limit (minLevel
).
level
attributeYour fileLogException
is only interested in one level of messages, Info
. Therefore, you can shorten this to
<logger name="*" level="Info" writeTo="fileLogInfo"/>
When should you use this option?
When you want to strictly define your logger to only ever include messages from a single log level.
levels
attributeThe levels
attribute allows you to explicitly specify multiple levels (comma-separated).
<logger name="*" levels="Trace,Info,Fatal" writeTo="fileLogException"/>
When should you use this option?
When you want to strictly define your logger to only ever include messages from multiple log levels that cannot be described with a range.E.g. If you want to log
Info
andError
messages, and you would usemaxLevel
andminLevel
, then Nlog would also include allWarning
messages (as that falls betweenInfo
andError
in the ordered list of log levels). However, you can excludeWarning
messages by usinglevels="Info,Error"
.
All information is based on the NLog documentation
Upvotes: 3
Reputation: 36710
You need the final
attribute on the first <logger>
rule
<logger name="*" minlevel="Error" writeTo="fileLogException" final="true"/>
<logger name="*" minlevel="Info" writeTo="fileLogInfo"/>
Rules are non-final by default and so the events will be written to all loggers (from top to down), which meet the name and (min)level requirements.
For more info, see the docs
Upvotes: 0