Skip to content

Commit

Permalink
Add sidekiq-cron patch for automatic monitoring of jobs listed in the
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sl0thentr0py committed Nov 16, 2023
1 parent a418b54 commit 1ff8687
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 4 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
### Features

- Improve default slug generation for Crons [#2168](https://github.com/getsentry/sentry-ruby/pull/2168)
- Automatic Crons support for scheduling gems
- Add support for `sidekiq-cron` [#2170](https://github.com/getsentry/sentry-ruby/pull/2170)

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.

```rb
config.enabled_patches += [:sidekiq_cron]
```

### Bug Fixes

Expand Down
1 change: 1 addition & 0 deletions sentry-sidekiq/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ sidekiq_version = "7.0" if sidekiq_version.nil?
sidekiq_version = Gem::Version.new(sidekiq_version)

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

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

Expand Down
3 changes: 3 additions & 0 deletions sentry-sidekiq/lib/sentry-sidekiq.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ class Railtie < ::Rails::Railtie
chain.add Sentry::Sidekiq::SentryContextClientMiddleware
end
end

# patches
require "sentry/sidekiq/cron/job"
34 changes: 34 additions & 0 deletions sentry-sidekiq/lib/sentry/sidekiq/cron/job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

return unless defined?(::Sidekiq::Cron::Job)

module Sentry
module Sidekiq
module Cron
module Job
def save
# validation failed, do nothing
return false unless super

# fail gracefully if can't find class
klass_const =
begin
::Sidekiq::Cron::Support.constantize(klass.to_s)
rescue NameError
return true
end

# 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: Sentry::Cron::MonitorConfig.from_crontab(cron))
end
end
end
end
end
end

Sentry.register_patch(:sidekiq_cron, Sentry::Sidekiq::Cron::Job, ::Sidekiq::Cron::Job)
11 changes: 11 additions & 0 deletions sentry-sidekiq/spec/fixtures/schedule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
happy:
cron: "* * * * *"
class: "HappyWorkerDup"

manual:
cron: "* * * * *"
class: "SadWorkerWithCron"

invalid_cron:
cron: "not a crontab"
class: "ReportingWorker"
46 changes: 46 additions & 0 deletions sentry-sidekiq/spec/sentry/sidekiq/cron/job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'spec_helper'

return unless defined?(Sidekiq::Cron::Job)

RSpec.describe Sentry::Sidekiq::Cron::Job do
before do
perform_basic_setup { |c| c.enabled_patches += [:sidekiq_cron] }
end

before do
schedule_file = 'spec/fixtures/schedule.yml'
schedule = Sidekiq::Cron::Support.load_yaml(ERB.new(IO.read(schedule_file)).result)
Sidekiq::Cron::Job.load_from_hash!(schedule, source: 'schedule')
end

it 'patches class' do
expect(Sidekiq::Cron::Job.ancestors).to include(described_class)
end

it 'patches HappyWorker' do
expect(HappyWorkerDup.ancestors).to include(Sentry::Cron::MonitorCheckIns)
expect(HappyWorkerDup.sentry_monitor_slug).to eq('happy')
expect(HappyWorkerDup.sentry_monitor_config).to be_a(Sentry::Cron::MonitorConfig)
expect(HappyWorkerDup.sentry_monitor_config.schedule).to be_a(Sentry::Cron::MonitorSchedule::Crontab)
expect(HappyWorkerDup.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 'does not patch ReportingWorker because of invalid schedule' do
expect(ReportingWorker.ancestors).not_to include(Sentry::Cron::MonitorSchedule)
end

it 'does not raise error on invalid class' do
expect do
Sidekiq::Cron::Job.create(name: 'invalid_class', cron: '* * * * *', class: 'UndefinedClass')
end.not_to raise_error
end

end
2 changes: 1 addition & 1 deletion sentry-sidekiq/spec/sentry/sidekiq_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
event = transport.events.last.to_json_compatible

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

it "adds the failed job to the retry queue" do
Expand Down
7 changes: 4 additions & 3 deletions sentry-sidekiq/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
WITH_SIDEKIQ_7 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new("7.0")
WITH_SIDEKIQ_6 = Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new("6.0") && !WITH_SIDEKIQ_7

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

require "sentry-ruby"

Expand Down Expand Up @@ -129,6 +128,8 @@ def perform
end
end

class HappyWorkerDup < HappyWorker; end

class HappyWorkerWithCron < HappyWorker
include Sentry::Cron::MonitorCheckIns
sentry_monitor_check_ins
Expand Down

0 comments on commit 1ff8687

Please sign in to comment.