Log in a file only if the database fails? - nlog

I have a scenario where I want to log in a file only if the database fails for some reason.
Is it possible to achieve that using NLog ?

Yes, you could use the FallbackGroup target for that. In the fallback group you should configure the database and file target.
e.g.
<target xsi:type="FallbackGroup" name="all" returnToFirstOnSuccess="true">
<target name="target1" xsi:type="Database" ... />
<target name="target2" xsi:type="File" ... />
</target>
<rules>
<logger name="*" minlevel="Trace" writeTo="all" />
</rules>
See https://github.com/NLog/NLog/wiki/FallbackGroup-target

Related

Redirect output from specific logger to a specific NLog Target

Using ASP.NET Core3.1 and NLog, this is a part of my NLog.config:
<nlog>
<targets>
<!-- write logs to file -->
<target name="allfile" xsi:type="File"
fileName="${aspnet-appbasepath}/AspNetCore_Nlog/nlog-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring} | url: ${aspnet-request-url} | controller: ${aspnet-mvc-controller} | action: ${aspnet-mvc-action}"
archiveAboveSize="1000000"
maxArchiveFiles="20" />
<target name="searchedFile" xsi:type="File"
fileName="${aspnet-appbasepath}/AspNetCore_Nlog/whatIsSearched-${shortdate}.txt"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message}"
archiveAboveSize="1000000"
maxArchiveFiles="20"/>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Trace" writeTo="allfile" />
<logger name="whatIsSearched" minlevel="Trace" writeTo="searchedFile" />
</rules>
</nlog>
My problem is that, all the logs inside searchedFile, also exist in allfile.
I need to know if there is a way to exclude a special target from all logs/all file that logs every thing ?
I would move the logging-rule for whatIsSearched to the top, and add final="true":
<rules>
<logger name="whatIsSearched" minlevel="Trace" writeTo="searchedFile" final="true" />
<logger name="*" minlevel="Trace" writeTo="allfile" />
</rules>
See also: https://github.com/nlog/NLog/wiki/Configuration-file#rules

NLog - Daily Log file - how to add a summary when it's triggered or new log file is created

I have the config setup for daily logging. (I assume the following is correct). How can add a 'summary' when the new log file is created. I'd like to add a daily 'count' to the last line in the log file for the day. Is this possible? How do I know when the new log is triggered?
<variable name="logDirectory" value="C:/Logs/" />
<targets async="true">
<target xsi:type="File"
name="ErrorLog"
filename="${logDirectory}PDF.log"
archiveFileName="log.{#}.log"
archiveNumbering="Date"
archiveEvery="Day"
archiveDateFormat="yyyyMMdd" />
NLog FileTarget has support for Footer-layout and Header-Layout.
If you need special statistics then you probably need to write your owned custom layout-renderer.
<nlog>
<targets>
<target name="ErrorLog" xsi:type="File"
header="----------------- Logging started on ${longdate} ------------------"
footer="----------------- Logging finished on ${longdate} -----------------"
filename="${logDirectory}PDF.log"
archiveFileName="log.{#}.log"
archiveNumbering="Date"
archiveEvery="Day"
archiveDateFormat="yyyyMMdd" />
</targets>
<rules>
<logger name="*" minlevel="Error" writeTo="ErrorLog" />
</rules>
</nlog>

Transform that preserve namespace prefixes

I'm trying to insert an NLog custom config section into my Web.config using this XDT section:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" throwExceptions="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xdt:Transform="InsertIfMissing" >
<targets>
<target xsi:type="File" name="logfile" fileName="H:\testLog.txt" layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="logfile" />
</rules>
</nlog>
When I run the XDT transform, my Web.Debug.config contains:
<nlog throwExceptions="true" xmlns="http://www.nlog-project.org/schemas/NLog.xsd">
<targets>
<target d4p1:type="File" name="logfile" fileName="H:\testLog.txt" layout="${longdate} ${uppercase:${level}} ${message}" xmlns:d4p1="http://www.w3.org/2001/XMLSchema-instance" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="logfile" />
</rules>
</nlog>
Typically, a namespace prefix is arbitrary, so transforming xsi to d4p1 would cause no issues.
However, I get a runtime exception in my application from NLog when I use d4p1. Manually changing the instances of d4p1 to xsi fixes the issue, but it subverts the utility of config transformation for me if the user needs to manually alter the file afterward.
Is there a way to preserve namespace prefixes using XDT?
We had exactly the same issue. I'm not sure why it suddenly started happening with a particular project, but the solution for us was to add the xsi namespace to the top level of the original configuration file (ie the base file the transformations work on). So...
<configuration>
... would become...
<configuration xmlns:xsi="http://www.nlog-project.org/schemas/NLog.xsd">
This did the trick.
An alternative approach that also worked was to apply the transforms on child elements of the nlog element.
Hope that helps someone.
I started to see this problem when I moved my xdt:Transform attribute from the target and rule tags to nlog. Moving them back to the original tags like this solved it:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" throwExceptions="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets xdt:Transform="InsertIfMissing">
<target xsi:type="File" name="logfile" fileName="H:\testLog.txt" layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>
<rules xdt:Transform="InsertIfMissing">
<logger name="*" minlevel="Trace" writeTo="logfile" />
</rules>
</nlog>

