Writing NLog messages to a different target - c#

I want to log messages to file based on a condition. For this I am first writing all the log messages to Memory type and checking the condition in my code behind. I am trying to write to file type, those stacked up (memory) logs only if the condition is true. Here is how my log looks.
<targets>
<target name="file" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
<!--auto-archive above 5 MB or daily. Max archives = 3 days
write to <installdir>/logs/DebugLog.log-->
<target xsi:type="File" name="debugFile" fileName="${basedir}/logs/DebugLog.log"
layout="${message}"
archiveFileName="${basedir}/logs/archives/DebugLog-${shortdate}.{#}.txt"
archiveAboveSize="5242880"
archiveEvery="Day"
archiveNumbering = "Rolling"
maxArchiveFiles="3" />
</target>
<target xsi:type="Memory" name="MemoTarget" layout="${longdate} : ${message}"/>
</targets>
<rules>
<!-- turn logging on by setting minLevel="Debug" (no service restart necesary, it detects the setting change automatically) -->
<logger name="*" minlevel="Debug" writeTo="MemoTarget"/>
<logger name="MyFileLogger" minlevel="Debug" writeTo="debugFile"/>
</rules>
Here is the code behind.
if (dTimeRTaken > 7000)
{
StringBuilder stringBuilder = new StringBuilder();
var target = (MemoryTarget)LogManager.Configuration.FindTargetByName("MemoTarget");
var logger = LogManager.GetLogger("MyFileLogger");
foreach (var loggingEvent in target.Logs.ToArray())
{
stringBuilder.AppendLine(loggingEvent);
}
logger.Debug(stringBuilder);
LogManager.Flush();
}
The problem here is flush is not working and memory target messages are being appended. The file contents are like
1
12
123
1234
I want the output as 1 2 3 4

Maybe use a BufferingWrapper around your file-target. Like this:
<targets>
<target name="memoFile" xsi:type="BufferingWrapper" bufferSize="10000" overflowAction="Discard">
<target name="asyncFile" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
<target name="debugFile" xsi:type="File" fileName="${basedir}/logs/DebugLog.log">
</target>
</target>
</target>
</targets>
<rules>
<!-- MyFileLogger writes directly to file without being stalled in buffer -->
<logger name="MyFileLogger" minlevel="Debug" writeTo="asyncFile" final="true" />
<!-- All other loggers writes to memory buffer and waits for flush -->
<logger name="*" minlevel="Debug" writeTo="memoFile" final="true" />
</rules>
But if you want manual control of the logevents without BufferingWrapper, then you should just ensure to configure the logging rules like this:
<rules>
<!-- MyFileLogger writes directly to file without being stalled in buffer -->
<logger name="MyFileLogger" minlevel="Debug" writeTo="asyncFile" final="true" />
<!-- All other loggers writes to memory buffer and waits for flush -->
<logger name="*" minlevel="Debug" writeTo="MemoTarget" final="true" />
</rules>

Related

Nlog not loggin to File

my nlog not creating files. I Use the same configuration in another project and everythink is Ok, but in new project nlog not create new files.
Nlog config :
<?xml version="1.0" encoding="utf-8" ?>
autoReload= "true"
internalLogLevel =" Trace"
internalLogFile ="c:\temp\internal-nlog.txt">
<targets>
<target name="file" xsi:type="File"
layout="${longdate} ${logger} ${message}${exception:format=ToString}"
fileName="C:\beka\logs\logfile.txt"
/>
<target name="exceptions" xsi:type="File"
layout="${longdate} ${logger} ${message}${exception:format=ToString}"
fileName="C:\beka\logs\logfileExceptions.txt"
/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="file" />
<logger name="*" minlevel="Error" writeTo="exceptions" />
</rules>
On the console I can see that the log has been called but its not sent to a file.
I think the problem can be in c:\temp\internal-nlog.txt becouse this file has references to another project. And when i start another project internal-nlog.txt is update but when i start this project internal-nlog-txt doesnt update
Nlog action = content,
Copy to outputDirectory = copy if newer

c#, Nlog and change target

