sentry-sidekiq 5.10.0 → 5.17.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e0032fc4b32f7d021cb268513357d37f6697fcae83a4d976a9b0e011e31931e9
4
- data.tar.gz: f32997df5b2f5aab6430d5828f8a678eff2e3440fc3b55b64f1bea5ab7de752f
3
+ metadata.gz: f5f509137be0aeafc58f722b7080f62e59536bd1536ec23cc7197d49909a8223
4
+ data.tar.gz: 77916ec8f88c630ef4bb90850cab1dd88971f36bcb5fc5126b8f38ad75a94697
5
5
  SHA512:
6
- metadata.gz: 36a7e7af214cfa651ab6a05c34735cb27ada4647a74c2ec3cf4e10af65eee47dd9cfd6bd8551c50971aede6315849f63c7fc44cefa7c8770504421cf24c3333d
7
- data.tar.gz: a74c6e2bd56eba75ad59504c87636a4de882f890af3ae97d898d2b8c9db7ff7431cc14d55aff13e4bdf44c6b287af4ff3417afad2eaa42806da585c742097119
6
+ metadata.gz: 450ab95f57fb91a548633da8c2d89392671c60e4f6323fdceef346a22f0e1143bc754f2af8fab7609bc1029f934324ae2f043e10e045f35a3bd180c5c518efa1
7
+ data.tar.gz: 2be23303499087c586e49cda2b24a963a67df2f1189dded68fbbe60f2b5a8ea10769fb670920d6d31264ac0a801a0ad3468c291e1e159daff2ef71af90d653d1
data/Gemfile CHANGED
@@ -6,25 +6,24 @@ gemspec
6
6
  gem "sentry-ruby", path: "../sentry-ruby"
7
7
  gem "sentry-rails", path: "../sentry-rails"
8
8
 
9
- gem "rake", "~> 12.0"
10
- gem "rspec", "~> 3.0"
11
- gem 'simplecov'
12
- gem "simplecov-cobertura", "~> 1.4"
13
- gem "rexml"
14
9
  # https://github.com/flavorjones/loofah/pull/267
15
10
  # loofah changed the required ruby version in a patch so we need to explicitly pin it
16
11
  gem "loofah", "2.20.0" if RUBY_VERSION.to_f < 2.5
17
12
 
13
+ # For https://github.com/ruby/psych/issues/655
14
+ gem "psych", "5.1.0"
15
+
18
16
  sidekiq_version = ENV["SIDEKIQ_VERSION"]
19
- sidekiq_version = "6.0" if sidekiq_version.nil?
17
+ sidekiq_version = "7.0" if sidekiq_version.nil?
18
+ sidekiq_version = Gem::Version.new(sidekiq_version)
20
19
 
21
20
  gem "sidekiq", "~> #{sidekiq_version}"
22
- gem "rails"
23
21
 
24
- if RUBY_VERSION.to_f >= 2.6
25
- gem "debug", github: "ruby/debug", platform: :ruby
26
- gem "irb"
22
+ if RUBY_VERSION.to_f >= 2.7 && sidekiq_version >= Gem::Version.new("6.0")
23
+ gem "sidekiq-cron"
24
+ gem "sidekiq-scheduler"
27
25
  end
28
26
 
29
- gem "pry"
27
+ gem "rails", "> 5.0.0"
30
28
 
29
+ eval_gemfile File.expand_path("../Gemfile", __dir__)
data/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
 
