丰富的Serlilogs,每个吊火作业都具有独特的价值 [英] Enrich Serlilogs with unique value per hangfire job
问题描述
我正在使用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屋!