I set up logging with log4net a while back and just didn't think of a particular scenario.
At present I have a global config file. There is a RollingFileAppender and an AdonetAppender.
When only one instance of the program is running on the database then all is fine. Sometimes, two slightly different instances may be run on the same database. The appenders log the messages from both instances, but often (in the communal code) it is not possible to tell from which instance the message originated. Of course, I could add the instance name to the message or whatever, but it seems like a last resort.
My brain is like a fog. I think the solution should be rather simple, but I just can't think what would be best.
Could I create another appender, and "switch" during runtime which appender is being used based on the instance name?
Here is the config file:
<?xml version="1.0" encoding="utf-8" ?>
<log4net debug="true">
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<file value="D:\Medupi logs\CalcEngineLog.txt"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="2"/>
<maximumFileSize value="4MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger %location - %message%newline%exception"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG"/>
<levelMax value="FATAL"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
</appender>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<!-- <threshold value="Warn" /> -->
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="" />
<commandText value="INSERT INTO [Calculation Engine Log] ([Date],[Thread],[Level],[Logger],[Location],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @location, @message, @exception)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@location" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%location" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
<root>
<level value="Debug"/>
<appender-ref ref="AdoNetAppender"/>
<appender-ref ref="RollingFileAppender"/>
<appender-ref ref="DebugAppender"/>
</root>
</log4net>
This is how it is configured in the start-up project:
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
static void Main()
{
if (!log4net.LogManager.GetRepository().Configured)
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo("C:\\Program Files\\Symplexity\\bin\\Log4NetSettingsGlobal.xml"));
}
...
}
Additional information
In production, a Windows Service is started and this checks a config file for which instances must be run on a cluster.
The individual instances each have a separate process:
foreach (var cluster in clusters)
{
ProcessStartInfo startInfo = new ProcessStartInfo
{
CreateNoWindow = true,
FileName = processFileName,
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = string.Format("\"{0}\" \"{1}\"", cluster.Name, _ConfigPath)
};
_ClusterProcesses.Add(Process.Start(startInfo));
}
I assume I could add the appIdentifier (as per comments) to the Arguments
of the startInfo
?