Skip to content

feat: add Sentry.Quartz3 for cron monitoring of Quartz.NET 3.x jobs - #5668

Open
wedamija wants to merge 66 commits into
mainfrom
danf/quartz-crons
Open

wedamija wants to merge 66 commits into
mainfrom
danf/quartz-crons

Conversation

@wedamija

@wedamija wedamija commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Part of a series adding automatic Crons monitoring for the most-used job schedulers in each SDK. Check-ins for a monitor that doesn't exist yet are dropped, so today each monitor has to be created by hand with its schedule copied from the code. Sending the job's schedule as the monitor config lets Sentry create the monitor and keep it in sync.

Adds Sentry.Quartz3, the Quartz.NET 3.x version of Sentry.Quartz. Quartz 4 only targets net10.0, so apps on .NET Framework or older .NET stay on Quartz 3. It builds the shared core files against Quartz [3.6.0,4.0.0) for net8.0 to net10.0 and net462, and runs them from an IJobListener because Quartz 3 has no job middleware.

services.AddQuartz(q => q.AddJobListener<SentryJobListener>());
// or: scheduler.ListenerManager.AddJobListener(new SentryJobListener());

As in Sentry.Quartz, jobs with [SentryMonitorSlug] send check-ins with their trigger's schedule unless SendMonitorConfig is off. A listener can't wrap the job, so there is no per-job scope or exception capture. Under Quartz 4 the listener would never be called, so it logs an error pointing to Sentry.Quartz.

A release-registry entry is needed before the first release.

Stacked on #5505 by @michaelmairegger, which is still open. The base branch danf/quartz-5505-rebased is a copy of its branch.
Docs: getsentry/sentry-docs#19790

@codecov

codecov Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.14286% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.12%. Comparing base (04cac0d) to head (4b670aa).

Files with missing lines Patch % Lines
src/Sentry.Quartz3/SentryJobListener.cs 65.21% 7 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5668      +/-   ##
==========================================
- Coverage   76.13%   76.12%   -0.02%     
==========================================
  Files         528      530       +2     
  Lines       19579    19615      +36     
  Branches     3829     3839      +10     
==========================================
+ Hits        14906    14931      +25     
- Misses       3791     3799       +8     
- Partials      882      885       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@wedamija
wedamija changed the base branch from main to danf/quartz4-crons October 6, 2026 02:03
@wedamija wedamija changed the title feat: add Sentry.Quartz for cron monitoring of Quartz.NET jobs feat: add Sentry.Quartz3 for cron monitoring of Quartz.NET 3.x jobs Oct 6, 2026
… dependencies and streamlining SentryCronJobListener options handling
… collection parameter and streamlining option configuration
…dSentryScope method, update SentryMetricsMiddleware to support configurable options
wedamija and others added 7 commits October 13, 2026 15:11
…ibute rename

Co-Authored-By: Claude <noreply@anthropic.com>
The AddSentry() remarks still said job exceptions are left to the logging integration. The scope middleware has captured them again since 73e5551.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…schedules

Reads every monitored trigger, cached for a minute, like Sentry.Hangfire. Replaces the check for jobs with several triggers.
A job without an identity has fallen back to its class name with a debug message, not a warning, since fe97276.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jamescrosswell

Copy link
Copy Markdown
Collaborator

Heads-up: #5505 now detects shared slugs differently (787ab1e), and this PR will stop compiling once it merges that in. Both packages compile the same Core/ files, so Sentry.Quartz3 needs Quartz 3 versions of two shims:

  1. src/Sentry.Quartz3/QuartzApi.cs. JobMonitor no longer calls HasSeveralTriggersAsync. It now calls QuartzApi.GetTriggersAsync(scheduler, predicate, cancellationToken) to read every monitored trigger, and only the Quartz 4 QuartzApi has that method. The Quartz 4 version uses bulk lookups (QueryTriggers, GetJobDetails, GetTriggers) that Quartz 3 doesn't have. On Quartz 3 it would be GetJobKeys(GroupMatcher<JobKey>.AnyGroup()), then GetJobDetail for each job and GetTriggersOfJob for each monitored one. That's one query per job, but JobMonitor only does the read at most once a minute, plus when a trigger it hasn't seen yet fires.
  2. test/Sentry.Quartz3.Tests/QuartzTestApi.cs. The shared core tests now call ReturnsTriggers(IReadOnlyList<(IJobDetail Job, ITrigger Trigger)>) and LookedUpTriggers(int). This shim still has the old ReturnsTriggers(JobKey, IReadOnlyList<ITrigger>) and no LookedUpTriggers.

HasSeveralTriggersAsync becomes dead code at the same time. Once #5505 is on main, this PR will also need retargeting from danf/quartz-5505-rebased to main.

jamescrosswell and others added 12 commits October 21, 2026 22:50
Picks up #5757, which fixes the Blazor WASM E2E job on Ubuntu 26.04 runners.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ports the shared slug check to Quartz 3: QuartzApi.GetTriggersAsync reads
each job and the triggers of each monitored one, since Quartz 3 has no
bulk lookups. The test shim gets the new ReturnsTriggers and
LookedUpTriggers, and HasSeveralTriggersAsync is gone.

Co-Authored-By: Claude <noreply@anthropic.com>
…gers

A job left in a persistent store after its class was renamed or deleted
made the whole trigger read throw, so no monitored job sent its schedule.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…aptured

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Quartz 3 annotates GetJobDetail differently across target frameworks.

Co-Authored-By: Claude <noreply@anthropic.com>
…tion on

Quartz's ErrorLogger logs the exception again, wrapped in a
JobExecutionProcessException that the default DeduplicateMode doesn't
unwrap. AddSentry now adds a log entry filter for that entry, to
whichever SentryLoggingOptions the app uses (SentryAspNetCoreOptions
included), when the middleware captured the inner exception.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@linear-code

linear-code Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

NET-180

NET-483

wedamija and others added 3 commits October 21, 2026 11:00
Co-authored-by: Ricardo Colombo Oliveira <github@ricoliv.com>
…log filter setup

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@wedamija
wedamija changed the base branch from danf/quartz-5505-rebased to main October 21, 2026 23:02
@wedamija
wedamija marked this pull request as ready for review October 21, 2026 23:18
@github-actions github-actions Bot added the risk: high PR risk score: high label Oct 21, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: high PR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants