2017-10-16 105 views
3

我使用Hangfire作爲背景作業,Serilog作爲伐木作業。我試圖用TrackingId來豐富我的serilogs,以便來自特定Hangfire作業的所有日誌將具有相同的TrackingId,我可以過濾它們。豐富Serlilogs具有獨特價值的每個掛火工作

Startup.cs配置Serilog這樣的:

Log.Logger = new LoggerConfiguration() 
    .ReadFrom.Configuration(Configuration) 
    .WriteTo.Seq(serverUrl: serverUrl, apiKey: apiKey) 

    // Enrich the logs with a tracking id. Will be a new value per request 
    .Enrich.WithProperty("TrackingId", Guid.NewGuid()) 

    .CreateLogger(); 

我入隊的工作是這樣的:

BackgroundJob.Enqueue<MyService>(myService => myService.DoIt(someParameter)); 

但是做這樣不會將每遲髮型工作單獨TrackingId。有什麼辦法可以達到這個目標嗎?

+0

我有一個看看遲髮型API並不能找到一種方法,輕鬆做到這一點;添加一個「服務器過濾器」似乎可能工作。 HTH。 –

回答

0

對於什麼是值得的,我最終使用服務器/客戶端過濾器和GlobalJobFilters註冊如下所示。我碰到的一個令人討厭的問題是AutomaticRetryAttribute默認添加到GlobalJobFilters集合中,並且該類​​3210沒有在我們的定製JobLoggerAttribute中創建的Serilog LogContext的知識。就我個人而言,我知道我只會允許手動重試,所以我只是刪除了該屬性並處理了IServerFilter.OnPerformed方法中的錯誤。檢查我的帖子的結尾,看看如何刪除它,如果這對你有用。

如果你要允許自動重試,那麼你將需要:1)創建裝點AutomaticRetryAttribute並使其意識到定製LogContext的自定義屬性,2)再次從GlobalJobFilters集合中刪除默認AutomaticRetryAttribute, 3)將你的裝飾器屬性添加到集合中。

public class JobLoggerAttribute : JobFilterAttribute, IClientFilter, IServerFilter 
{ 
    private ILogger _log; 

    public void OnCreating(CreatingContext filterContext) 
    { 
     _log = GetLogger(); 

     _log.Information("Job is being created for {JobType} with arguments {JobArguments}", filterContext.Job.Type.Name, filterContext.Job.Args); 
    } 

    public void OnCreated(CreatedContext filterContext) 
    { 
     _log.Information("Job {JobId} has been created.", filterContext.BackgroundJob.Id); 
    } 

    public void OnPerforming(PerformingContext filterContext) 
    { 
     if (_log == null) 
      _log = GetLogger(); 

     _log.Information("Job {JobId} is performing.", filterContext.BackgroundJob.Id); 
    } 

    public void OnPerformed(PerformedContext filterContext) 
    { 
     _log.Information("Job {JobId} has performed.", filterContext.BackgroundJob.Id); 

     if (filterContext.Exception != null) 
     { 
      _log.Error(
       filterContext.Exception, 
       "Job {JobId} failed due to an exception.", 
       filterContext.BackgroundJob.Id); 
     } 

     _log = null; 
    } 

    private ILogger GetLogger() 
    { 
     return Log.ForContext(GetType()).ForContext("HangfireRequestId", Guid.NewGuid()); 
    } 
} 

和登記...

GlobalJobFilters.Filters.Add(new JobLoggerAttribute()); 

卸下AutomaticRetryAttribute ...

var automaticRetryFilter = GlobalJobFilters.Filters.Where(x => x.Instance is AutomaticRetryAttribute).Single(); 
GlobalJobFilters.Filters.Remove(automaticRetryFilter.Instance); 
+0

這實際上是線程安全的嗎? _log字段在工作線程中共享。 –