i am running windows service,
and i want when i run in debugto to write to console
and when as service to event viewer.
in powershell i set
New-EventLog –LogName Application –Source "mySource"
I have this nlog.config:
<nlog>
<targets>
<target name="debugger" type="Debugger" layout="${logger}::${message}"/>
<target name="console" type="Console" layout="${logger}::${message}"/>
<target name="file" type="File" layout="${longdate} ${logger}::${message}" fileName="${basedir}/Logs/${shortdate}.log"/>
<target name="eventLog" type="eventlog" layout="${logger}::${message}" source="mySource"/>
</targets>
<rules>
<logger name="" minlevel="Trace" writeTo="debugger"/>
<logger name="" minlevel="Trace" writeTo="console"/>
<logger name="*" minlevel="Trace" writeTo="file"/>
<logger name="*" minlevel="Debug" writeTo="eventLog" />
</rules>
</nlog>
i do init when service start :
public static void InitLogger()
{
NLog.Targets.Target target = null;
target = LogManager.Configuration.FindTargetByName("eventlog");
NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target, LogLevel.Info);
LogManager.Configuration.Reload();
}
to test this i change it in both cases to write to "eventlog"
even in debug mode. but it is not working correctly when using the event viewer (VS is running in admin mode)
i set in each class
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
what is missing?
This line will load the NLog.config and lookup a named target:
target = LogManager.Configuration.FindTargetByName("eventlog");
This line will discard the original NLog config (with all rules and targets) and create new one with a single target:
NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target, LogLevel.Info);
This line will not do anything:
LogManager.Configuration.Reload();
I guess you are trying to add an extra target to the existing configuration. This can be done like this (Replacing all the above code):
LogManager.Configuration.AddRule("*", LogLevel.Info, target):
LogManager.ReconfigExistingLoggers();
Btw. if you don't configure the Source-property for the EventLog-target, then it will use AppDomain.FriendlyName

NLog for asp.net core is not filtering Microsoft logs

I have the following nlog.config file in ASP.NET Core 2.1 project. However, it's logging messages from every logger (including Microsoft logger) to console.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Error"
internalLogFile="${specialfolder:folder=UserProfile}\nlog\internal-nlog.txt">
<variable name="fullLayout" value="${shortdate} [${uppercase:${level}}] ${logger}: ${message} ${exception:format=tostring} url: ${aspnet-request-url}" />
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<!-- write to console -->
<target name="console" xsi:type="ColoredConsole" layout="${fullLayout}" />
<!-- write to file -->
<target xsi:type="File"
name="allfile"
fileName="${defaultDirectory}/test-api-all.log"
archiveEvery="Day"
archiveFileName="${defaultDirectory}/test-api-all-${#}.log"
archiveNumbering="Date"
archiveDateFormat="yyyy-MM-dd"
maxArchiveFiles="5"
layout="${fullLayout}" />
<!-- another file log, only own logs. Uses some ASP.NET core renderers -->
<target xsi:type="File"
name="ownFile-web"
fileName="${defaultDirectory}/test-api-app.log"
archiveEvery="Day"
archiveFileName="${defaultDirectory}/test-api-app-${#}.log"
archiveNumbering="Date"
archiveDateFormat="yyyy-MM-dd"
maxArchiveFiles="5"
layout="${fullLayout}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="console" />
<!--Skip non-critical Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" maxLevel="Info" final="true" />
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
</nlog>
I do not have any logging settings in appsettings.json files. All logger configuration in in nlog.config. In the Program.cs, I'm registering NLog like:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging => logging.ClearProviders())
.UseNLog()
.Build();
How can I filter out Microsoft logs?
EDIT:
Above configuration started working without a problem the next day without me making any changes :O
Maybe this will work:
<!-- rules to map from logger name to target -->
<rules>
<!--Skip non-critical Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" maxLevel="Info" final="true" />
<logger name="*" minlevel="Trace" writeTo="console" />
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
The order of the logging rules are important, as the rules are matched from the top. See also https://github.com/NLog/NLog/wiki/Configuration-file#rules
The order of your logging rules seems to be correct. I suggest trying to double check if your updated nlog.config file is being copied to the build directory (e.g. \bin\Debug\netcoreapp2.1\nlog.config)
I kind of encountered the same issue, but found out that debugging using Visual Studio, it sometimes doesn't really copy the nlog.config file to your build directory. So the solution is to Clean the project first, then Build, and finally Debug.

How to set debugEnabled/InfoEnabled in nlog.config