NLog: How to send log message to console from two different targets without duplications?

I have three targets - Engine, Tasks and Error. Please, find belog their NLog configuration:
<targets>
<target name="EngineLog" xsi:type="File" fileName="C:\Log\EngineLog.txt" layout="${layout}"/>
<target name="ErrorLog" xsi:type="File" fileName="C:\Log\ErrorLog.txt" layout="${layout}"/>
<target name="TasksLog" xsi:type="File" fileName="C:\Log\TasksLog.txt" layout="${layout}"/>
<target name="ConsoleLog" xsi:type="ColoredConsole" layout="${consoleLayout}"/>
</targets>
<rules>
<logger name="*" minLevel="Error" writeTo="ErrorLog"/>
<logger name="N1.*" minLevel="Warn" writeTo="EngineLog" final="true"/>
<logger name="N2.*" minLevel="Info" writeTo="EngineLog" final="true" />
<logger name="N3.*" minLevel="Info" writeTo="EngineLog" final="true" />
<logger name="N4.*" minLevel="Info" writeTo="EngineLog" final="true" />
<logger name="N5.*" minLevel="Info" writeTo="EngineLog" final="true" />
<logger name="N6" minLevel="Info" writeTo="EngineLog" />
<logger name="*" minlevel="Info" writeTo="TasksLog" />
</rules>
Of course, the real namespace names are not N1...N6, what matters is that I have:
5 namespaces which are logged to the Engine log exclusively (N1-N5)
All the errors (both Engine and Tasks) are logged to the same Error log in addition to the respective dedicated target.
One namespace is logged both to Engine and Tasks (N6)
The rest is considered Tasks
Now I would like additionally to log everything going to either ErrorLog or TasksLog to the console.
My first try was to wrap the ErrorLog and TasksLog with a SplitGroup grouping each target with the console target, like this:
<target name="ErrorLog" xsi:type="SplitGroup">
<target xsi:type="File" fileName="C:\Log\ErrorLog.txt" layout="${layout}"/>
<target xsi:type="ColoredConsole" layout="${consoleLayout}"/>
</target>
<target name="TasksLog" xsi:type="SplitGroup">
<target xsi:type="File" fileName="C:\Log\TasksLog.txt" layout="${layout}"/>
<target xsi:type="ColoredConsole" layout="${consoleLayout}"/>
</target>
But this is a wrong approach, because every error gets logged twice on the console - first on behalf of the ErrorLog and then on behalf of the TasksLog.
How can I log errors to the console without duplications while allowing them to go to both the ErrorLog target and the TasksLog/EngineLog targets?
EDIT
The desired effect can be achieved if I could specify to log messages, but not if they are Error or Fatal (because these have already been logged).
OK, I think I have found the solution:
<target name="ErrorLog" xsi:type="SplitGroup">
<target xsi:type="File" fileName="C:\Log\ErrorLog.txt" layout="${layout}"/>
<target name="ConsoleLog" xsi:type="ColoredConsole" layout="${consoleLayout}"/>
</target>
And add the following rule at the end:
<logger name="*" levels="Warn, Info, Debug, Trace" writeTo="ConsoleLog" />

Is it possible to have more Loggers in ServiceStack for the same AppHost?

I'm creating a Plugin for ServiceStack that contains certain services. However, I want these services to Log to another DB (in my case) that the other services in the AppHost.
Is it possible to register 2 ILog interfaces inside the AppHost?
The ServiceStack.Logging.LogManager.GetLogger(GetType()) will always return an ILog interface. Do I need to create a second ILog implementation for the other Logger?
I'm using NLog.
I'm not familiar with ServiceStack, so my suggestion might not make sense (but it does make sense when considering NLog in isolation).
Can't you just configure another Target in the NLog.config file and configure your loggers to write to that Target?
For example...
Configure some targets in the NLog.config (I am configuring a console target and a file target)
<targets>
<target name="file" xsi:type="File" layout="${longdate} | ${level} | ${logger} | ${message}" fileName="${basedir}/${shortdate}.log" />
<target name="console" xsi:type="ColoredConsole" layout="${longdate} | ${level} | ${logger} | ${message}" />
</targets>
Configure some rules
<rules>
<logger name="Your.Name.Space1.*" minlevel="Trace" writeTo="file" />
<logger name="Your.Name.Space2.*" minlevel="Trace" writeTo="file" />
<logger name="*" minLevel="Trace" writeTo="console" />
</rules>
Now, all classes from Your.Name.Space1 and Your.Name.Space2 will log to the "file" target while all other classes will log to the "console" target. You could add "final=true" to the loggers for your classes if you want their logs to appear only in the "file" target.
I think that should all you to do what you want to do.

Resources