alface
alface

Reputation: 89

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?

Upvotes: 3

Views: 4082

Answers (2)

Julian
Julian

Reputation: 36700

As addition,

You could create two loggingrules, but another option is to use 1 LoggingRule, and make the filepath depended of the loggername.

e.g.

FileTarget fileTarget = new FileTarget();
fileTarget.FileName = "${basedir}/${logger}.log";
fileTarget.Layout = "${message}";

LoggingRule rule1 = new LoggingRule("*", LogLevel.Debug, fileTarget);

var config = new LoggingConfiguration();
config.AddTarget("log1", fileTarget);
config.LoggingRules.Add(rule1);

LogManager.Configuration = config;

var logger1 = LogManager.GetLogger("logger1");
logger.Trace("im logger1 to logger1.log");


var logger2 = LogManager.GetLogger("logger2");
logger.Trace("im logger2 and going to logger2.log");

Upvotes: 3

Striezel
Striezel

Reputation: 3758

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. ;)

Upvotes: 5

Related Questions