in my C# application (.NET Framework 4.8.1) i want to do some logging and messaging. For this purpose I decided to use NLOG and I don't want to configure this using the config file but programmatically. Also I need two loggers, one which logs to console and a logfile, the other which logs to memory only. This is how I create the loggers in my logger class:
internal static class Logger
{
private static NLog.Logger _logger = null;
private static NLog.Logger _message = null;
private static ColoredConsoleTarget _consoleTarget = null;
private static FileTarget _fileTarget = null;
private static MemoryTarget _memTarget = null;
private const string _loggerName = "logger";
private const string _loggerConsoleTarget = "consoleTarget";
private const string _loggerFileTarget = "fileTarget";
private const string _memoryTarget = "memTarget";
private const string _loggerRule = "loggerRule";
private const string _messageLoggerName = "messageLogger";
private const string _messageLoggerRule = "messageRule";
// access file and console logger
public static NLog.Logger Log
{
get
{
if (_logger == null) CreateLogger();
return _logger;
}
}
// access memory logger
public static NLog.Logger Msg
{
get
{
if (_message == null) CreateMessage();
return _message;
}
}
// get memory logger content
public static IList<string> MemoryLog
{
get
{
MemoryTarget target = LogManager.Configuration.FindTargetByName<MemoryTarget>(_memoryTarget);
return target == null ? new List<string>() : target.Logs;
}
}
public static bool hasMemoryLog
{
get
{
MemoryTarget target = LogManager.Configuration.FindTargetByName< MemoryTarget>(_memoryTarget);
return target != null && target.Logs.Count > 0;
}
}
private static FileTarget CreateFileTarget()
{
FileTarget fileTarget = new FileTarget(_loggerFileTarget)
{
FileName = Path.Combine(ConnectionHandler.UserDataFolder, $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.log"),
ArchiveAboveSize = 1024 * 1024 * 10, // 10 MB
MaxArchiveFiles = 10,
ArchiveNumbering = ArchiveNumberingMode.Rolling
};
return fileTarget;
}
// create file and console logger
public static void CreateLogger()
{
_logger = LogManager.GetLogger(_loggerName);
if (LogManager.Configuration == null)
LogManager.Configuration = new LoggingConfiguration();
_consoleTarget = new ColoredConsoleTarget(_loggerConsoleTarget);
LogManager.Configuration.AddTarget(_consoleTarget);
_fileTarget = CreateFileTarget();
LogManager.Configuration.AddTarget(_fileTarget);
LoggingRule rule = new LoggingRule(_loggerRule);
rule.Targets.Add(_consoleTarget);
rule.Targets.Add(_fileTarget);
rule.SetLoggingLevels(LogLevel.Info, LogLevel.Fatal);
rule.LoggerNamePattern = _loggerName;
LogManager.Configuration.AddRule(rule);
}
// create memory logger
private static void CreateMessage()
{
_message = LogManager.GetLogger(_messageLoggerName);
if (LogManager.Configuration == null)
LogManager.Configuration = new LoggingConfiguration();
_memTarget = new MemoryTarget(_memoryTarget);
LogManager.Configuration.AddTarget(_memTarget);
LoggingRule rule = new LoggingRule(_messageLoggerRule);
rule.Targets.Add(_memTarget);
rule.SetLoggingLevels(LogLevel.Trace, LogLevel.Info);
rule.LoggerNamePattern = _messageLoggerName;
}
public static void DestroyLogger()
{
if (_logger == null) return;
LogManager.Configuration.RemoveTarget(_loggerConsoleTarget);
LogManager.Configuration.RemoveTarget(_loggerFileTarget);
LogManager.Configuration.RemoveRuleByName(_loggerRule);
_logger = null;
_consoleTarget = null;
if (_message == null)
_fileTarget = null;
}
public static void DestroyMessage()
{
if (_message == null) return;
LogManager.Configuration.RemoveTarget(_memoryTarget);
LogManager.Configuration.RemoveRuleByName(_messageLoggerRule);
_memTarget = null;
_message = null;
if (_logger == null)
_fileTarget = null;
}
public static void ClearMessageLog()
{
if (_memTarget == null) return;
_memTarget.Logs.Clear();
}
public static void setMinLogLevel(LogLevel level)
{
LoggingRule rule = LogManager.Configuration.FindRuleByName(_loggerRule);
rule.SetLoggingLevels(level, LogLevel.Fatal);
}
}
First I call 'CreateLogger', then I call Logger.Log.Info("some logging text"). So, in short:
_logger = LogManager.GetLogger(_loggerName);
if (LogManager.Configuration == null)
LogManager.Configuration = new LoggingConfiguration();
_consoleTarget = new ColoredConsoleTarget(_loggerConsoleTarget);
LogManager.Configuration.AddTarget(_consoleTarget);
_fileTarget = CreateFileTarget();
LogManager.Configuration.AddTarget(_fileTarget);
LoggingRule rule = new LoggingRule(_loggerRule);
rule.Targets.Add(_consoleTarget);
rule.Targets.Add(_fileTarget);
rule.SetLoggingLevels(LogLevel.Info, LogLevel.Fatal);
rule.LoggerNamePattern = _loggerName;
LogManager.Configuration.AddRule(rule);
_logger.Info("som log text");
For some reason it doesn't log anything. When I call Logger.Log.Info(logmessage), it doesn't write anything, neither to console nor to file. When I step into the Info method, it shows, that 'IsInfoEnabled' is false, although I set the appropriate log levels to the rules. In the rules the appropriate loglevel array entries are set to true.
What am I doing wrong? I searched the net but most articles refer to the config file method. The NLog documentation has no examples (or I didn't find them) and does not tell very much.
Make the configuration occur before the CreateLogger. This line of code should be the last line in CreateLogger, rather than at the top.
_logger = LogManager.GetLogger(_loggerName);