Reputation: 1524
Not sure whats going on here, but my logging code will not write to the rollingFileAppender unless I call XmlConfigurator.Configure() on every call. I have turned on debugging in the following code and can confirm that when Configure is called just the one time in the constructor it does appear to be pulling in my configuration, but when Log() is actually called, nothing happens to the log file OR shows up in the debug window. If I uncomment that call to Configure() in Log() and let it reconfigure on every call, then it works just fine, but I don't think that is intended usage.
Bonus Points! - I notice that the very first call to log.Info() is not logging, but all subsequent ones in each run of the process are fine.
Thanks!
public static class LogToFile
{
public const string RollingFileAppenderName = "RollingFileLogger";
static LogToFile()
{
log4net.Config.XmlConfigurator.Configure();
}
public static void Log(string fileNameBase, string message, string context)
{
if (fileNameBase == null) throw new ArgumentNullException("fileNameBase");
if (message == null) throw new ArgumentNullException("message");
if (context == null) throw new ArgumentNullException("context");
//log4net.Config.XmlConfigurator.Configure();
string fileName = string.Format("{0}_{1}.log", fileNameBase, context);
string fullFileName = Path.Combine(Properties.Settings.Default.LogFilePath, fileName);
if (!Directory.Exists(Properties.Settings.Default.LogFilePath)) Directory.CreateDirectory(Properties.Settings.Default.LogFilePath);
LogicalThreadContext.Properties["LogName"] = string.Format(fullFileName);
ILog log = LogManager.GetLogger(RollingFileAppenderName);
log.Info(message);
}
}
<appender name="rollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="%property{LogName}" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="2MB" />
<countDirection value="-1"/>
<LockingModel value="log4net.Appender.FileAppender+MinimalLock"/>
<staticLogFileName value="false" />
<immediateFlush value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="AlertMessageHandler Message : %-25date [%thread] - %newline%message%newline" />
</layout>
</appender>
Upvotes: 3
Views: 2748
Reputation: 1524
Actuall sgmoore's advice led me to the solution. If I can just name the log file on the Appender object instead of messsing with the config file Property, then calling ActivateOptions works just fine. Here's the working code. Thanks!
public static class LogToFile
{
public const string RollingFileLoggerName = "RollingFileLogger";
public const string RollingFileAppenderName = "rollingFileAppender";
private static readonly ILog Logger = LogManager.GetLogger(RollingFileLoggerName);
/// <summary>
/// Logs to log4net rollingFileAppender
/// </summary>
/// <param name="fileNameBase">prefix of log filename</param>
/// <param name="message">log4net message property</param>
/// <param name="context">files grouped by context</param>
public static void Log(string fileNameBase, string message, string context)
{
if (fileNameBase == null) throw new ArgumentNullException("fileNameBase");
if (message == null) throw new ArgumentNullException("message");
if (context == null) throw new ArgumentNullException("context");
string fileName = string.Format("{0}_{1}.log", fileNameBase, context);
string fullFileName = Path.Combine(Properties.Settings.Default.LogFilePath, fileName);
if (!Directory.Exists(Properties.Settings.Default.LogFilePath)) Directory.CreateDirectory(Properties.Settings.Default.LogFilePath);
ActivateAppenderOptions(string.Format(fullFileName));
Logger.Info(message);
}
/// <summary>
/// Update the appender in log4net after setting the log file path
/// </summary>
/// <param name="filename"></param>
private static void ActivateAppenderOptions(string filename)
{
var hierarchy = (Hierarchy)LogManager.GetRepository();
var appenders = hierarchy.GetAppenders();
foreach (
var rfa in appenders.OfType<RollingFileAppender>().Where(rfa => rfa.Name == RollingFileAppenderName))
{
rfa.File = filename;
rfa.ActivateOptions();
}
}
}
Upvotes: 1
Reputation: 16067
Your configuration file says that the logfile name is set to use the LogName property which you are changing at runtime. I always thought you were not allowed to change the properties on an appender at runtime without reinitialising the appender (by called ActivateOptions) or by calling XmlConfigurator.Configure() which is easier but will do a lot more.
Also in your log method, if you call XmlConfigurator.Configure() before setting LogName, then I would suspect your first call would fail (trying to write to null) and your second call would write to the file that was supposed to be used with the first call.
If you move XmlConfigurator.Configure() to after you set LogName, it should work properly.
Upvotes: 2
Reputation: 2491
Try declaring the log variable outside out your method that way:
private static readonly ILog log = LogManager.GetLogger(typeof(LogToFile));
That's the way I use it and I have to problem. However, in my case, I don't log in a static class.
Also, I have my appender information is in a file that I specify in the XmlConfigurator.Configure() function.
log4net.Config.XmlConfigurator.Configure(new FileInfo(configFile));
Upvotes: 1