AutomaticRetryAttribute

AutomaticRetryAttribute

我正在使用Hangfire进行后台作业,并使用Serilog进行日志记录。我正在尝试使用TrackingId丰富我的serilog,以便来自特定Hangfire作业的所有日志都具有可以过滤的相同TrackingId

我在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));

但是,这样做不会为每个Hangfire作业设置单独的TrackingId。有什么办法可以实现?

最佳答案

对于它的值(value),我最终使用下面显示的服务器/客户端过滤器和GlobalJobFilters注册实现了这一点。我遇到的一个烦人的问题是,默认情况下将AutomaticRetryAttribute添加到GlobalJobFilters集合中,而类will log errors for failed jobs却不知道在我们的自定义JobLoggerAttribute中创建的Serilog LogContext。就个人而言,我知道我将只允许手动重试,因此我只是删除了该属性并在IServerFilter.OnPerformed方法中处理了错误。查看我的帖子末尾,看看如何删除它(如果适合您的话)。

如果要允许自动重试,那么您将需要:1)创建一个装饰AutomaticRetryAttribute并使其了解自定义LogContext的自定义属性,2)再次从AutomaticRetryAttribute集合中删除默认的GlobalJobFilters,以及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);

10-08 04:35