13
13
  [![Gem Version](https://img.shields.io/gem/v/sentry-sidekiq.svg)](https://rubygems.org/gems/sentry-sidekiq)
14
- ![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-sidekiq%20Test/badge.svg)
14
+ ![Build Status](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml/badge.svg)
15
15
  [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master)
16
16
  [![Gem](https://img.shields.io/gem/dt/sentry-sidekiq.svg)](https://rubygems.org/gems/sentry-sidekiq/)
17
17
  [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=sentry-sidekiq&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=sentry-sidekiq&package-manager=bundler&version-scheme=semver)
data/Rakefile CHANGED
@@ -5,4 +5,4 @@ RSpec::Core::RakeTask.new(:spec).tap do |task|
5
5
  task.rspec_opts = "--order rand"
6
6
  end
7
7
 
8
- task :default => :spec
8
+ task default: :spec
data/example/Gemfile CHANGED
@@ -4,5 +4,4 @@ gem "sidekiq"
4
4
  gem "sentry-sidekiq", path: "../"
5
5
  gem "sentry-ruby", path: "../../sentry-ruby"
6
6
 
7
- gem "pry"
8
7
  gem "debug", github: "ruby/debug"
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Try requiring sidekiq-cron to ensure it's loaded before the integration.
4
+ # If sidekiq-cron is not available, do nothing.
5
+ begin
6
+ require "sidekiq-cron"
7
+ rescue LoadError
8
+ return
9
+ end
10
+
11
+ module Sentry
12
+ module Sidekiq
13
+ module Cron
14
+ module Job
15
+ def save
16
+ # validation failed, do nothing
17
+ return false unless super
18
+
19
+ # fail gracefully if can't find class
20
+ klass_const =
21
+ begin
22
+ ::Sidekiq::Cron::Support.constantize(klass.to_s)
23
+ rescue NameError
24
+ return true
25
+ end
26
+
27
+ # only patch if not explicitly included in job by user
28
+ unless klass_const.send(:ancestors).include?(Sentry::Cron::MonitorCheckIns)
29
+ klass_const.send(:include, Sentry::Cron::MonitorCheckIns)
30
+ klass_const.send(:sentry_monitor_check_ins,
31
+ slug: name,
32
+ monitor_config: Sentry::Cron::MonitorConfig.from_crontab(cron))
33
+ end
34
+
35
+ true
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ Sentry.register_patch(:sidekiq_cron, Sentry::Sidekiq::Cron::Job, ::Sidekiq::Cron::Job)
@@ -5,7 +5,13 @@ module Sentry
5
5
  class ErrorHandler
6
6
  WITH_SIDEKIQ_7 = ::Gem::Version.new(::Sidekiq::VERSION) >= ::Gem::Version.new("7.0")
7
7
 
8
- def call(ex, context)
8
+ # @param ex [Exception] the exception / error that occured
9
+ # @param context [Hash or Array] Sidekiq error context
10
+ # @param sidekiq_config [Sidekiq::Config, Hash] Sidekiq configuration,
11
+ # Defaults to nil.
12
+ # Sidekiq will pass the config in starting Sidekiq 7.1.5, see
13
+ # https://github.com/sidekiq/sidekiq/pull/6051
14
+ def call(ex, context, sidekiq_config = nil)
9
15
  return unless Sentry.initialized?
10
16
 
11
17
  context_filter = Sentry::Sidekiq::ContextFilter.new(context)
@@ -13,9 +19,12 @@ module Sentry
13
19
  scope = Sentry.get_current_scope
14
20
  scope.set_transaction_name(context_filter.transaction_name, source: :task) unless scope.transaction_name
15
21
 
22
+ # If Sentry is configured to only report an error _after_ all retries have been exhausted,
23
+ # and if the job is retryable, and have not exceeded the retry_limit,
24
+ # return early.
16
25
  if Sentry.configuration.sidekiq.report_after_job_retries && retryable?(context)
17
26
  retry_count = context.dig(:job, "retry_count")
18
- if retry_count.nil? || retry_count < retry_limit(context) - 1
27
+ if retry_count.nil? || retry_count < retry_limit(context, sidekiq_config) - 1
19
28
  return
20
29
  end
21
30
  end
@@ -37,7 +46,10 @@ module Sentry
37
46
  retry_option == true || (retry_option.is_a?(Integer) && retry_option.positive?)
38
47
  end
39
48
 
40
- def retry_limit(context)
49
+ # @return [Integer] the number of retries allowed for the job
50
+ # Tries to fetch the retry limit from the job config first,
51
+ # then falls back to Sidekiq's configuration.
52
+ def retry_limit(context, sidekiq_config)
41
53
  limit = context.dig(:job, "retry")
42
54
 
43
55
  case limit
@@ -46,7 +58,11 @@ module Sentry
46
58
  when TrueClass
47
59
  max_retries =
48
60
  if WITH_SIDEKIQ_7
49
- ::Sidekiq.default_configuration[:max_retries]
61
+ # Sidekiq 7.1.5+ passes the config to the error handler, so we should use that.
62
+ # Sidekiq 7.0 -> 7.1.5 provides ::Sidekiq.default_configuration.
63
+ sidekiq_config.is_a?(::Sidekiq::Config) ?
64
+ sidekiq_config[:max_retries] :
65
+ ::Sidekiq.default_configuration[:max_retries]
50
66
  else
51
67
  ::Sidekiq.options[:max_retries]
52
68
  end
@@ -19,7 +19,7 @@ module Sentry
19
19
  scope.set_tags(build_tags(job["tags"]))
20
20
  scope.set_contexts(sidekiq: job.merge("queue" => queue))
21
21
  scope.set_transaction_name(context_filter.transaction_name, source: :task)
22
- transaction = start_transaction(scope, job["sentry_trace"])
22
+ transaction = start_transaction(scope, job["trace_propagation_headers"])
23
23
  scope.set_span(transaction) if transaction
24
24
 
25
25
  begin
@@ -39,9 +39,9 @@ module Sentry
39
39
  Array(tags).each_with_object({}) { |name, tags_hash| tags_hash[:"sidekiq.#{name}"] = true }
40
40
  end
41
41
 
42
- def start_transaction(scope, sentry_trace)
42
+ def start_transaction(scope, env)
43
43
  options = { name: scope.transaction_name, source: scope.transaction_source, op: OP_NAME }
44
- transaction = Sentry::Transaction.from_sentry_trace(sentry_trace, **options) if sentry_trace
44
+ transaction = Sentry.continue_trace(env, **options)
45
45
  Sentry.start_transaction(transaction: transaction, **options)
46
46
  end
47
47
 
@@ -58,9 +58,8 @@ module Sentry
58
58
  return yield unless Sentry.initialized?
59
59
 
60
60
  user = Sentry.get_current_scope.user
61
- transaction = Sentry.get_current_scope.get_transaction
62
61
  job["sentry_user"] = user unless user.empty?
63
- job["sentry_trace"] = transaction.to_sentry_trace if transaction
62
+ job["trace_propagation_headers"] ||= Sentry.get_trace_propagation_headers
64
63
  yield
65
64
  end
66
65
  end
@@ -1,5 +1,5 @@
1
1
  module Sentry
2
2
  module Sidekiq
3
- VERSION = "5.10.0"
3
+ VERSION = "5.17.3"
4
4
  end
5
5
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Try to require sidekiq-scheduler to make sure it's loaded before the integration.
4
+ begin
5
+ require "sidekiq-scheduler"
6
+ rescue LoadError
7
+ return
8
+ end
9
+
10
+ # If we've loaded sidekiq-scheduler, but the API changed,
11
+ # and the Scheduler class is not there, fail gracefully.
12
+ return unless defined?(::SidekiqScheduler::Scheduler)
13
+
14
+ module Sentry
15
+ module SidekiqScheduler
16
+ module Scheduler
17
+ def new_job(name, interval_type, config, schedule, options)
18
+ # Schedule the job upstream first
19
+ # SidekiqScheduler does not validate schedules
20
+ # It will fail with an error if the schedule in the config is invalid.
21
+ # If this errors out, let it fall through.
22
+ rufus_job = super
23
+
24
+ klass = config.fetch("class")
25
+ return rufus_job unless klass
26
+
27
+ # Constantize the job class, and fail gracefully if it could not be found
28
+ klass_const =
29
+ begin
30
+ Object.const_get(klass)
31
+ rescue NameError
32
+ return rufus_job
33
+ end
34
+
35
+ # For cron, every, or interval jobs — grab their schedule.
36
+ # Rufus::Scheduler::EveryJob stores it's frequency in seconds,
37
+ # so we convert it to minutes before passing in to the monitor.
38
+ monitor_config =
39
+ case interval_type
40
+ when "cron"
41
+ # fugit is a second order dependency of sidekiq-scheduler via rufus-scheduler
42
+ parsed_cron = ::Fugit.parse_cron(schedule)
43
+ timezone = parsed_cron.timezone
44
+
45
+ # fugit supports having the timezone part of the cron string,
46
+ # so we need to pull that with some hacky stuff
47
+ if timezone
48
+ parsed_cron.instance_variable_set(:@timezone, nil)
49
+ cron_without_timezone = parsed_cron.to_cron_s
50
+ Sentry::Cron::MonitorConfig.from_crontab(cron_without_timezone, timezone: timezone.name)
51
+ else
52
+ Sentry::Cron::MonitorConfig.from_crontab(schedule)
53
+ end
54
+ when "every", "interval"
55
+ Sentry::Cron::MonitorConfig.from_interval(rufus_job.frequency.to_i / 60, :minute)
56
+ end
57
+
58
+ # If we couldn't build a monitor config, it's either an error, or
59
+ # it's a one-time job (interval_type is in, or at), in which case
60
+ # we should not make a monitof for it automaticaly.
61
+ return rufus_job if monitor_config.nil?
62
+
63
+ # only patch if not explicitly included in job by user
64
+ unless klass_const.send(:ancestors).include?(Sentry::Cron::MonitorCheckIns)
65
+ klass_const.send(:include, Sentry::Cron::MonitorCheckIns)
66
+ slug = klass_const.send(:sentry_monitor_slug, name: name)
67
+ klass_const.send(:sentry_monitor_check_ins,
68
+ slug: slug,
69
+ monitor_config: monitor_config)
70
+
71
+ ::Sidekiq.logger.info "Injected Sentry Crons monitor checkins into #{klass}"
72
+ end
73
+
74
+ rufus_job
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ Sentry.register_patch(:sidekiq_scheduler, Sentry::SidekiqScheduler::Scheduler, ::SidekiqScheduler::Scheduler)
@@ -39,3 +39,7 @@ Sidekiq.configure_client do |config|
39
39
  chain.add Sentry::Sidekiq::SentryContextClientMiddleware
40
40
  end
41
41
  end
42
+
43
+ # patches
44
+ require "sentry/sidekiq/cron/job"
45
+ require "sentry/sidekiq-scheduler/scheduler"
@@ -22,6 +22,6 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- spec.add_dependency "sentry-ruby", "~> 5.10.0"
25
+ spec.add_dependency "sentry-ruby", "~> 5.17.3"
26
26
  spec.add_dependency "sidekiq", ">= 3.0"
27
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry-sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.10.0
4
+ version: 5.17.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-04 00:00:00.000000000 Z
11
+ date: 2024-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sentry-ruby
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 5.10.0
19
+ version: 5.17.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 5.10.0
26
+ version: 5.17.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sidekiq
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -61,8 +61,10 @@ files:
61
61
  - example/config/sidekiq.yml
62
62
  - example/error_worker.rb
63
63
  - lib/sentry-sidekiq.rb
64
+ - lib/sentry/sidekiq-scheduler/scheduler.rb
64
65
  - lib/sentry/sidekiq/configuration.rb
65
66
  - lib/sentry/sidekiq/context_filter.rb
67
+ - lib/sentry/sidekiq/cron/job.rb
66
68
  - lib/sentry/sidekiq/error_handler.rb
67
69
  - lib/sentry/sidekiq/sentry_context_middleware.rb
68
70
  - lib/sentry/sidekiq/version.rb