簡體   English   中英

log4net實現細節-自定義追加程序

[英]log4net implementation detail - custom appender

我已經實現了一個自定義的log4net附加器,該附加器可以寫入http服務……效果很好,但是我腦子里有些過早的優化。 具體來說,是否有更好的方法? 我想我可以確保只有關鍵類才具有該特定的委托人,但即使使用保守的日志記錄選項,也感覺可能會有很多附加程序和責任。

有沒有人想分享經驗? 我看過http://geekswithblogs.net/michaelstephenson/archive/2014/01/02/155044.aspx ,這實際上是我在做的...(請參閱代碼)這種比例的效果如何? 我喜歡單例的工廠...如何實現並發隊列來緩沖寫操作呢?

希望管理員不會因為問一個(可能的意見)最佳實踐問題而被管理員打得太厲害。

(在文章中添加代碼以進行澄清)

    public class ServiceBusAppender : AppenderSkeleton
{
    public string ConnectionStringKey { get; set; }
    public string MessagingEntity { get; set; }
    public string ApplicationName { get; set; }
    public string EventType { get; set; }
    public bool Synchronous { get; set; }
    public string CorrelationIdPropertyName { get; set; }

    protected override void Append(log4net.Core.LoggingEvent loggingEvent)
    {
        var myLogEvent = new AzureLoggingEvent(loggingEvent);
        myLogEvent.ApplicationName = ApplicationName;
        myLogEvent.EventType = EventType;
        myLogEvent.CorrelationId = loggingEvent.LookupProperty(CorrelationIdPropertyName) as string;

        if (Synchronous)
            AppendInternal(myLogEvent, 0);
        else
        {
            Task.Run(() => AppendInternal(myLogEvent, 0));
        }            
    }

    protected void AppendInternal(AzureLoggingEvent myLogEvent, int attemptNo)
    {
        try
        {                
            //Convert event to JSON
            var stream = new MemoryStream();
            var json = Newtonsoft.Json.JsonConvert.SerializeObject(myLogEvent);
            var writer = new StreamWriter(stream);
            writer.Write(json);
            writer.Flush();
            stream.Seek(0, SeekOrigin.Begin);

            //Setup service bus message
            var message = new BrokeredMessage(stream, true);
            message.ContentType = "application/json";
            message.Label = myLogEvent.MessageType;                
            message.Properties.Add(new KeyValuePair<string, object>("ApplicationName", myLogEvent.ApplicationName));
            message.Properties.Add(new KeyValuePair<string, object>("UserName", myLogEvent.UserName));
            message.Properties.Add(new KeyValuePair<string, object>("MachineName", myLogEvent.MachineName));
            message.Properties.Add(new KeyValuePair<string, object>("MessageType", myLogEvent.MessageType));
            message.Properties.Add(new KeyValuePair<string, object>("Level", myLogEvent.Level));
            message.Properties.Add(new KeyValuePair<string, object>("EventType", myLogEvent.EventType));

            //Setup Service Bus Connection
            var connection = ConfigurationManager.ConnectionStrings[ConnectionStringKey];
            if (connection == null || string.IsNullOrEmpty(connection.ConnectionString))
            {
                ErrorHandler.Error("Cant publish the error, the connection string does not exist");
                return;
            }                
            var factory = MessagingFactoryManager.Instance.GetMessagingFactory(connection.ConnectionString);
            var sender = factory.CreateMessageSender(MessagingEntity);                

            //Publish
            sender.Send(message);                
        }
        catch (Exception ex)
        {
            if (ex.Message.Contains("The operation cannot be performed because the entity has been closed or aborted"))
            {
                if (attemptNo < 3)
                    AppendInternal(myLogEvent, attemptNo++);
                else
                    ErrorHandler.Error("Error occured while publishing error", ex);                    
            }
            else                
                ErrorHandler.Error("Error occured while publishing error", ex);                
        }
    }

    protected override void Append(log4net.Core.LoggingEvent[] loggingEvents)
    {
        foreach(var loggingEvent in loggingEvents)
        {
            Append(loggingEvent);
        }
    }        

謝謝,

克里斯

過早優化的方法是先進行測試和測量,然后再次進行測試和測量。 編寫一個集成測試以記錄到一千個記錄器中,然后看看如何進行。

如果那確實顯示出問題,那么與其實現自己的隊列,不如從BufferingAppenderSkeleton繼承:

追加程序應使用此基類,這些追加程序需要在記錄事件之前先緩沖多個事件。 例如,AdoNetAppender緩沖事件,然后一次性將緩沖區的所有內容提交給基礎數據庫。

子類應重寫SendBuffer方法以傳遞緩沖的事件。

BufferingAppenderSkeleton維護事件的固定大小的循環緩沖區。 使用BufferSize屬性設置緩沖區的大小。

(順便說一句,log4net文檔的內容什么,每次查看時似乎都有更多的'½ï¿'字符?)

我看到您的代碼涉及JSON序列化。 如果您正在尋找log4net JSON,為什么要重做已經做的事情? 請參閱log4net.ext.json 我是開發商 Wiki涵蓋了如何啟動和運行它的第一步 它代替布局使用,因此可以插入采用布局的任何log4net附加程序中。

在項目的一部分中,我還為log4net創建了負載測試GUI。 它沒有發布,但應該可以從源代碼輕松編譯。 您可以使用它來發現不同配置如何根據您的條件進行擴展。

最后,如果性能優先,我建議您嘗試一下LOCALHOST UDP交付。 諸如nxlog或logstash之類的項目可以輕松地吞下它。 同樣,為什么要編寫新代碼?

讓我知道您是否需要澄清。 親切的問候和好運,羅布

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM