【问题标题】:My Custom Log4net Asynch Failover Appender Skips Messages我的自定义 Log4net 异步故障转移附加程序跳过消息
【发布时间】:2016-05-21 03:21:19
【问题描述】:

我正在尝试为Log4net 编写异步Failover Appender。我快到了,但有一些小问题。

appender 需要尝试登录到我们的内部 Web 服务,如果失败,则写入文件。

  • Web 服务运行良好...每一次。
  • 故障转移到文件会丢失消息

这是我需要帮助的地方...

症状:

  • 我的测试控制台应用程序显示所有消息(请参阅下面的附图
  • 但是当故障转移激活时,部分或许多消息不会附加到文件中

我的 APPENDER 代码如下所示:
最终,我将动态解析客户端,但现在......

namespace Testing.Appenders
{
    using log4net.Appender;
    using log4net.Core;
    using System;
    using System.IO;
    using System.ServiceModel;
    using System.Threading.Tasks;
    using wsEventManager;

    public class AsynchWebServiceFailoverAppender : AppenderSkeleton
    {
        #region <Properties>

        public string ServiceUrl { get; set; }

        public string File { get; set; }

        #endregion

        #region <Methods>

        #region protected

        protected override void Append(LoggingEvent loggingEvent)
        {
            if (loggingEvent == null)
                throw new ArgumentNullException("LoggingEvent");

            if (string.IsNullOrEmpty(File))
                throw new ArgumentNullException("File");

            if (string.IsNullOrEmpty(ServiceUrl))
                throw new ArgumentNullException("ServiceUrl");

            Task.Factory.StartNew(() =>
            {
                var uri = new Uri(ServiceUrl);
                var myBinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
                var endpoint = new EndpointAddress(uri);
                var client = new EventManagerSoapClient(myBinding, endpoint);

                var eventType = GetEventType(loggingEvent);
                var log = GetEvent(eventType);

                client.Log(log);
                client.Close();
                client = null;
            }) 
            .ContinueWith(task => 
            {    
                using (var streamWriter = new StreamWriter(File, true))
                {
                    using (var textWriter = TextWriter.Synchronized(streamWriter))
                    {
                        textWriter.WriteLine(base.RenderLoggingEvent(loggingEvent));
                        textWriter.FlushAsync();
                    }
                }
            }, TaskContinuationOptions.OnlyOnFaulted);
        }

        #endregion

        #endregion
    }
}

我的配置有效,但在这里:

<?xml version="1.0"?>
<configuration>

  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>

  <log4net>
    <appender name="WebServiceFailoverAppender" type="Testing.Appenders.AsynchWebServiceFailoverAppender , Testing">
      <ServiceUrl value="http://localhost/DiagnosticsWeb/BadUrl.asmx" />
      <file value="C:\Logs\Support\Diagnostics.Appender\log4net.log" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="&lt;%level date=&quot;%date{MM-dd-yyyy}&quot; time=&quot;%date{h:mm:ss tt}&quot; file=&quot;%class&quot; thread=&quot;%thread&quot;&gt;%message&lt;/%level&gt;%newline" />
      </layout>
    </appender>
    <root>
      <level value="ALL" />
      <appender-ref ref="WebServiceFailoverAppender" />
    </root>
  </log4net>

</configuration>

结果:

  • 5 条消息发送到控制台进行日志记录
  • 仅记录 2 条消息

【问题讨论】:

  • 当您写入文件时,您很可能遇到了竞态条件。您的 TextWriter.Synchronized 无效,因为您每次都创建新的作家。验证尝试锁定整个文件写入块。
  • 为什么会被否决?这是一个合法的问题
  • 不知道,只知道那不是我。锁定文件编写代码有帮助吗?
  • @Evk 是的……它奏效了。我不值得 :-) 添加你的答案!!

标签: c# asynchronous log4net


【解决方案1】:

当你写入文件时你有竞争条件。您的TextWriter.Synchronized 无效,因为您每次都创建新的写入器,并且创建此构造是为了将写入同步到TextWriter 的单个实例。要验证尝试锁定整个文件写入块。如果您想以即发即弃的异步方式从多个线程写入单个日志文件 - 请参阅我的其他答案 here

【讨论】:

    【解决方案2】:

    如果您正在使用asynchronous 呼叫,您应该等待它们,否则,当您离开scope 时,它可能不会完成。 我的猜测是,flush 确实会对您所遇到的这种竞争状况产生任何影响。

    要解决此问题,您应该为await 提供flush。在您的task 续篇中,我将介绍await async 架构:

    ContinueWith(async task => 
    {    
        using (var streamWriter = new StreamWriter(File, true))
        {
           using (var textWriter = TextWriter.Synchronized(streamWriter))
           {
               textWriter.WriteLine(base.RenderLoggingEvent(loggingEvent));
               await textWriter.FlushAsync();
            }
         }
    }, TaskContinuationOptions.OnlyOnFaulted);
    

    让我知道这是否有效。

    【讨论】:

      猜你喜欢
      • 2014-05-29
      • 2015-01-03
      • 2020-01-30
      • 2019-09-02
      • 1970-01-01
      • 1970-01-01
      • 2022-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多