I am creating a logging library with NLog and have requirement for setting the logger based on different terminals. What I have done is to create a ILoggerFacade implementation and have the filenames passed as constructor injected with the filename used to create the log file.
Here is my code:
internal static class FileLogFactory
{
#region "Private Static Members"
private static ILog _applicationLog;
private static Dictionary<string, ILog> _terminalLogs;
private static object _syncLock = new object();
#endregion
#region "Constant Fields"
private const string _APPLICATION_LOG = "applicationLog";
private const string _TERMINAL_LOG = "terminalHandlerLog";
private const string _TERMINAL_PREFIX = "filenameprefix";
public const string APPLICATION = "Application";
#endregion
#region "Static Cosntructors"
static FileLogFactory()
{
_terminalLogs = new Dictionary<string, ILog>();
}
#endregion
#region "Static Methods"
internal static ILog CreateLoggerInstance(string filename)
{
lock (_syncLock)
{
if (string.IsNullOrEmpty(filename) || filename == APPLICATION)
{
// Application Log requested.
if (_applicationLog == null)
{
_applicationLog = LogManager.GetLogger(_APPLICATION_LOG);
}
return _applicationLog;
}
// terminal log requested, check if already created else create new.
if (!_terminalLogs.ContainsKey(filename))
{
NLog.GlobalDiagnosticsContext.Set(_TERMINAL_PREFIX, filename);
_terminalLogs.Add(filename, LogManager.GetLogger(_TERMINAL_LOG));
}
return _terminalLogs[filename];
}
}
#endregion
}
And Following are my NLog config
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<variable name="logpath" value="c:/Log"/>
<targets>
<!-- add your targets here -->
<target xsi:type="File"
name="applicationTarget"
layout="${longdate}|${uppercase:${level}}|${threadid}| ${message}"
archiveAboveSize="1024000"
fileName="${logpath}/Application.${shortdate}.log"
/>
<target xsi:type="File"
name="terminalHandlerTarget"
layout="${longdate}|${uppercase:${level}}|${threadid}| ${message}"
archiveAboveSize="1024000"
fileName="${logpath}/${gdc:item=filenameprefix}.${shortdate}.log"/>
</targets>
<rules>
<!-- add your logging rules here -->
<logger name="applicationLog" minlevel="Trace" writeTo="applicationTarget" />
<logger name="terminalHandlerLog" minlevel="Trace" writeTo="terminalHandlerTarget" />
</rules>
</nlog>
The idea is to pass the gdc:item=filenameprefix from code and create log file for each terminal. Now whats happening is GetLogger returns the same object terminalHandlerLog and hence the last filename given takes the preference and from thereon writes always into that file.
I beleive this is because GetLogger follows singleton patterns and creates single object for each logger.
How can this be overriden, is there any setting which could be utilised for this?