log4net 在作为网络服务运行时以静默方式失败
本文关键字:静默 方式 失败 运行时 网络服务 log4net | 更新日期: 2023-09-27 18:32:11
我有一个启动控制台应用程序的 Web 服务。 控制台应用程序包含 Log4net。
来自控制台应用的代码:
log4net.Config.XmlConfigurator.Configure();
ILog log = log4net.LogManager.GetLogger(typeof(Program));
我遇到的问题是,当它以network services
运行时,不会创建log4net日志文件。 应用程序不会失败,它只是在没有日志记录的情况下继续运行。
我需要找到一种方法来检测这一点并使应用程序失败,如果没有日志文件,我们就无法继续。 我需要通知用户他们需要修复权限,以便网络服务可以创建文件。
如何检测此无法创建文件? 我能够提出的唯一解决方案是检查该文件是否存在于应用程序顶部,以及它是否不是为了停止而创建的。 这对我来说就像一个黑客,Log4net应该能够告诉我它无法创建文件。
更新:
我正在测试以下内容。 我目前的测试方法是将文件设置为仅在第一次创建后读取,然后它无权写入它。 此时它应该失败,因为它无法写入日志文件。
string logFile = @"D:'TaskDev'Log4NetTesting'Log4NetTesting'bin'Debug'Test'Log4netTesting.Log";
log4net.GlobalContext.Properties["LogFileName"] = logFile;
log4net.Config.XmlConfigurator.Configure();
log4net.NDC.Push("Test Application");
ILog log = log4net.LogManager.GetLogger(typeof(Program));
var m = LogManager.GetAllRepositories().SelectMany(repository => repository.GetAppenders()).OfType<FileAppender>();
try
{
log.Info("hello Log test");
}
catch (Exception ex) {
Console.WriteLine("Log write failed: " + ex.Message);
}
Console.WriteLine("Done");
Console.ReadLine();
应用配置
版 <configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<errorHandler type="Log4NetTesting.util.CustomLogErrorHandler" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
</layout>
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="%property{LogFileName}" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="250KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
您是否考虑过为 FileAppender 设置错误处理程序?
您可以使用以下代码获取配置文件中设置的 FileAppender:
var fileAppenders = LogManager.GetAllRepositories().SelectMany(repository => repository.GetAppenders()).OfType<FileAppender>();
foreach (var fileAppender in fileAppenders) {
fileAppender.ErrorHandler = new MyErrorHandler();
}
其中 MyErrorHandler 类有点像这样:
class MyErrorHandler : IErrorHandler {
public void Error(string messages) {
// giver error message and abort
}
public void Error(string messages, Exception exception) {
// giver error message and abort
}
public void Error(string messages, Exception exception, ErrorCode errorCode) {
// giver error message and abort
}
}
我不确定"给予者错误消息和中止"像往常一样简单,您在服务中没有 GUI 访问权限
FileAppender 成员如下所示:http://logging.apache.org/log4net/release/sdk/html/AllMembers_T_log4net_Appender_FileAppender.htmIErrorHandler 成员在这里:http://logging.apache.org/log4net/release/sdk/html/AllMembers_T_log4net_Core_IErrorHandler.htm
您可能还想在 repository.ConfigurationChanged
注册活动
有了詹斯的一些提示,我能够做到这一点。
app.config - 添加了此行
<errorHandler type="Log4NetTesting.util.CustomLogErrorHandler" />
自定义日志错误处理程序
public class LogException : Exception
{
private readonly ErrorCode errorCode;
/// <summary>Gets the service name which related to this exception.</summary>
public ErrorCode ErrorCode
{
get { return errorCode; }
}
public LogException()
{
}
public LogException(string message)
: base(message)
{
}
public LogException(string message, Exception inner)
: base(message, inner)
{
}
public LogException(string message, Exception inner, ErrorCode errorCode)
: base(message, inner)
{
this.errorCode = errorCode;
}
}
public class CustomLogErrorHandler : IErrorHandler
{
public string message { get;private set; }
public Exception Exception { get; private set; }
public ErrorCode ErrorCode { get; private set; }
#region IErrorHandler Members
public void Error(string message)
{
this.message = message;
}
public void Error(string message, Exception e)
{
this.message = message;
this.Exception = e;
}
public void Error(string message, Exception e, ErrorCode errorCode)
{
this.message = message;
this.Exception = e;
this.ErrorCode = errorCode;
}
#endregion
}
测试它
try
{
string logFile = @"D:'TaskDev'Log4NetTesting'Log4NetTesting'bin'Debug'Test'Log4netTesting.Log";
log4net.GlobalContext.Properties["LogFileName"] = logFile;
log4net.Config.XmlConfigurator.Configure();
log4net.NDC.Push("Test Application");
ILog log = log4net.LogManager.GetLogger(typeof(Program));
var fileAppenders = LogManager.GetAllRepositories().SelectMany(repository => repository.GetAppenders()).OfType<FileAppender>();
var customLogErrorHandler = new CustomLogErrorHandler(); // custom error IErrorHandler.
// loop though fileappenders adding the error handler
foreach (var fileAppender in fileAppenders)
{
fileAppender.ErrorHandler = customLogErrorHandler;
}
log.Info("hello Log file");
if (customLogErrorHandler.message != null) // if there is an error throw exception
{
throw new LogException(customLogErrorHandler.message, customLogErrorHandler.Exception, customLogErrorHandler.ErrorCode);
}
}
catch (LogException lex) {
// catch log exception
Console.WriteLine(lex.ErrorCode);
Console.WriteLine(lex.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
虽然我知道默默失败对某些人来说可能是件好事。 对于我的应用程序,如果我没有日志文件,并且 Log4Net 无法告诉我它有问题,我们的用户无法知道存在问题。
您可以执行以下操作来验证配置是否有效:
if(!LogManager.GetRepository().Configured)
{
XmlConfigurator.Configure();
}
if (!LogManager.GetRepository().Configured)
{
var logMsg = new StringBuilder();
logMsg.AppendLine("Failed to initialize log4net");
foreach(var msg in LogManager.GetRepository().ConfigurationMessages)
{
logMsg.AppendLine(msg.ToString());
}
// ....do something with the message, raise
// an evt to UI, log to OS Event logger, etc....
}