I am currently running a windows service that creates multiple instances of a class.
At the top of the service class and every other class in my solution, I have something like this:
private static readonly ILog _log = LogManager.GetLogger(typeof(SomeClassTypeHere));
In my App.config, I have Log4Net configured for a single file:
<log4net debug="true">
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs\SomeLogFileName.xml" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<countDirection value="1" />
<maxSizeRollBackups value="30" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.XmlLayoutSchemaLog4j">
<locationInfo value="true" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
This works great in most respects, and everything logs to a single file. However, I'd really like to create a separate log file for each instance of a particular class that my service creates.
This is a class that we often need to monitor for support and we can have a handful of instances running at the same time.
We don't know which instances will be running at a given time, so it makes creating static files in the configuration kinda painful.
I tried taking off the readonly modifier and setting the following in the class constructor:
_log = LogManager.GetLogger("DataCollectionClass_" + deviceName + "_" + DateTime.Now.ToString("MMddyyyy"), typeof(SomeClassTypeHere));
But that requires that I define an appender manually in the configuration, which would be cumbersome and tough to keep up with.
Any thoughts on doing this in L4N? I have seen links here but don't really know if that much frameworking is necessary.
The code below shows how you can programatically configure log4Net without using a configuration file to achieve the effect you're looking for. Basically, it just involves creating a named logger and adding to the hierarchy.
I used as a starting point one of the answers from here.
using log4net;
using log4net.Appender;
using log4net.Layout;
using log4net.Repository.Hierarchy;
namespace LoggerTest
{
class Program
{
static void Main(string[] args)
{
DeviceConnection dev1 = new DeviceConnection("Device1");
DeviceConnection dev2 = new DeviceConnection("Device2");
dev1.DoSomething();
dev2.DoSomething();
}
}
public class DeviceConnection
{
private string name;
private readonly ILog logger;
public DeviceConnection(string _name)
{
name = _name;
logger = TestLogger.AddNamedLogger(name);
logger.Info("---- Begin Logging for DeviceConnection: " + name);
}
public void DoSomething()
{
logger.Info("Doing something for device connection " + name);
}
}
public static class TestLogger
{
private static PatternLayout _layout = new PatternLayout();
private const string LOG_PATTERN = "%d [%t] %-5p %m%n";
public static string DefaultPattern
{
get { return LOG_PATTERN; }
}
static TestLogger()
{
_layout.ConversionPattern = DefaultPattern;
_layout.ActivateOptions();
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
hierarchy.Configured = true;
}
public static PatternLayout DefaultLayout
{
get { return _layout; }
}
public static ILog AddNamedLogger(string name)
{
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
Logger newLogger = hierarchy.GetLogger(name) as Logger;
PatternLayout patternLayout = new PatternLayout();
patternLayout.ConversionPattern = LOG_PATTERN;
patternLayout.ActivateOptions();
RollingFileAppender roller = new RollingFileAppender();
roller.Layout = patternLayout;
roller.AppendToFile = true;
roller.RollingStyle = RollingFileAppender.RollingMode.Size;
roller.MaxSizeRollBackups = 4;
roller.MaximumFileSize = "100KB";
roller.StaticLogFileName = true;
roller.File = name + ".log";
roller.ActivateOptions();
newLogger.AddAppender(roller);
return LogManager.GetLogger(name);
}
}
}