If the number of jobs is not known in advance and the requirement is one log file per job, it is possible to update the NLog configuration programmatically at the start of each job.
At the start of the job, create a new NLog target.
var target = new NLog.Targets.FileTarget()
{
FileName = $"Arquivo{jobNumber}.Log",
Name = $"logfile{jobNumber}",
Layout = "${logger} ${longdate} ${level} ${message}",
//add settings are required
};
Then get the existing NLog configuration, add the target and add a rule for the target.
var config = NLog.LogManager.Configuration;
config.AddTarget(target);
config.AddRuleForAllLevels(target, loggerName);
Finally call ReconfigExistingLoggers
. (see ReconfigExistingLoggers, this answer and this forum entry)
NLog.LogManager.ReconfigExistingLoggers();
The jobs are in all likelihood concurrent, so a locking mechanism is required.
The code above will append to an existing configuration, even when there is a Nlog.config file present.
Here is a full sample.
using NLog;
using System.Threading;
using System.Threading.Tasks;
using NLog.Config;
namespace ConsoleApplication2
{
class Program
{
private static readonly object LoggerSynchronization = new object();
static void Main(string[] args)
{
//create some jobs
int numberOfJobs = 5;
for (int i = 0; i < numberOfJobs; i++)
{
var jobNumber = i;
Task.Run(() => RunJob(jobNumber));
}
Thread.Sleep(1000); //wait till done
}
private static void RunJob(int jobNumber)
{
var logger = SetupLog(jobNumber);
logger.Info($"Running job {jobNumber}.");
//do stuff here ...
}
private static Logger SetupLog(int jobNumber)
{
var loggerName = $"Job{jobNumber}";
//create a custom target per job
var target = new NLog.Targets.FileTarget()
{
FileName = $"Arquivo{jobNumber}.Log",
Name = $"logfile{jobNumber}",
Layout = "${logger} ${longdate} ${level} ${message}",
};
//add the target to the configuration
lock (LoggerSynchronization) //avoid concurrency issues between the jobs
{
//check if configuration exists
if (NLog.LogManager.Configuration == null)
{
NLog.LogManager.Configuration = new LoggingConfiguration();
}
var config = NLog.LogManager.Configuration;
config.AddTarget(target);
config.AddRuleForAllLevels(target, loggerName);
NLog.LogManager.ReconfigExistingLoggers();
}
return NLog.LogManager.GetLogger(loggerName);
}
}
}
And sample 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"
autoReload="true"
throwExceptions="false">
<targets>
<target name="console" xsi:type="ColoredConsole" layout="${logger} ${longdate} ${level} ${message}" />
</targets>
<rules>
<logger name="*" writeTo="console" minlevel="Info" />
</rules>
</nlog>
Sample output
