Fluorite.Hangfire.JobsVisualizer 0.1.0

dotnet add package Fluorite.Hangfire.JobsVisualizer --version 0.1.0
                    
NuGet\Install-Package Fluorite.Hangfire.JobsVisualizer -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Fluorite.Hangfire.JobsVisualizer" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Fluorite.Hangfire.JobsVisualizer" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Fluorite.Hangfire.JobsVisualizer" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Fluorite.Hangfire.JobsVisualizer --version 0.1.0
                    
#r "nuget: Fluorite.Hangfire.JobsVisualizer, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Fluorite.Hangfire.JobsVisualizer@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Fluorite.Hangfire.JobsVisualizer&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Fluorite.Hangfire.JobsVisualizer&version=0.1.0
                    
Install as a Cake Tool

Hangfire Jobs Visualizer

Coverage Mutation score

Hangfire dashboard extension that visualizes recurring jobs and helps to choose a free slot for a new one. All data is computed from the cron expressions of the jobs, no execution history is needed.

Installation

dotnet add package Fluorite.Hangfire.JobsVisualizer

Targets .NET 8 and .NET 10. Requires Hangfire 1.8 or newer.

Usage

Register the visualizer while configuring Hangfire:

builder.Services.AddHangfire(config =>
{
    config.UseSqlServerStorage(connectionString);
    config.UseRecurringJobsVisualizer();
});

app.UseHangfireDashboard();

The page is served at /hangfire/visualizer and added to the navigation bar of the dashboard. It uses the authorization of the dashboard. It plugs into Hangfire and acts like an extension.

Options

config.UseRecurringJobsVisualizer(options =>
{
    options.DefaultJobDuration = TimeSpan.FromMinutes(2);
    options.JobDurations["nightly-database-backup"] = TimeSpan.FromMinutes(40);
    options.MeasureJobDurations = true;
    options.MaxMeasuredJobsPerRequest = 200;
});
Option Default Description
DefaultJobDuration 1 minute Duration assumed when nothing better is known
JobDurations empty Durations by job id, take precedence over measured ones
MeasureJobDurations true Read durations of the last executions from the Hangfire storage
MaxMeasuredJobsPerRequest 200 Limit of jobs measured in a single request

Views

View Description
Heatmap Starts or average number of running jobs per cell, for a month, a week or a day. A cell lists the jobs in it
By period Jobs grouped by frequency (minutes, hours, daily, weekly, monthly, rare), each group on a ruler that fits it, e.g. the minute of the hour
Timeline One row per job with executions drawn as bars. Overlapping executions are marked
Load and free slots Chart of concurrently running jobs, the longest free windows, a check of a cron expression and a search for the quietest schedule

Screenshots

Heatmap of one week, every cell is half an hour:

Heatmap

<details> <summary>More screenshots</summary>

Jobs grouped by period, with a ruler for every group:

By period

Timeline of three days, one row per job:

Timeline

Load chart with the longest free windows, a check of a new cron expression and a search for a free slot:

Load and free slots

</details>

Behavior

Filtering

A slider hides jobs that run more often than a chosen interval (5 minutes by default), as pollers cover the whole picture. Jobs can also be filtered by a text, a regular expression (/^report-/) and a queue, or hidden one by one. The state is kept in the browser.

Durations

A job has a duration, taken from the first source that has one:

  1. JobDurations from the options,
  2. the last successful execution kept by the storage,
  3. an estimate: DefaultJobDuration, capped at half of the shortest gap between executions of the job.

Estimated durations are drawn faded.

Time zones

A cron expression is evaluated in the time zone of its job (TimeZoneId), as Hangfire does, including skipped and repeated hours. Times are shown in the time zone of the browser. It can be switched to UTC or any IANA zone in the top right corner.

Clock changes are shown as they are: days of 23 and 25 hours, a skipped hour (hatched cells) and a repeated hour (both of its occurrences are summed in one cell).

Limits

  • A range is limited to 62 days.
  • Jobs with an invalid cron expression are listed, but not drawn.
  • A job that runs more often than once a minute is counted as a steady load in the load chart.

HTTP endpoints

The page reads JSON from /hangfire/visualizer/api: jobs, grid, cell, periods, timeline, load, slots and candidate.

Development

dotnet build
dotnet test --no-build

Mutation testing with Stryker.NET runs against the unit tests only. The build fails when the score drops below 70%.

dotnet tool restore
cd tests/Fluorite.Hangfire.JobsVisualizer.UnitTests
dotnet dotnet-stryker

The report is saved to StrykerOutput/<date>/reports/mutation-report.html.

Examples

You can find an example project showcasing Jobs Visualizer usage in Fluorite.Hangfire.JobsVisualizer.ExampleApi. It registers jobs of many kinds, including time zones, the last day of the month and the first Monday of the month.

License

Licensed under MIT. Read full license here.

Credits

Piotr Wosiek | GitLab | GitHub

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 88 11/1/2026