【问题标题】:Log4Net Custom AdoNetAppender Buffer IssueLog4Net 自定义 AdoNetAppender 缓冲区问题
【发布时间】:2011-05-04 13:25:26
【问题描述】:

我正在使用log4net,并且我从AdoNetAppender 创建了自己的附加程序。我的 appender 只是实现了一种缓冲区,它允许在一个日志中对相同的事件进行分组(对于数千个相同的错误,我将在数据库中只有一行)。

这是便于理解的代码(我的 appender 有一个 buffersize = 1):

class CustomAdoNetAppender : AdoNetAppender
{
    //My Custom Buffer
    private static List<LoggingEvent> unSendEvents = new List<LoggingEvent>();
    private int customBufferSize = 5;
    private double interval = 100;
    private static DateTime lastSendTime = DateTime.Now;

    protected override void SendBuffer(log4net.Core.LoggingEvent[] events)
    {
        LoggingEvent loggingEvent = events[0];
        LoggingEvent l = unSendEvents.Find(delegate(LoggingEvent logg) { return GetKey(logg).Equals(GetKey(loggingEvent), StringComparison.OrdinalIgnoreCase); });
        //If the events already exist in the custom buffer (unSendEvents) containing the 5 last events
        if (l != null)
        {
            //Iterate the count property
            try
            {
                l.Properties["Count"] = (int)l.Properties["Count"] + 1;
            }
            catch
            {
                l.Properties["Count"] = 1;
            }
        }

        //Else
        else
        {
            //If the custom buffer (unSendEvents) contains 5 events
            if (unSendEvents.Count() == customBufferSize)
            {
                //Persist the older event
                base.SendBuffer(new LoggingEvent[] { unSendEvents.ElementAt(0) });
                //Delete it from the buffer
                unSendEvents.RemoveAt(0);
            }
            //Set count properties to 1
            loggingEvent.Properties["Count"] = 1;
            //Add the event to the pre-buffer 
            unSendEvents.Add(loggingEvent);
        }

        //If timer is over
        TimeSpan timeElapsed = loggingEvent.TimeStamp - lastSendTime;
        if (timeElapsed.TotalSeconds > interval)
        {
            //Persist all events contained in the unSendEvents buffer
            base.SendBuffer(unSendEvents.ToArray());
            //Update send time
            lastSendTime = unSendEvents.ElementAt(unSendEvents.Count() - 1).TimeStamp;
            //Flush the buffer
            unSendEvents.Clear();
        }
    }

    /// <summary>
    /// Function to build a key (aggregation of important properties of a logging event) to facilitate comparison.
    /// </summary>
    /// <param name="logg">The loggign event to get the key.</param>
    /// <returns>Formatted string representing the log event key.</returns>
    private string GetKey(LoggingEvent logg)
    {
        return string.Format("{0}|{1}|{2}|{3}", logg.Properties["ErrorCode"] == null ? string.Empty : logg.Properties["ErrorCode"].ToString()
                                , logg.Level.ToString()
                                , logg.LoggerName
                                , logg.MessageObject.ToString()
                                );
    }
}

缓冲区和计数部分进展顺利。我的问题是我丢失了最后 5 个日志,因为在程序结束时缓冲区没有被刷新。 unSendEvent 缓冲区已满,但从未在数据库中刷新,因为不再有新日志将“推送”到 db 旧日志中。

我有什么解决办法吗?我曾尝试使用 Flush() 方法,但没有成功。

【问题讨论】:

  • 我没有这个麻烦,虽然我在很多情况下使用 ado net appender 进行缓冲:MVC 站点、web api、webform 站点和 NT 服务。我能够重现它的唯一方法是终止进程。也许您应该检查您的应用程序是如何终止的。并详细说明它是什么类型的应用程序。 (但也许你的麻烦自 2011 年以来就消失了^^。)

标签: c# log4net


【解决方案1】:

Smtp appender 有一个有损参数。如果它未设置为 false,则不能保证您获得所有日志消息。听起来这可能是你的问题?我使用了一个配置文件,所以这一行在我的 appender 定义中。

<lossy value="false" />

【讨论】:

  • 我使用的是 adonetappender,而不是 smtp,但是是的,我将有损值设置为 false。也许是因为我的 LoggingEvent 列表没有被检测为缓冲区?
  • @Xavier 是否解决了您的问题?
  • 还没有。是否可以访问 AdoNetAppender 缓冲区中的事件?
【解决方案2】:

我可以想到几种方法来处理这个问题。第一个是将缓冲区大小更改为 1(现在为 5)。这将确保所有条目都被立即写入。但是,这可能并不理想。如果是这种情况,我能想到的一种解决方法是将五个虚拟日志消息放入缓冲区。这将清除真实事件,而您的虚拟事件将被丢弃。

【讨论】:

  • 我的缓冲区大小实际上是 1。问题就在这里,因为我自己管理缓冲。记录5个假事件的问题是应用程序没有“真正的终点”
  • 嗯。我以前从未手动管理过缓冲区。听起来缓冲区仍然没有调整为只有 1。在顶部,您将缓冲区设置为 5(私有 int bufferSize = 5;)。会不会是在那之后没有调整到1?
  • 我的 appender 的缓冲区大小等于 1。我手动管理大小为 5 的缓冲区(为了更清楚,私有 int bufferSize = 5 现在是 manualBufferSize = 5)。我现在的问题是:是否可以访问 CustomAdoNetAppender 的缓冲区并修改 events 属性?这个想法是访问附加程序的缓冲区(不再是我的自定义缓冲区)并检查缓冲区中的事件,并以我想要的方式修改属性“计数”。有了这个,也许 log4net 会在最后成功刷新缓冲区?
猜你喜欢
  • 1970-01-01
  • 2012-11-23
  • 2014-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
相关资源
最近更新 更多