Skip to content

Commit 0699b8c

Browse files
committed
Add sidekiq-cron patch for automatic monitoring of jobs listed in the
schedule * optional patch under `sidekiq_cron` * patch the `Sidekiq::Cron::Job#save` method and auto inject the Sentry::MonitorCheckIns module and turn monitoring on part of #2134
1 parent a418b54 commit 0699b8c

File tree

8 files changed

+108
-4
lines changed

8 files changed

+108
-4
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
### Features
44

55
- Improve default slug generation for Crons [#2168](https://github.com/getsentry/sentry-ruby/pull/2168)
6+
- Automatic Crons support for scheduling gems
7+
- Add support for [`sidekiq-cron`](https://github.com/sidekiq-cron/sidekiq-cron) [#2170](https://github.com/getsentry/sentry-ruby/pull/2170)
8+
9+
You can opt in to the `sidekiq-cron` patch and we will automatically monitor check-ins for all jobs listed in your `config/schedule.yml` file.
10+
11+
```rb
12+
config.enabled_patches += [:sidekiq_cron]
13+
```
614

715
### Bug Fixes
816

sentry-sidekiq/Gemfile

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ sidekiq_version = "7.0" if sidekiq_version.nil?
2323
sidekiq_version = Gem::Version.new(sidekiq_version)
2424

2525
gem "sidekiq", "~> #{sidekiq_version}"
26+
gem "sidekiq-cron" if sidekiq_version >= Gem::Version.new("6.0")
2627

2728
gem "rails", "> 5.0.0", "< 7.1.0"
2829

sentry-sidekiq/lib/sentry-sidekiq.rb

+3
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,6 @@ class Railtie < ::Rails::Railtie
3939
chain.add Sentry::Sidekiq::SentryContextClientMiddleware
4040
end
4141
end
42+
43+
# patches
44+
require "sentry/sidekiq/cron/job"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# frozen_string_literal: true
2+
3+
return unless defined?(::Sidekiq::Cron::Job)
4+
5+
module Sentry
6+
module Sidekiq
7+
module Cron
8+
module Job
9+
def save
10+
# validation failed, do nothing
11+
return false unless super
12+
13+
# fail gracefully if can't find class
14+
klass_const =
15+
begin
16+
::Sidekiq::Cron::Support.constantize(klass.to_s)
17+
rescue NameError
18+
return true
19+
end
20+
21+
# only patch if not explicitly included in job by user
22+
unless klass_const.send(:ancestors).include?(Sentry::Cron::MonitorCheckIns)
23+
klass_const.send(:include, Sentry::Cron::MonitorCheckIns)
24+
klass_const.send(:sentry_monitor_check_ins,
25+
slug: name,
26+
monitor_config: Sentry::Cron::MonitorConfig.from_crontab(cron))
27+
end
28+
end
29+
end
30+
end
31+
end
32+
end
33+
34+
Sentry.register_patch(:sidekiq_cron, Sentry::Sidekiq::Cron::Job, ::Sidekiq::Cron::Job)
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
happy:
2+
cron: "* * * * *"
3+
class: "HappyWorkerDup"
4+
5+
manual:
6+
cron: "* * * * *"
7+
class: "SadWorkerWithCron"
8+
9+
invalid_cron:
10+
cron: "not a crontab"
11+
class: "ReportingWorker"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
require 'spec_helper'
2+
3+
return unless defined?(Sidekiq::Cron::Job)
4+
5+
RSpec.describe Sentry::Sidekiq::Cron::Job do
6+
before do
7+
perform_basic_setup { |c| c.enabled_patches += [:sidekiq_cron] }
8+
end
9+
10+
before do
11+
schedule_file = 'spec/fixtures/schedule.yml'
12+
schedule = Sidekiq::Cron::Support.load_yaml(ERB.new(IO.read(schedule_file)).result)
13+
Sidekiq::Cron::Job.load_from_hash!(schedule, source: 'schedule')
14+
end
15+
16+
it 'patches class' do
17+
expect(Sidekiq::Cron::Job.ancestors).to include(described_class)
18+
end
19+
20+
it 'patches HappyWorker' do
21+
expect(HappyWorkerDup.ancestors).to include(Sentry::Cron::MonitorCheckIns)
22+
expect(HappyWorkerDup.sentry_monitor_slug).to eq('happy')
23+
expect(HappyWorkerDup.sentry_monitor_config).to be_a(Sentry::Cron::MonitorConfig)
24+
expect(HappyWorkerDup.sentry_monitor_config.schedule).to be_a(Sentry::Cron::MonitorSchedule::Crontab)
25+
expect(HappyWorkerDup.sentry_monitor_config.schedule.value).to eq('* * * * *')
26+
end
27+
28+
it 'does not override SadWorkerWithCron manually set values' do
29+
expect(SadWorkerWithCron.ancestors).to include(Sentry::Cron::MonitorCheckIns)
30+
expect(SadWorkerWithCron.sentry_monitor_slug).to eq('failed_job')
31+
expect(SadWorkerWithCron.sentry_monitor_config).to be_a(Sentry::Cron::MonitorConfig)
32+
expect(SadWorkerWithCron.sentry_monitor_config.schedule).to be_a(Sentry::Cron::MonitorSchedule::Crontab)
33+
expect(SadWorkerWithCron.sentry_monitor_config.schedule.value).to eq('5 * * * *')
34+
end
35+
36+
it 'does not patch ReportingWorker because of invalid schedule' do
37+
expect(ReportingWorker.ancestors).not_to include(Sentry::Cron::MonitorSchedule)
38+
end
39+
40+
it 'does not raise error on invalid class' do
41+
expect do
42+
Sidekiq::Cron::Job.create(name: 'invalid_class', cron: '* * * * *', class: 'UndefinedClass')
43+
end.not_to raise_error
44+
end
45+
46+
end

sentry-sidekiq/spec/sentry/sidekiq_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
event = transport.events.last.to_json_compatible
9898

9999
expect(event["message"]).to eq "I have something to say!"
100-
expect(event["contexts"]["sidekiq"]).to eq("args" => [], "class" => "ReportingWorker", "jid" => "123123", "queue" => "default")
100+
expect(event["contexts"]["sidekiq"]).to include("args" => [], "class" => "ReportingWorker", "jid" => "123123", "queue" => "default")
101101
end
102102

103103
it "adds the failed job to the retry queue" do

sentry-sidekiq/spec/spec_helper.rb

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
WITH_SIDEKIQ_7 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new("7.0")
99
WITH_SIDEKIQ_6 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new("6.0") && !WITH_SIDEKIQ_7
1010

11-
if WITH_SIDEKIQ_7
12-
require "sidekiq/embedded"
13-
end
11+
require "sidekiq/embedded" if WITH_SIDEKIQ_7
12+
require 'sidekiq-cron' if RUBY_VERSION.to_f >= 2.7 && WITH_SIDEKIQ_6 || WITH_SIDEKIQ_7
1413

1514
require "sentry-ruby"
1615

@@ -129,6 +128,8 @@ def perform
129128
end
130129
end
131130

131+
class HappyWorkerDup < HappyWorker; end
132+
132133
class HappyWorkerWithCron < HappyWorker
133134
include Sentry::Cron::MonitorCheckIns
134135
sentry_monitor_check_ins

0 commit comments

Comments
 (0)