Reputation: 1052
Having for example this class that inits the NLog config programmatically:
public class NLogConfig
{
public NLogConfiguration(string traceFileName, LogLevel minLogleven, LogLevel maxLogLevel)
{
var config = new NLog.Config.LoggingConfiguration();
// Targets where to log to file
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = $"{traceFileName}.log" };
logfile.Layout = @"${date:format=HH\:mm\:ss}|${level}|${message} ${exception:format=tostring}";
// Rules for mapping loggers to targets
config.AddRule(minLogleven, maxLogLevel, logfile);
// Apply config
LogManager.Configuration = config;
}
}
Now, I call this config in two different classes, e.g.:
public class A
{
public A()
{
var nlogConfig = new NLogConfig("Trace1", LogLevel.Trace, LogLevel.Fatal);
}
}
public class B
{
public B()
{
var nlogConfig = new NLogConfig("Trace2", LogLevel.Info, LogLevel.Fatal);
}
}
Now the problem is, that the two different log level rules will not be taken by the Nlog configuration, so in that case the Trace1.log
and the Trace2.log
log both with the trace
level, while I expected the Trace1.log
to log with the level Trace
and the Trace2.log
to log with the info
log level.
How to fix this behavior, so, I can change the log level dynamically?
Upvotes: 0
Views: 1182
Reputation: 94
At the beginning I would try to overview general design of your app and only then I would give you code samples.
Design overview.
We [developers] like to keep things as simple as possible. One of the ways to achieve this is to separation of responsibilities of software modules. In your case class A (or B) should NOT care what destination file name is or log level. It should just log records and this's all! But you can ask how to write into different files with different settings? For this purpose you should use "targets" and "rules" concepts. Basically, target is just a log destination. It can be a file, console etc. A rule is filter to select only messages you need . It can be just a log level or/and even special filter by class name or/and way more. Actually, the configuration your are showing in the first example is setup of targets and rules. This design should help to separate and simplify things. I hope you understand what I'm talking about otherwise imagine simulation when you require to change logging settings in project with 100 classes that uses logger.
Possible solution.
Classes A and B should create log instance and use it.
public class A
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public A()
{
Logger.Info("Class 'A' created.");
}
}
Nlog configuration usually done at the application startup to execute it only one time during application lifetime.
public static class Program
{
public static void Main()
{
LogConfiguration();
}
private static void LogConfiguration()
{
var config = new LoggingConfiguration()
// Targets where to log to: File and Console
var f1 = new FileTarget("file1") { FileName = "file1.txt" };
var f2 = new FileTarget("file2") { FileName = "file2.txt" };
// Rules for mapping loggers to targets
config.AddRule(LogLevel.Info, LogLevel.Fatal, f1);
config.AddRule(LogLevel.Debug, LogLevel.Fatal, f2);
// Apply config
NLog.LogManager.Configuration = config;
}
}
Possible feature.
From your code seems that you might want to write into "file2.txt" only messages from class B. This is also possible. You need to specify logger name during rule creation as shown here. Small tip: the name you want to use is name of full your class. From this example you will get what I'm talking about.
Upvotes: 1