2017-10-16 19 views
3

백그라운드 작업에는 Hangfire를 사용하고 로깅에는 Serilog를 사용하고 있습니다. 내 Serilogs를 TrackingId으로 풍부하게 만들려고 특정 Hangfire 작업의 모든 로그에 필터링 할 수있는 동일한 TrackingId을 갖도록합니다.벽화 작업 당 고유 값으로 Serlilogs를 보완하십시오.

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(); 

을 그리고는 다음과 같이 작업을 대기열 :

나는 Startup.cs이 같은 Serilog을 구성

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

그러나이 같은 일을하는 Hangfire 작업마다 별도의 TrackingId을 설정하지 않습니다. 내가 성취 할 수있는 방법이 있습니까?

+0

은 내가 Hangfire의 API를 살펴 했어 제거하고 할 수있는 방법을 찾을 수 없습니다 이것을 쉽게하십시오; "서버 필터"를 추가하는 것이 효과가있는 것처럼 보입니다. HTH. –

답변

0

가치가있는 부분에 대해서는 아래에 표시된 서버/클라이언트 필터와 GlobalJobFilters 등록을 사용하여이 문제를 해결했습니다. 하나의 성가신 문제는 AutomaticRetryAttribute이 기본적으로 GlobalJobFilters 컬렉션에 추가되었으며 해당 클래스 will log errors for failed jobs은 사용자 정의 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 필드는 작업자 스레드에서 공유됩니다. –