-
-
Notifications
You must be signed in to change notification settings - Fork 501
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Crons: add
sidekiq-scheduler
zero-config monitor check-ins (#2172)
* Crons: add sidekiq-scheduler zero config support. - Adds support for `sidekiq-scheduler` instrumentation without any configuration from the user. - Based on #2170. * Crons: support intervals for sidekiq-scheduler jobs - AppliesApply review feedback. - Adds support for interval and every interval_types for sidekiq-scheduler-schedule - Adds specs for the above. * Crons: changelog for sidekiq-scheduler support. * Crons: fix tests on Sidekiq 6 * Require sidekiq-scheduler to ensure it's there * sidekiq-scheduler mock config without delegation * Make version checks consistent * Fix some stuff * need int for interval * constantize doesn't exist outside rails * cleanup specs --------- Co-authored-by: Neel Shah <neelshah.sa@gmail.com>
- Loading branch information
1 parent
78fb37a
commit 7793e97
Showing
9 changed files
with
189 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# frozen_string_literal: true | ||
|
||
# Try to require sidekiq-scheduler to make sure it's loaded before the integration. | ||
begin | ||
require "sidekiq-scheduler" | ||
rescue LoadError | ||
return | ||
end | ||
|
||
# If we've loaded sidekiq-scheduler, but the API changed, | ||
# and the Scheduler class is not there, fail gracefully. | ||
return unless defined?(::SidekiqScheduler::Scheduler) | ||
|
||
module Sentry | ||
module SidekiqScheduler | ||
module Scheduler | ||
def new_job(name, interval_type, config, schedule, options) | ||
# Schedule the job upstream first | ||
# SidekiqScheduler does not validate schedules | ||
# It will fail with an error if the schedule in the config is invalid. | ||
# If this errors out, let it fall through. | ||
rufus_job = super | ||
|
||
klass = config.fetch("class") | ||
return rufus_job unless klass | ||
|
||
# Constantize the job class, and fail gracefully if it could not be found | ||
klass_const = | ||
begin | ||
Object.const_get(klass) | ||
rescue NameError | ||
return rufus_job | ||
end | ||
|
||
# For cron, every, or interval jobs — grab their schedule. | ||
# Rufus::Scheduler::EveryJob stores it's frequency in seconds, | ||
# so we convert it to minutes before passing in to the monitor. | ||
monitor_config = case interval_type | ||
when "cron" | ||
Sentry::Cron::MonitorConfig.from_crontab(schedule) | ||
when "every", "interval" | ||
Sentry::Cron::MonitorConfig.from_interval(rufus_job.frequency.to_i / 60, :minute) | ||
end | ||
|
||
# If we couldn't build a monitor config, it's either an error, or | ||
# it's a one-time job (interval_type is in, or at), in which case | ||
# we should not make a monitof for it automaticaly. | ||
return rufus_job if monitor_config.nil? | ||
|
||
# only patch if not explicitly included in job by user | ||
unless klass_const.send(:ancestors).include?(Sentry::Cron::MonitorCheckIns) | ||
klass_const.send(:include, Sentry::Cron::MonitorCheckIns) | ||
klass_const.send(:sentry_monitor_check_ins, | ||
slug: name, | ||
monitor_config: monitor_config) | ||
|
||
::Sidekiq.logger.info "Injected Sentry Crons monitor checkins into #{klass}" | ||
end | ||
|
||
rufus_job | ||
end | ||
end | ||
end | ||
end | ||
|
||
Sentry.register_patch(:sidekiq_scheduler, Sentry::SidekiqScheduler::Scheduler, ::SidekiqScheduler::Scheduler) |
2 changes: 1 addition & 1 deletion
2
sentry-sidekiq/spec/fixtures/schedule.yml → ...q/spec/fixtures/sidekiq-cron-schedule.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
happy: | ||
cron: "* * * * *" | ||
class: "HappyWorkerDup" | ||
class: "HappyWorkerForCron" | ||
|
||
manual: | ||
cron: "* * * * *" | ||
|
14 changes: 14 additions & 0 deletions
14
sentry-sidekiq/spec/fixtures/sidekiq-scheduler-schedule.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
:schedule: | ||
happy: | ||
cron: "* * * * *" | ||
class: "HappyWorkerForScheduler" | ||
manual: | ||
cron: "* * * * *" | ||
class: "SadWorkerWithCron" | ||
regularly_happy: | ||
every: "10 minutes" | ||
class: "EveryHappyWorker" | ||
reports: | ||
in: "2 hours" | ||
class: "ReportingWorker" | ||
|
56 changes: 56 additions & 0 deletions
56
sentry-sidekiq/spec/sentry/sidekiq-scheduler/scheduler_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
require 'spec_helper' | ||
|
||
return unless defined?(SidekiqScheduler::Scheduler) | ||
|
||
RSpec.describe Sentry::SidekiqScheduler::Scheduler do | ||
before do | ||
perform_basic_setup { |c| c.enabled_patches += [:sidekiq_scheduler] } | ||
end | ||
|
||
before do | ||
schedule_file = 'spec/fixtures/sidekiq-scheduler-schedule.yml' | ||
config_options = { scheduler: YAML.load_file(schedule_file) } | ||
|
||
# Sidekiq::Scheduler merges it's config with Sidekiq. | ||
# To grab a config for it to start, we need to pass sidekiq configuration | ||
# (defaults should be fine though). | ||
scheduler_config = SidekiqScheduler::Config.new(sidekiq_config: sidekiq_config(config_options)) | ||
|
||
# Making and starting a Manager instance will load the jobs | ||
schedule_manager = SidekiqScheduler::Manager.new(scheduler_config) | ||
schedule_manager.start | ||
end | ||
|
||
it 'patches class' do | ||
expect(SidekiqScheduler::Scheduler.ancestors).to include(described_class) | ||
end | ||
|
||
it 'patches HappyWorkerForScheduler' do | ||
expect(HappyWorkerForScheduler.ancestors).to include(Sentry::Cron::MonitorCheckIns) | ||
expect(HappyWorkerForScheduler.sentry_monitor_slug).to eq('happy') | ||
expect(HappyWorkerForScheduler.sentry_monitor_config).to be_a(Sentry::Cron::MonitorConfig) | ||
expect(HappyWorkerForScheduler.sentry_monitor_config.schedule).to be_a(Sentry::Cron::MonitorSchedule::Crontab) | ||
expect(HappyWorkerForScheduler.sentry_monitor_config.schedule.value).to eq('* * * * *') | ||
end | ||
|
||
it 'does not override SadWorkerWithCron manually set values' do | ||
expect(SadWorkerWithCron.ancestors).to include(Sentry::Cron::MonitorCheckIns) | ||
expect(SadWorkerWithCron.sentry_monitor_slug).to eq('failed_job') | ||
expect(SadWorkerWithCron.sentry_monitor_config).to be_a(Sentry::Cron::MonitorConfig) | ||
expect(SadWorkerWithCron.sentry_monitor_config.schedule).to be_a(Sentry::Cron::MonitorSchedule::Crontab) | ||
expect(SadWorkerWithCron.sentry_monitor_config.schedule.value).to eq('5 * * * *') | ||
end | ||
|
||
it "sets correct monitor config based on `every` schedule" do | ||
expect(EveryHappyWorker.ancestors).to include(Sentry::Cron::MonitorCheckIns) | ||
expect(EveryHappyWorker.sentry_monitor_slug).to eq('regularly_happy') | ||
expect(EveryHappyWorker.sentry_monitor_config).to be_a(Sentry::Cron::MonitorConfig) | ||
expect(EveryHappyWorker.sentry_monitor_config.schedule).to be_a(Sentry::Cron::MonitorSchedule::Interval) | ||
expect(EveryHappyWorker.sentry_monitor_config.schedule.to_hash).to eq({value: 10, type: :interval, unit: :minute}) | ||
end | ||
|
||
it "does not add monitors for a one-off job" do | ||
expect(ReportingWorker.ancestors).not_to include(Sentry::Cron::MonitorCheckIns) | ||
end | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters