You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 17:48:15