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
<PackageReference Include="Fluorite.Hangfire.JobsVisualizer" Version="0.1.0" />
<PackageVersion Include="Fluorite.Hangfire.JobsVisualizer" Version="0.1.0" />
<PackageReference Include="Fluorite.Hangfire.JobsVisualizer" />
paket add Fluorite.Hangfire.JobsVisualizer --version 0.1.0
#r "nuget: Fluorite.Hangfire.JobsVisualizer, 0.1.0"
#:package Fluorite.Hangfire.JobsVisualizer@0.1.0
#addin nuget:?package=Fluorite.Hangfire.JobsVisualizer&version=0.1.0
#tool nuget:?package=Fluorite.Hangfire.JobsVisualizer&version=0.1.0
Hangfire Jobs Visualizer
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:

<details> <summary>More screenshots</summary>
Jobs grouped by period, with a ruler for every group:

Timeline of three days, one row per job:

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

</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:
JobDurationsfrom the options,- the last successful execution kept by the storage,
- 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
| Product | Versions 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. |
-
net10.0
- Cronos (>= 0.13.0)
- Fluid.Core (>= 2.40.0)
- Hangfire.Core (>= 1.8.23)
-
net8.0
- Cronos (>= 0.13.0)
- Fluid.Core (>= 2.40.0)
- Hangfire.Core (>= 1.8.23)
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 |