我们有一个Windows服务启动另一个名为ClusterProcess的进程。 我想从Windows服务和ClusterProcess获取日志,我希望这些日志转到数据库和文件。例如,如果数据库不可访问,我希望能够在文件中看到日志。
我有一个Log4Net设置的外部配置文件。有两个RollingFileAppender和两个AdoNetAppender。 有一个默认的根记录器和一个名为ClusterProcessLogger的附加记录器。
这个想法是Windows服务使用根记录器并记录到其中一个AdoNetAppenders和一个RollingFileAppender,并且ClusterProcess使用ClusterProcessLogger并记录到另一个AdoNetAppender和另一个RollingFileAppender。
两个案例的AdoNetAppenders都运行良好。 RollingFileAppenders没有。
所以这是log4net配置的外部配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<log4net debug="true">
<appender name="RollingFileAppender"
type="log4net.Appender.RollingFileAppender">
<file value="C:\Program Files\Sym\Logging\CalcEngineLog.txt"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="5"/>
<maximumFileSize value="10MB"/>
<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="SpecialRollingFileAppender"
type="log4net.Appender.RollingFileAppender">
<file value="C:\Program Files\Sym\Logging\SpecialCalcEngineLog.txt"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="5"/>
<maximumFileSize value="10MB"/>
<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="Error" />-->
<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>
<appender name="ClusterProcessAdoNetAppender"
type="log4net.Appender.AdoNetAppender">
<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 [ClusterProcess Calculation Engine Log]
([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date,
@thread, @log_level, @logger, @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="@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>
<logger name="ClusterProcessLogger" additivity="false">
<level value="Debug" />
<appender-ref ref="ClusterProcessAdoNetAppender" />
<appender-ref ref="SpecialRollingFileAppender" />
</logger>
<root>
<level value="Debug"/>
<appender-ref ref="AdoNetAppender"/>
<appender-ref ref="RollingFileAppender"/>
</root>
</log4net>
以下是Windows服务的主要方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Globalization;
using Sym.Core.Culture;
using System.Threading;
namespace Sym.WindowsService
{
static class Program
{
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\\Sym\\bin\\Log4NetSettingsGlobal.xml"));
}
log.Debug("Culture info before change: " + Thread.CurrentThread.CurrentCulture.Name);
...
}
}
}
以下是Windows服务的App.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="ConfigPath" value="C:\Program Files\Sym\Configs\Example.config"/>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add
name="textWriterTraceListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="C:\Program Files\Sym\Logging\Log4Net_Trace_WindowsServer.txt" />
</listeners>
</trace>
</system.diagnostics>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
对于ClusterProcess项目,这是Main方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sym.Core.Config;
using Sym.Clustering.Framework;
using System.Diagnostics;
using Sym.Core.Services;
using System.Reflection;
using System.IO;
using log4net.Repository.Hierarchy;
using log4net;
using log4net.Appender;
using System.Configuration;
using System.Collections.Specialized;
using Sym.Core.Log4Net;
using log4net.Config;
namespace Sym.Clustering.ClusterProcess
{
class Program
{
private static ClusterProcessor _ClusterProcessor ;
private static SelectedConfiguration _Config;
private static readonly log4net.ILog log = log4net.LogManager.GetLogger("ClusterProcessLogger");
static void Main(string[] args)
{
try
{
...
try
{
log4net.Config.XmlConfigurator.Configure();
if (!log4net.LogManager.GetRepository().Configured)
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo("C:\\Program Files\\Sym\\bin\\Log4NetSettingsGlobal.xml"));
}
Log4NetConfiguration.ConfigureLog4Net(_Config); // Load connection strings
}
catch (Exception e)
{
Console.WriteLine(e);
}
log.Debug("ClusterProcess using DatabaseName: " + config.Database.DatabaseName);
...
}
catch(Exception exp)
{
log.Error(exp.Message, exp);
}
}
}
}
这是ClusterProcess项目的App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add
name="textWriterTraceListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="C:\Program Files\Sym\Logging\Log4Net_Trace_ClusterProcess.txt" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
在ClusterProcess的log4net跟踪中,给出了以下错误:
log4net:ERROR无法在应用程序的.config文件中找到配置节'log4net'。检查.config文件中的
<log4net>
和<configSections>
元素。配置部分应如下所示:
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
log4net:ERROR [RollingFileAppender] ErrorCode:GenericFailure。无法获取文件C:\ Program Files \ Sym \ Logging \ SpecialCalcEngineLog.txt上的锁定。该进程无法访问文件'C:\ Program Files \ Sym \ Logging \ SpecialCalcEngineLog.txt',因为它正由另一个进程使用。
log4net:ERROR [RollingFileAppender] ErrorCode:GenericFailure。无法获取文件C:\ Program Files \ Sym \ Logging \ CalcEngineLog.txt上的锁定。该进程无法访问文件'C:\ Program Files \ Sym \ Logging \ CalcEngineLog.txt',因为它正由另一个进程使用。
我不知道如何处理第一个错误。 第二个和第三个错误不应该存在。 ClusterProcess应该能够访问SpecialCalcEngineLog.txt,它不应该被CalcEngineLog.txt打扰,因为那是Windows服务正在使用的RollingFileAppender。
如何解决这些错误?我在俯瞰什么?
答案 0 :(得分:0)
添加
可以缓解第一个错误No Tests were found
的某个地方。
多个RollingFileAppenders无法写入同一文件。但是,您可以区分,例如,将进程ID添加到文件名(然后从所有进程收集日志):
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
</configSections>