自定义AdoNetAppender缓冲区问题

本文关键字:问题 缓冲区 AdoNetAppender 自定义 | 更新日期: 2023-09-27 17:54:55

我使用log4net,我已经从AdoNetAppender创建了我自己的appender。我的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()方法,但没有成功。

自定义AdoNetAppender缓冲区问题

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

<lossy value="false" />

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