I have Logger of NLog package,
I want to define trace enable=true in my config logger file.
How can I do it?
My NLog.config file:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="logfile" xsi:type="File" fileName="file.txt" />
<target name="logconsole" xsi:type="Console" />
</targets>
<rules>
<logger name="*" maxlevel="Trace" minlevel="Trace" writeTo="logfile" />
</rules>
</nlog>
You do this by setting the minLevel attribute in your rules section of the NLog.config like so;
<rules>
<logger name="*" minlevel="Debug" writeTo="CSVFile" />
</rules>
Debug will write out Debug, Info, Warn, Error and Fatal-level log messages. Only Trace is skipped.
EDIT
Conversely, if you wanted to only log Trace, then set the maxLevel like so;
<rules>
<logger name="*" maxlevel="Trace" writeTo="CSVFile" />
</rules>
To just log a specific intermediate level, use minLevel and maxLevel together like;
<rules>
<logger name="*" minlevel="Debug" maxlevel="Debug" writeTo="CSVFile" />
</rules>
EDIT2
I tweaked your config file such that the output logs to the console rather than the file;
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="logfile" xsi:type="File" fileName="file.txt" />
<target name="logconsole" xsi:type="Console" />
</targets>
<rules>
<logger name="*" maxlevel="Trace" writeTo="logconsole" />
</rules>
</nlog>
And when run in a test application where I'm writing out multiple logging levels like so;
_logger.Trace("trace text");
_logger.Debug("debug text");
_logger.Info("info text");
_logger.Warn("warn text");
_logger.Error("error text");
_logger.Fatal("fatal text");
And only the Trace text displays in the console window. One thing of note however, is that the XML in the config file must be correctly formatted. The sample above is working as described in my test application here.
You can create multiple levels of logging by creating multiple logger instaances such as
<rules>
<!-- add your logging rules here -->
<!-- different logger instances for different environments, no levels are mentioned explicitly, can be done if exclusion of some levels is required -->
<logger name="Log.Dev" minlevel="Debug" writeTo="database" enabled="true" />
<logger name="Log.Staging" minlevel="Info" writeTo="database" enabled="true" />
<logger name="Log.Production" minlevel="Error" writeTo="database" enabled="true" />
</rules>
After that while initializing give the name of the logger which you want to initialize
/// <summary>
/// The log.
/// Getting Logger instance from key name defined in Web.config of main web file. Key name is LoggerInstanceName
/// On the basis of name , logger instance and defined rules can be switched from one to another.
/// </summary>
private static readonly NLog.Logger Log = LogManager.GetLogger(Convert.ToString(ConfigurationManager.AppSettings.Get("LoggerInstance")));
Also do not forget to add key in your app settings
<appSettings>
<!--logger instance name-->
<add key="LoggerInstanceName" value="Log.Dev" />
</appSettings>

NLog weirdness - extra fields displayed

I use NLog for debugging/tracing in my app. What's happening is that I am seeing some extra stuff in the output. This is C#/VisualStudio on the Mac, targeting iOS.
Here is an example...
I'm using a target of type "Debugger", and my layout line is:
<layout="${time} ${level} ${callsite}:${callsite-linenumber} ${message}"/>
The call to the logger is:
log.Debug("Added New Key. Code = {0}", code);
And the output is:
AppleLibrary.PasswordMgr: 16:04:36.4064 Debug
AppleLibrary.PasswordMgr.SavePassword:55 Added New Key. Code = -34018
Every debug line starts with <logger name>:
Its even worse when I use a target type of "Console" with exactly the same layout. A call like this:
log.Debug("Started Application");
ends up with this:
2017-06-14 16:04:23.673 MyApp.iOS[11942:6245589] 16:04:23.6374 Debug MyApp.iOS.Application.Main:14 Started Application
in this case every line starts with: 2017-06-14 16:04:23.673 MyApp.iOS[11942:6245589], which looks like the long date, logger name and thread/tick information.
Note that this does not happen with my file target, even though it uses exactly the same layout! The above call shows this in the logfile.txt:
16:04:23.6374 Debug MyApp.iOS.Application.Main:14 Started Application
Which is exactly what I want.
Here is my NLog.config:
<?xml version="1.0" encoding="utf-8"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true">
<targets>
<target name="logfile"
xsi:type="File"
header="############STARTING RUN ${date} ${time}"
archiveOldFileOnStartup="true"
maxArchiveFiles="5"
fileName="/Users/Paul/Dev/MyApp/MyApp.iOS/logfile.txt"
layout="${time} ${level} ${callsite}:${callsite-linenumber} ${message}"/>
<target name="console" xsi:type="Console"
layout="${time} ${level} ${callsite}:${callsite-linenumber} ${message}"/>
<target name="debugger"
xsi:type="Debugger"
layout="${time} ${level} ${callsite}:${callsite-linenumber} ${message}"/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="logfile" />
<logger name="CoreLibrary.*" minlevel="Trace" writeTo="debugger" enabled="false" />
<logger name="AppleLibrary.*" minlevel="Debug" writeTo="debugger" />
<logger name="MyApp.iOS.*" minlevel="Debug" writeTo="console" />
</rules>
</nlog>
I'd appreciate any pointers as to what I'm misunderstanding here.
Thanks.
Paul.

Categories

Resources