[英]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.