alface alface - 12 days ago 6
C# Question

How to log to two different files using NLog

I have the following class:

private string name;
private Logger logger;
private LogLevel lvl;
private LoggingConfiguration config;

public Logger(string name, string path, string format, LogLevel lvl)
{
this.name = name;

FileTarget fileTarget = new FileTarget();
fileTarget.FileName = path;
fileTarget.Layout = format;

this.lvl = lvl;
LoggingRule rule = new LoggingRule(name, lvl, fileTarget);

config = new LoggingConfiguration();
config.AddTarget(name, fileTarget);
config.LoggingRules.Add(rule);

LogManager.Configuration = config;

logger = LogManager.GetLogger(this.name);
logger.Trace("test");
}


I create two different loggers like this:

Logger("log1", "c:\\test\\log1.txt", ${message}, LogLevel.Debug);
Logger("log2", "c:\\test\\log2.txt", ${message}, LogLevel.Debug);


Both files are created with the string test. But when I try to log a message with (a class method):

public void Log(string msg)
{
logger = NLog.LogManager.GetLogger(name);
//LogManager.Configuration = config;
//LogManager.Configuration.Reload();
logger.Log(lvl, msg);
}


The message is only logged in the second file. What am I doing wrong?

Answer

I'm not quite sure, but as far as I remember the LogManager.Configuration is kind of global and is used for all loggers created thereafter. So the second call to your Logger() function overwrites the configuration settings you made during the first call. That is why the logging only happens in the later file.

To fix this, you have to create both file targets plus rules for them first and then add the targets and rules to the logging configuration.

So the basic approach (without separate function) should look somewhat like this: (Caution: Code has not been tested, so copy & paste at your own risk!)

FileTarget fileTarget1 = new FileTarget();
fileTarget1.FileName = "C:\\foo\\bar1.txt";
fileTarget1.Layout = "${message}";

FileTarget fileTarget2 = new FileTarget();
fileTarget2.FileName = "C:\\foo\\bar2.txt";
fileTarget2.Layout = "${message}";

LoggingRule rule1 = new LoggingRule("log1", LogLevel.Debug, fileTarget1);
LoggingRule rule2 = new LoggingRule("log2", LogLevel.Debug, fileTarget2);

config = new LoggingConfiguration();
config.AddTarget("log1", fileTarget1);
config.LoggingRules.Add(rule1);
config.AddTarget("log2", fileTarget2);
config.LoggingRules.Add(rule2);

LogManager.Configuration = config;

logger = LogManager.GetLogger(this.name);
logger.Trace("test");

I'll leave the details of how to put that in some kind of reusable function/method as an exercise for the reader. ;)