丰富的Serlilogs,每个吊火作业都具有独特的价值 [英] Enrich Serlilogs with unique value per hangfire job

查看:83
本文介绍了丰富的Serlilogs,每个吊火作业都具有独特的价值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Hangfire for background jobs, and Serilog for logging. I'm trying to enrich my serilogs with a TrackingId so that all logs from a specific Hangfire job will have the same TrackingId that I can filter on.

我在 Startup.cs 中配置Serilog:

I configure Serilog like this in Startup.cs:

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 .有什么办法可以实现?

But doing like this will not set a separate TrackingId per Hangfire job. Is there any way I can achieve that?

推荐答案

对于它的价值,我最终使用下面显示的服务器/客户端过滤器和 GlobalJobFilters 注册将其提取出来.我遇到的一个烦人的问题是,默认情况下将 AutomaticRetryAttribute 添加到 GlobalJobFilters 集合中,并且该类

For what it's worth, I ended up pulling this off using the server/client filter and GlobalJobFilters registration shown below. One annoying issue I ran into is that the AutomaticRetryAttribute is added by default to the GlobalJobFilters collection, and that class will log errors for failed jobs without knowledge of the Serilog LogContext created in our custom JobLoggerAttribute. Personally, I know I will only allow manual retry, so I just removed that attribute and handled the error within the IServerFilter.OnPerformed method. Check the end of my post to see how to remove it if that works for you.

如果要允许自动重试,则需要:1)创建一个装饰 AutomaticRetryAttribute 的自定义属性,并使它知道自定义LogContext,2)再次删除默认属性 GlobalJobFilters 集合中的 AutomaticRetryAttribute ,并3)将您的decorator属性添加到该集合中.

If you are going to allow automatic retry, then you will need to: 1) create a custom attribute that decorates the AutomaticRetryAttribute and makes it aware of a custom LogContext, 2) again remove the default AutomaticRetryAttribute from the GlobalJobFilters collection, and 3) add your decorator attribute to the collection.

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

这篇关于丰富的Serlilogs,每个吊火作业都具有独特的价值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