我前一段时间使用log4net设置日志记录,只是没有想到特定的情况。
目前,我有一个全局配置文件。有一个RollingFileAppender和一个AdonetAppender。
当程序的一个实例仅在数据库上运行时,则一切正常。 有时,两个稍有不同的实例可能会在同一数据库上运行。附加程序记录来自两个实例的消息,但是通常(在公共代码中)无法分辨消息是从哪个实例发出的。当然,我可以将实例名称添加到消息中或其他内容,但这似乎是不得已的方法。
我的大脑就像雾。我认为解决方案应该很简单,但是我想不出什么是最好的。
我可以创建另一个追加程序,并在运行时根据实例名称使用哪个追加程序“切换”吗?
这是配置文件:
<?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>
这是在启动项目中的配置方式:
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"));
}
...
}
其他信息
在生产中,将启动Windows服务,这将检查必须在群集上运行其实例的配置文件。
每个实例都有一个单独的过程:
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));
}
我假设我可以将appIdentifier(根据评论)添加到Arguments
的{{1}}中?
答案 0 :(得分:2)
首先确定2个应用程序实例。
最简单的方法是使用唯一的命令行参数启动每个应用程序实例。
通过例如启动第一个实例。 .cmd
文件为MyApplication.exe instance1
,第二个文件为MyApplication.exe instance2
。
从方法args
的{{1}}参数中读取此参数值。
Main
现在您有多种选择。
将static void Main(String[] args)
{
String appIdentifier = args[0];
// ...
}
分配给appIdentifier
。
使用范围取决于您的情况,请参见the Log4net documentation。
Log4net context property
RollingFileAppender
通过log4net.GlobalContext.Properties["appIdentifier"] = appIdentifier;
将此上下文属性包括在layout
的{{1}}中。
现在,每个记录的行将包含相应的RollingFileAppender
值'instance1'或'instance2'。
%property{appIdentifier}
AdoNetAppender
首先请确保您要登录的表包含用于存储appIdentifier
值的列,
例如。列<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="... %property{appIdentifier} ..."/>
</layout>
。
使用额外的参数扩展appIdentifier
的配置以匹配appIdentifier VARCHAR(25)
属性。
AdoNetAppender
用相应的列名和参数扩展appIdentifier
语句。
<parameter>
<parameterName value="@appIdentifier"/>
<dbType value="String" />
<size value="25" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{appIdentifier}" />
</layout>
</parameter>
这不是选项1,而是选项。
通过将文件名与SQL INSERT
命令行参数进行匹配,为每个实例创建一个单独的INSERT INTO [Calculation Engine Log] ([Date],[Thread],[Level],[Logger],[Location],[Message],[Exception],[appIdentifier])
VALUES (@log_date, @thread, @log_level, @logger, @location, @message, @exception, @appIdentifier)
配置文件。
xml
RollingFileAppender
为每个实例配置一个单独的输出文件路径。
例如1
appIdentifier
例如2
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo("C:\\Program Files\\Symplexity\\bin\\" + appIdentifier + '.xml'));
AdoNetAppender
有关如何设置列以存储<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
...
<file value="D:\Medupi logs\Instance1.txt"/>
...
</appender>
的信息,请参阅选项1。
在<file value="D:\Medupi logs\Instance2.txt"/>
语句中包含一个常量值作为标识符。
appIdentifier
在实例2的SQL INSERT
配置文件中执行相同的操作,值为'Instance2'。
如果您在整个应用程序中仅使用一个INSERT INTO [Calculation Engine Log] ([Date],[Thread],[Level],[Logger],[Location],[Message],[Exception],[appIdentifier])
VALUES (@log_date, @thread, @log_level, @logger, @location, @message, @exception, 'Instance1')
实例,请使用xml
的值按名称检索它。
ILog
的{{1}}和appIdentifier
标记的%logger
标记将分别包含值'Instance1'或'Instance2'。
我不喜欢使用单个记录器,但是我经常看到这种做法。
RollingFileAppender
这是 @logger
的替代选项,仅将其与上述 AdoNetAppender
的选项之一结合使用。
按照选项1中的说明设置private static log4net.ILog log;
static void Main(String args)
{
String appIdentifier = args[0];
if (!log4net.LogManager.GetRepository().Configured)
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo("C:\\Program Files\\Symplexity\\bin\\Log4NetSettingsGlobal.xml"));
log = log4net.LogManager.GetLogger(appIdentifier);
}
// ...
}
。
可以在RollingFileAppender
的输出文件的路径中包含这样的AdoNetAppender
。
这样做将分别生成文件“ Instance1.log”或“ Instance2.log”。
(除了更改文件名之外,您还可以将其应用于(子)文件夹名称。)
如果您遇到或担心锁定和/或性能问题,最好不要在同时运行的多个pepe应用程序实例之间共享相同的输出文件。 < / p>
Log4net context property