我的自定义Log4net Asynch故障转移Appender跳过邮件

时间:2016-05-20 18:01:04

标签: c# asynchronous log4net

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

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

  • Web服务每次都很有效。
  • 故障转移到文件中会丢失消息

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

症状:

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

我的附录代码看起来像:
最终,我将动态解析客户端,但现在......

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条消息

5 Messages are sent to the console for logging Only 2 messages get logged

2 个答案:

答案 0 :(得分:1)

如果您正在使用// get the webpage source -- depends on allow_url_fopen // see the previously mentioned stack overflow answer for alternates $externalWebpage = file_get_contents('http://yoursite.com/your-page.html'); // split the webpage by </head> $websiteSections = explode($externalWebpage, '</head>',); // don't neglect to add the '</head>' back if you want to use that // portion somewhere else $head = $websiteSections[0] . '</head>'; $body = $websiteSections[1]; 电话,则应等待他们,否则,当您离开asynchronous时可能无法完成。 我的猜测是scope确实会对你所处的竞争条件产生任何影响。

要解决此问题,flush应该await。在flush延续中,我将介绍task架构:

await async

如果有效,请告诉我。

答案 1 :(得分:1)

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