.NET Core 5中如何借助Serilog自动记录Hangfire任务状态?
自动记录Hangfire任务状态的实现方案(.NET Core 5 + Serilog)
现成NuGet包说明
没有完全匹配你指定日志格式的现成包,但可以基于官方的Hangfire-Serilog集成包,配合自定义过滤器实现需求。需要引用的核心包:
Hangfire.Core&Hangfire.AspNetCore:Hangfire核心及ASP.NET Core集成Serilog.AspNetCore:Serilog的.NET Core集成Hangfire.Serilog(可选):让Hangfire自身的内部日志输出到Serilog
自定义过滤器实现(推荐)
通过实现Hangfire的过滤器接口,可以精准拦截任务生命周期的关键节点,输出你需要格式的日志。
1. 编写日志过滤器类
using Hangfire.Common; using Hangfire.Server; using Hangfire.States; using Serilog; using System.Linq; public class HangfireJobLoggingFilter : IServerFilter, IElectStateFilter { private readonly ILogger _logger; public HangfireJobLoggingFilter(ILogger logger) { _logger = logger; } // 任务开始执行时触发 public void OnPerforming(PerformingContext context) { var jobName = context.Job.Method.Name; var jobId = context.BackgroundJob.Id; var parameters = string.Join(", ", context.Job.Args.Select(arg => arg?.ToString() ?? "null")); _logger.Information("[{Timestamp}] {JobName}-{JobId} has started with parameters [{Parameters}]", DateTime.UtcNow, jobName, jobId, parameters); } // 任务执行完成后触发 public void OnPerformed(PerformedContext context) { var jobName = context.Job.Method.Name; var jobId = context.BackgroundJob.Id; var status = context.Exception != null ? "Failed" : "Succeeded"; var returnObject = context.Result?.ToString() ?? "null"; if (context.Exception != null) { _logger.Error(context.Exception, "[{Timestamp}] {JobName}-{JobId} has finished with status {Status}", DateTime.UtcNow, jobName, jobId, status); } else { _logger.Information("[{Timestamp}] {JobName}-{JobId} has finished with status {Status} and returned {ReturnObject}", DateTime.UtcNow, jobName, jobId, status, returnObject); } } // 捕获任务失败状态(含重试场景) public void OnStateElection(ElectStateContext context) { if (context.CandidateState is FailedState failedState) { var jobName = context.Job.Method.Name; var jobId = context.BackgroundJob.Id; _logger.Error(failedState.Exception, "[{Timestamp}] {JobName}-{JobId} has failed with message: {ErrorMessage}", DateTime.UtcNow, jobName, jobId, failedState.Exception.Message); } } }
2. 注册过滤器到Hangfire
在Startup.cs或Program.cs中配置Hangfire时,注册全局过滤器:
// 配置Hangfire services.AddHangfire(config => { // 配置Serilog作为Hangfire的日志提供器(可选,若需Hangfire内部日志也走Serilog) config.UseSerilogLogProvider(); // 注册自定义日志过滤器 config.UseFilter(new HangfireJobLoggingFilter(Log.Logger)); }); // 启动Hangfire后台服务器 services.AddHangfireServer();
扩展说明
- 若需要捕获更多任务状态(如排队、重试、取消),可以额外实现
IApplyStateFilter接口,处理状态变更事件。 - 日志中的
Timestamp可以依赖Serilog的内置时间戳配置,无需手动传入,只需在Serilog配置中开启即可(比如Enrich.FromLogContext()+ 模板中包含{Timestamp:yyyy-MM-dd HH:mm:ss})。
内容的提问来源于stack exchange,提问作者Raamyy
相关产品推荐
相关产品推荐

