NLog OnNewLogFile Handler? - nlog

Is there any event handler or similar that I can hook into, to run some code every time NLog starts a new Log File?
I have an NLog Config like this:
<target name="logfile" xsi:type="File"
fileName="[stuff]"
layout="[more Stuff]"
maxArchiveFiles="4"
archiveAboveSize="102400" />
And I'd kinda like to add some meta-data at the start of every log file (version number, Machine Name, etc. so that every log file comes complete with some contextual information)
I don't expect to be able to configure this text in NLog itself, but I'm hoping that I can tell NLog to run a certain method everytime it's going to create a new Log File.
Is this a thing?

Sounds like you are really looking for the Header-Layout on the FileTarget.
<target name="logfile" xsi:type="File">
<header>--- ${assembly-version} started on ${longdate} ---</header>
</target>
See also https://github.com/NLog/NLog/wiki/File-target
Some combine it with archiveOldFileOnStartup="true" because the Header is only printed when file is created (ensure application restarts will create new file).

You can use FileSystemWatcher.
FileSystemWatcher is watching specific (which you want it) directory, If new file created, handle this event with FileSystemWatcher
For more details : https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=netframework-4.8

Another partial solution to the "What version?" aspect of this problem could come from:
https://github.com/NLog/NLog/wiki/AssemblyVersion-Layout-Renderer

Related

NLog filename per thread

I'm trying to create log filename dynamically using NLog (.NET Framework 4.8). Basically, I would like unique filename created every time new thread is fired. I got it somewhat working with the following sections:
<target xsi:type="File" name="ownFile" header="${machinename}${newline}${threadid}${newline}"
fileName="${mdc:logFolder}\${date:format=yyyyMMdd}\log_${activityid}.txt" layout="${date}|${activityid}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}"
footer="${newline}Finished at: ${date}"/>
<logger name="*" minlevel="Debug" writeTo="ownFile" />
When thread is started, it sets the logFolder using MappedDiagnosticsContext.Set and sets the Trace.CorrelationManager.ActivityId. But there is one problem. The footer part is only written when FileTarget is disposed, which I believe then closes all file appenders cached inside FileTarget.
Is there a way for me to manually close the internal file appender for dynamic file? What I want is when thread is done with its processing is to close the dynamic log file.
I also have another approach working where I add new FileTarget when thread starts and the remove it when thread is finished. It does work, but I would prefer config file solution.
Thanks in advance.

Is it possible to archive logs based on size and on time using NLog

I am using NLog.
I would like to have a size-based file archival and a time-based file archival.
Meaning, every time the log file exceeds 10 MB a new log file is created. Also, every day a new log file is created.
It is clear how to do each of the above separately (https://github.com/NLog/NLog/wiki/FileTarget-Archive-Examples) but not how to use them in tandem.
Without any details of the expected fileName-Layout, then this will work just fine in NLog 4.5 (and newer):
<target type="file" name="logfile" fileName="App-${shortdate}.log" archiveAboveSize="1000000" maxArchiveFiles="30" />
It will produce the following filenames (newest first)
App-20200216.log
App-20200216.2.log
App-20200216.1.log
App-20200215.log
App-20200214.log
App-20200214.1.log
See also: https://github.com/NLog/NLog/wiki/File-target#archive-old-log-files

How to use NLog to write to different file according to parameter

I want to be able to write to logs to a different log file according to one of my log parameters.
Lets say, bankId. Each day and bank will write to their own file like
2019-11-11-bank11.log
2019-11-12-bank11.log
and so on.
How can i achieve that programmatic with some kind of a pattern for the log file.
I don't want to create a new version of my app every time I have a new bankid.
You could set the context in one of the context classes and render it with a layout renderer.
e.g. use ${mdlc} and MappedDiagnosticsLogicalContext:
Config:
<target name="file" xsi:type="File"
fileName="${basedir}/${mdlc:bankid}.log" .. />
Code:
using (NLog.MappedDiagnosticsLogicalContext.SetScoped("bankid", "bank11"))
{
logger.Info("myLogEvent");
}
See also all context layout renderers
Sounds like you have an application-wide setting. For that you should either use:
NLog Config Variables - ${var:bankid}
Global Diagnostic Context - ${gdc:bankid}
I prefer to use the GDC has it has a minimum number of surprises, when modifying at runtime.
You can do this in NLog.config:
<target name="file" xsi:type="File"
fileName="${basedir}/${shortdate}-bank${gdc:bankid:whenEmpty=0}.log" .. />
Then at application startup then you can do this:
NLog.GlobalDiagnosticsContext.Set("bankid","11");
See also: https://github.com/nlog/nlog/wiki/Gdc-Layout-Renderer
You can also extract a setting from config-file:
app.config - https://github.com/NLog/NLog/wiki/AppSetting-Layout-Renderer
appsettings.json - https://github.com/NLog/NLog/wiki/ConfigSetting-Layout-Renderer

how to switch log4net multiple log files using C# code?

I'm using log4net, I would like to have 2 logs,
- BasketballCustomer.log, for all Customers that plays Basketball;
- ChessCustomer.log, for all Customers that plays Chess.
, while for each customer, whether he/she plays Basketball or Chess, is only known until runtime.
I would like to have each log configured separately, about log file name, size, number, log level, etc.
Also, I'd prefer such set up done by C# code, not config file.
How could I do that?
I tried search on net, there are some articles but none meet exactly my requirements
- Log4Net and multiple log files talked about multiple log files but it does not toggle during runtime;
- Configure Log4net to write to multiple files is similiar but it's done in config file....
Please kindly suggest, many thanks!
You can do this by using an environment variable in the log4net.config and then set the value of the environment variable through the C# code
So somewhere in your C# class, do something like:
Environment.SetEnvironmentVariable("log_file_name", "MyLogFileName");
And then in the log4net.config that is used, specify the value to the name of the environment variable. The syntax would be something like this:
<param name="File" value="${log_file_name}".log/>

"Duplicate node detected" in a CruiseControl.NET configuration file

When I launch CruiseControl.NET with a particular configuration file I receive the following error:
ThoughtWorks.CruiseControl.Core.Config.ConfigurationException: Duplicate node detected
What does this mean, and what causes it?
I think you have 2 nodes in your config where it only expected one. Is there any chance you could post the config file it is throwing the exception on here as additional information? I'm using cruisecontrol (not the .net version) currently and find it can be very picky about it's XML files (rightly so) but not tell you anything about where in the file the exceptions were thrown from.
I found that I had an incorrectly structured config file. In particular, some blocks were outside of the configuration section. The error pointed to the second of these exec sections- apparently it didn't like that there was more than one of a given section inside the project.
Thus, the error occurred due a config file like this:
<project>
<tasks>
...
</tasks>
<exec>...</exec>
<exec>...</exec>
<project>
In my case I had something like:
<task>...</task>
<sourceControls>...</sourceControls>
<task>...</task>
<publishers>...</publishers>
It didn't like the two "<task>" nodes so I fixed it by removing the first "<task>" node. I was trying to do some stuff before getting the latest from svn, and then doing the build after that in the second "<task>" node. I'll need to revisit how to do that...any suggestions?

Resources