I have a program that starts smaller programs, or tasks, and now I want each task to log to their own filename dynamically, preferrably using the name of task.
I've digged around a little and it seems that there's a nifty %property
thing that you can use with Log4Net. So I tried that. But it seems that Log4Net doesn't pickup changes for this after it has been initialized.
I wrote a little test program to play around with. I would prefer to only build the windsor container once, but then Log4Net won't be "reinitialized", and create a new logfile. So now I have to build the container before starting the task to be sure that I get the right filename on the logfile.
Does anyone know if there's a better/smarter way to change the filename of the log during runtime?
Here's my testcode:
public class Program
{
static void Main(string[] args)
{
GlobalContext.Properties["LogName"] = "default";
XmlConfigurator.ConfigureAndWatch(new FileInfo("log4net.config"));
while (true)
{
Console.WriteLine();
Console.Write("> ");
string cmd = (Console.ReadLine() ?? string.Empty);
if (string.IsNullOrWhiteSpace(cmd)) continue;
if (cmd.ToLower() == "exit") Environment.Exit(0);
ExecuteTask(Regex.Split(cmd, @"\s+"));
}
}
private static void ExecuteTask(string[] args)
{
//This changes the filename Log4Net logs to, but Log4Net only picks it up if I rebuild my container
GlobalContext.Properties["LogName"] = args[0];
//This should only be run once. No real need to build the container before each run, except to reinitialize Log4Net
var container = BuildContainer();
try
{
var task = container.Resolve<ITask>(args[0]);
task.DoLog();
}
catch (Exception)
{
// This doesn't work as expected, Log4Net logs to the file specified outside of the trycatch
GlobalContext.Properties["LogName"] = "default";
var logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
logger.Info("Could not find "+args[0]);
}
}
private static WindsorContainer BuildContainer()
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
var container = new WindsorContainer();
container.Install(
FromAssembly.This());
return container;
}
}
public interface ITask
{
void DoLog();
}
public class TwoTask : ITask
{
private readonly ILogger _logger;
public TwoTask(ILogger logger)
{
_logger = logger;
}
public void DoLog()
{
_logger.Info("Hello!");
}
}
public class OneTask : ITask
{
private readonly ILogger _logger;
public OneTask(ILogger logger)
{
_logger = logger;
}
public void DoLog()
{
_logger.Info("Hello!");
}
}
public class Installer : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn(typeof(ITask))
.Configure(c => c.LifeStyle.Transient.Named(c.Implementation.Name)));
container.AddFacility<LoggingFacility>(f => f.UseLog4Net("log4net.config"));
}
}
Nugets used: Castle.Core, Castle.Core-log4net, Castle.LoggingFacility, Castle.Windsor