appsignal 2.11.0.alpha.2-java → 2.11.0.beta.1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/.semaphore/semaphore.yml +37 -9
  4. data/CHANGELOG.md +10 -1
  5. data/build_matrix.yml +5 -1
  6. data/gemfiles/rails-4.2.gemfile +9 -2
  7. data/gemfiles/rails-5.0.gemfile +1 -0
  8. data/gemfiles/rails-5.1.gemfile +1 -0
  9. data/gemfiles/rails-5.2.gemfile +1 -0
  10. data/gemfiles/rails-6.0.gemfile +1 -0
  11. data/gemfiles/resque-1.gemfile +7 -0
  12. data/gemfiles/{resque.gemfile → resque-2.gemfile} +1 -1
  13. data/lib/appsignal/hooks.rb +2 -0
  14. data/lib/appsignal/hooks/active_job.rb +89 -0
  15. data/lib/appsignal/hooks/resque.rb +60 -0
  16. data/lib/appsignal/hooks/sidekiq.rb +16 -92
  17. data/lib/appsignal/integrations/que.rb +1 -1
  18. data/lib/appsignal/integrations/resque.rb +9 -12
  19. data/lib/appsignal/integrations/resque_active_job.rb +9 -32
  20. data/lib/appsignal/transaction.rb +10 -0
  21. data/lib/appsignal/utils/deprecation_message.rb +5 -1
  22. data/lib/appsignal/version.rb +1 -1
  23. data/spec/lib/appsignal/hooks/activejob_spec.rb +458 -0
  24. data/spec/lib/appsignal/hooks/resque_spec.rb +185 -0
  25. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +215 -263
  26. data/spec/lib/appsignal/integrations/que_spec.rb +25 -6
  27. data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +20 -179
  28. data/spec/lib/appsignal/integrations/resque_spec.rb +20 -85
  29. data/spec/lib/appsignal/probes/sidekiq_spec.rb +10 -7
  30. data/spec/lib/appsignal/transaction_spec.rb +5 -7
  31. data/spec/support/helpers/action_mailer_helpers.rb +25 -0
  32. data/spec/support/helpers/dependency_helper.rb +9 -2
  33. data/spec/support/helpers/transaction_helpers.rb +6 -0
  34. data/spec/support/stubs/sidekiq/api.rb +1 -1
  35. metadata +12 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a510cdd0af6ef1f3780e5d559a41762d7d2b094fb5309d0e10d143b223e76fb
4
- data.tar.gz: d7195e855b5a2ea44db9cfdd9c132dfb2afda1994bc4c7c8aba08181f47081d8
3
+ metadata.gz: e3403327daac577742fc279cc704c58cc766e64e71995d2206cdefa104512993
4
+ data.tar.gz: 638b4104fc2ac814a28b98ff9de32a675531fed3e6d451adb3dc996551e52458
5
5
  SHA512:
6
- metadata.gz: bcf0aa5c31a43142fb264dab678ae2b19896d2b1618ae3caf6fbacfff67c3fd46c62c87f062968a92ca93abfc88f159d7c849ca03862c661fd5540112b2a5b9a
7
- data.tar.gz: 9eb9618c8cb83f87db2b183573e64313a6fe01651bf2f5e93b748347de38e64716053ba7dcf42ce9a2954caa1c3e2096153acb37543a49cfe4c069afe7e8c705
6
+ metadata.gz: 2c51e569187ea8f8fa5d99b237c22d4ad14472527329d78463ef2c12d59cb4abce350398ead4a22e8358378eb0d12ee67fd84808c5e91c30c1e0464368b42990
7
+ data.tar.gz: 4c822a8d331d632f2fc47c06e0823092b29605e1b1f4070a978edd78f5feb4896bedc17d59437fe8b382757d93cf676fa40af0775a98ec53df6227a659cc5282
@@ -64,6 +64,9 @@ Style/Encoding: # For Ruby 1.9 as it doesn't default to UTF-8
64
64
  Style/Lambda:
65
65
  EnforcedStyle: lambda
66
66
 
67
+ Style/WordArray:
68
+ Enabled: false
69
+
67
70
  Naming/FileName:
68
71
  Exclude:
69
72
  - "ext/Rakefile"
@@ -214,14 +214,14 @@ blocks:
214
214
  value: 1.17.3
215
215
  commands:
216
216
  - "./support/bundler_wrapper exec rake test"
217
- - name: Ruby 2.0.0-p648 for resque
217
+ - name: Ruby 2.0.0-p648 for resque-1
218
218
  env_vars:
219
219
  - name: RUBY_VERSION
220
220
  value: 2.0.0-p648
221
221
  - name: GEMSET
222
- value: resque
222
+ value: resque-1
223
223
  - name: BUNDLE_GEMFILE
224
- value: gemfiles/resque.gemfile
224
+ value: gemfiles/resque-1.gemfile
225
225
  - name: _RUBYGEMS_VERSION
226
226
  value: 2.7.8
227
227
  - name: _BUNDLER_VERSION
@@ -600,20 +600,34 @@ blocks:
600
600
  value: latest
601
601
  commands:
602
602
  - "./support/bundler_wrapper exec rake test"
603
- - name: Ruby 2.6.5 for resque
603
+ - name: Ruby 2.6.5 for resque-1
604
604
  env_vars:
605
605
  - name: RUBY_VERSION
606
606
  value: 2.6.5
607
607
  - name: GEMSET
608
- value: resque
608
+ value: resque-1
609
609
  - name: BUNDLE_GEMFILE
610
- value: gemfiles/resque.gemfile
610
+ value: gemfiles/resque-1.gemfile
611
611
  - name: _RUBYGEMS_VERSION
612
612
  value: latest
613
613
  - name: _BUNDLER_VERSION
614
614
  value: 1.17.3
615
615
  commands:
616
616
  - "./support/bundler_wrapper exec rake test"
617
+ - name: Ruby 2.6.5 for resque-2
618
+ env_vars:
619
+ - name: RUBY_VERSION
620
+ value: 2.6.5
621
+ - name: GEMSET
622
+ value: resque-2
623
+ - name: BUNDLE_GEMFILE
624
+ value: gemfiles/resque-2.gemfile
625
+ - name: _RUBYGEMS_VERSION
626
+ value: latest
627
+ - name: _BUNDLER_VERSION
628
+ value: latest
629
+ commands:
630
+ - "./support/bundler_wrapper exec rake test"
617
631
  - name: Ruby 2.6.5 for sequel
618
632
  env_vars:
619
633
  - name: RUBY_VERSION
@@ -840,20 +854,34 @@ blocks:
840
854
  value: latest
841
855
  commands:
842
856
  - "./support/bundler_wrapper exec rake test"
843
- - name: Ruby 2.7.1 for resque
857
+ - name: Ruby 2.7.1 for resque-1
844
858
  env_vars:
845
859
  - name: RUBY_VERSION
846
860
  value: 2.7.1
847
861
  - name: GEMSET
848
- value: resque
862
+ value: resque-1
849
863
  - name: BUNDLE_GEMFILE
850
- value: gemfiles/resque.gemfile
864
+ value: gemfiles/resque-1.gemfile
851
865
  - name: _RUBYGEMS_VERSION
852
866
  value: latest
853
867
  - name: _BUNDLER_VERSION
854
868
  value: 1.17.3
855
869
  commands:
856
870
  - "./support/bundler_wrapper exec rake test"
871
+ - name: Ruby 2.7.1 for resque-2
872
+ env_vars:
873
+ - name: RUBY_VERSION
874
+ value: 2.7.1
875
+ - name: GEMSET
876
+ value: resque-2
877
+ - name: BUNDLE_GEMFILE
878
+ value: gemfiles/resque-2.gemfile
879
+ - name: _RUBYGEMS_VERSION
880
+ value: latest
881
+ - name: _BUNDLER_VERSION
882
+ value: latest
883
+ commands:
884
+ - "./support/bundler_wrapper exec rake test"
857
885
  - name: Ruby 2.7.1 for sequel
858
886
  env_vars:
859
887
  - name: RUBY_VERSION
@@ -3,8 +3,17 @@
3
3
  # 2.11.0
4
4
  - Track queue time regardless of namespace. Support custom namespaces. PR #602
5
5
  - Improve deprecation message from frontend error middleware. PR #620
6
- - Report Ruby environment metadata. PR #621, #627
6
+ - Report Ruby environment metadata. PR #621, #627, #619, #618
7
7
  - Refactor: Move minutely probes to their own files and modules. PR #623
8
+ - Allow custom action names in Que integration. Needed for Active Job
9
+ integration. PR #628
10
+ - Add Active Job support. Support Active Job without separate AppSignal
11
+ integration of the background job library. Add support for previously
12
+ unsupported Active Job adapters. Adapters that were previously already
13
+ supported (Sidekiq, DelayedJob and Resque) still work in this new setup.
14
+ PR #629
15
+ - Add automatic Resque integration. Remove manual Resque and Resque Active Job
16
+ integrations. PR #630
8
17
 
9
18
  # 2.10.9
10
19
  - Use http proxy if configured when downloading agent. PR #606
@@ -165,8 +165,12 @@ matrix:
165
165
  - "2.3.8"
166
166
  - "2.4.9"
167
167
  - "jruby-9.1.17.0"
168
- - gem: "resque"
168
+ - gem: "resque-1"
169
169
  bundler: "1.17.3"
170
+ - gem: "resque-2"
171
+ exclude:
172
+ ruby:
173
+ - "2.0.0-p648"
170
174
  - gem: "sequel"
171
175
  - gem: "sequel-435"
172
176
  - gem: "sinatra"
@@ -3,8 +3,15 @@ source 'https://rubygems.org'
3
3
  gem 'rails', '~> 4.2.0'
4
4
  gem 'mime-types', '~> 2.6'
5
5
 
6
- gemspec :path => '../'
6
+ ruby_version = Gem::Version.new(RUBY_VERSION)
7
+ if ruby_version < Gem::Version.new("2.3.0")
8
+ gem "sidekiq", "~> 4.0"
9
+ else
10
+ gem "sidekiq"
11
+ end
7
12
 
8
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.1.0")
13
+ if ruby_version < Gem::Version.new("2.1.0")
9
14
  gem 'nokogiri', '~> 1.6.0'
10
15
  end
16
+
17
+ gemspec :path => '../'
@@ -1,5 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gem 'rails', '~> 5.0.0'
4
+ gem "sidekiq"
4
5
 
5
6
  gemspec :path => '../'
@@ -1,5 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gem 'rails', '~> 5.1.0'
4
+ gem "sidekiq"
4
5
 
5
6
  gemspec :path => '../'
@@ -1,5 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gem 'rails', '~> 5.2.0'
4
+ gem "sidekiq"
4
5
 
5
6
  gemspec :path => '../'
@@ -1,5 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gem 'rails', '~> 6.0.0'
4
+ gem "sidekiq"
4
5
 
5
6
  gemspec :path => '../'
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'resque', "~> 1.27.0"
4
+ gem 'sinatra'
5
+ gem 'mime-types', '~> 2.6'
6
+
7
+ gemspec :path => '../'
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'resque'
3
+ gem 'resque', "~> 2.0"
4
4
  gem 'sinatra'
5
5
  gem 'mime-types', '~> 2.6'
6
6
 
@@ -73,6 +73,7 @@ module Appsignal
73
73
  end
74
74
 
75
75
  require "appsignal/hooks/action_cable"
76
+ require "appsignal/hooks/active_job"
76
77
  require "appsignal/hooks/active_support_notifications"
77
78
  require "appsignal/hooks/celluloid"
78
79
  require "appsignal/hooks/delayed_job"
@@ -81,6 +82,7 @@ require "appsignal/hooks/passenger"
81
82
  require "appsignal/hooks/puma"
82
83
  require "appsignal/hooks/rake"
83
84
  require "appsignal/hooks/redis"
85
+ require "appsignal/hooks/resque"
84
86
  require "appsignal/hooks/sequel"
85
87
  require "appsignal/hooks/shoryuken"
86
88
  require "appsignal/hooks/sidekiq"
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appsignal
4
+ class Hooks
5
+ # @api private
6
+ class ActiveJobHook < Appsignal::Hooks::Hook
7
+ register :active_job
8
+
9
+ def dependencies_present?
10
+ defined?(::ActiveJob)
11
+ end
12
+
13
+ def install
14
+ ::ActiveJob::Base
15
+ .extend ::Appsignal::Hooks::ActiveJobHook::ActiveJobClassInstrumentation
16
+ end
17
+
18
+ # @todo Add queue time support for Rails 6's enqueued_at. For both
19
+ # existing and new transactions.
20
+ module ActiveJobClassInstrumentation
21
+ def execute(job)
22
+ current_transaction = Appsignal::Transaction.current
23
+ transaction =
24
+ if current_transaction.nil_transaction?
25
+ # No standalone integration started before ActiveJob integration.
26
+ # We don't have a separate integration for this QueueAdapter like
27
+ # we do for Sidekiq.
28
+ #
29
+ # Prefer job_id from provider, instead of ActiveJob's internal ID.
30
+ Appsignal::Transaction.create(
31
+ job["provider_job_id"] || job["job_id"],
32
+ Appsignal::Transaction::BACKGROUND_JOB,
33
+ Appsignal::Transaction::GenericRequest.new({})
34
+ )
35
+ else
36
+ current_transaction
37
+ end
38
+
39
+ super
40
+ rescue Exception => exception # rubocop:disable Lint/RescueException
41
+ transaction.set_error(exception)
42
+ raise exception
43
+ ensure
44
+ if transaction
45
+ transaction.params =
46
+ Appsignal::Utils::HashSanitizer.sanitize(
47
+ job["arguments"],
48
+ Appsignal.config[:filter_parameters]
49
+ )
50
+
51
+ tags = { :queue => job["queue_name"] }
52
+ provider_job_id = job["provider_job_id"]
53
+ tags[:provider_job_id] = provider_job_id if provider_job_id
54
+ transaction.set_tags(tags)
55
+
56
+ transaction.set_action_if_nil(ActiveJobHelpers.action_name(job))
57
+ enqueued_at = job["enqueued_at"]
58
+ if enqueued_at # Present in Rails 6 and up
59
+ transaction.set_queue_start((Time.parse(enqueued_at).to_f * 1_000).to_i)
60
+ end
61
+
62
+ if current_transaction.nil_transaction?
63
+ # Only complete transaction if ActiveJob is not wrapped in
64
+ # another supported integration, such as Sidekiq.
65
+ Appsignal::Transaction.complete_current!
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ module ActiveJobHelpers
72
+ ACTION_MAILER_CLASSES = [
73
+ "ActionMailer::DeliveryJob",
74
+ "ActionMailer::Parameterized::DeliveryJob",
75
+ "ActionMailer::MailDeliveryJob"
76
+ ].freeze
77
+
78
+ def self.action_name(job)
79
+ case job["job_class"]
80
+ when *ACTION_MAILER_CLASSES
81
+ job["arguments"][0..1].join("#")
82
+ else
83
+ "#{job["job_class"]}#perform"
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appsignal
4
+ class Hooks
5
+ # @api private
6
+ class ResqueHook < Appsignal::Hooks::Hook
7
+ register :resque
8
+
9
+ def dependencies_present?
10
+ defined?(::Resque)
11
+ end
12
+
13
+ def install
14
+ Resque::Job.class_eval do
15
+ alias_method :perform_without_appsignal, :perform
16
+
17
+ def perform
18
+ transaction = Appsignal::Transaction.create(
19
+ SecureRandom.uuid,
20
+ Appsignal::Transaction::BACKGROUND_JOB,
21
+ Appsignal::Transaction::GenericRequest.new({})
22
+ )
23
+
24
+ Appsignal.instrument "perform.resque" do
25
+ perform_without_appsignal
26
+ end
27
+ rescue Exception => exception # rubocop:disable Lint/RescueException
28
+ transaction.set_error(exception)
29
+ raise exception
30
+ ensure
31
+ if transaction
32
+ transaction.set_action_if_nil("#{payload["class"]}#perform")
33
+ args =
34
+ Appsignal::Utils::HashSanitizer.sanitize(
35
+ ResqueHelpers.arguments(payload),
36
+ Appsignal.config[:filter_parameters]
37
+ )
38
+ transaction.params = args if args
39
+ transaction.set_tags("queue" => queue)
40
+
41
+ Appsignal::Transaction.complete_current!
42
+ end
43
+ Appsignal.stop("resque")
44
+ end
45
+ end
46
+ end
47
+
48
+ class ResqueHelpers
49
+ def self.arguments(payload)
50
+ case payload["class"]
51
+ when "ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper"
52
+ nil # Set in the ActiveJob integration
53
+ else
54
+ payload["args"]
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -27,8 +27,7 @@ module Appsignal
27
27
  class SidekiqPlugin # rubocop:disable Metrics/ClassLength
28
28
  include Appsignal::Hooks::Helpers
29
29
 
30
- UNKNOWN_ACTION_NAME = "unknown".freeze
31
- JOB_KEYS = %w[
30
+ EXCLUDED_JOB_KEYS = %w[
32
31
  args backtrace class created_at enqueued_at error_backtrace error_class
33
32
  error_message failed_at jid retried_at retry wrapped
34
33
  ].freeze
@@ -55,7 +54,10 @@ module Appsignal
55
54
  ensure
56
55
  if transaction
57
56
  transaction.set_action_if_nil(formatted_action_name(item))
58
- transaction.params = filtered_arguments(item)
57
+
58
+ params = filtered_arguments(item)
59
+ transaction.params = params if params
60
+
59
61
  formatted_metadata(item).each do |key, value|
60
62
  transaction.set_metadata key, value
61
63
  end
@@ -81,16 +83,20 @@ module Appsignal
81
83
 
82
84
  def formatted_action_name(job)
83
85
  sidekiq_action_name = parse_action_name(job)
86
+ return unless sidekiq_action_name
87
+
84
88
  complete_action = sidekiq_action_name =~ /\.|#/
85
- if complete_action || sidekiq_action_name == UNKNOWN_ACTION_NAME
86
- return sidekiq_action_name
87
- end
89
+ return sidekiq_action_name if complete_action
90
+
88
91
  "#{sidekiq_action_name}#perform"
89
92
  end
90
93
 
91
94
  def filtered_arguments(job)
95
+ arguments = parse_arguments(job)
96
+ return unless arguments
97
+
92
98
  Appsignal::Utils::HashSanitizer.sanitize(
93
- parse_arguments(job),
99
+ arguments,
94
100
  Appsignal.config[:filter_parameters]
95
101
  )
96
102
  end
@@ -98,7 +104,8 @@ module Appsignal
98
104
  def formatted_metadata(item)
99
105
  {}.tap do |hash|
100
106
  (item || {}).each do |key, value|
101
- next if JOB_KEYS.include?(key)
107
+ next if EXCLUDED_JOB_KEYS.include?(key)
108
+
102
109
  hash[key] = truncate(string_or_inspect(value))
103
110
  end
104
111
  end
@@ -117,81 +124,11 @@ module Appsignal
117
124
  safe_load(args[0], job_class) do |target, method, _|
118
125
  "#{target}.#{method}"
119
126
  end
120
- when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
121
- wrapped_job = job["wrapped"]
122
- if wrapped_job
123
- parse_active_job_action_name_from_wrapped job
124
- else
125
- parse_active_job_action_name_from_arguments job
126
- end
127
127
  else
128
128
  job_class
129
129
  end
130
130
  end
131
131
 
132
- # Return the ActiveJob wrapped job name.
133
- #
134
- # Returns "unknown" if no acceptable job class name could be found.
135
- #
136
- # @example Payload with "wrapped" value
137
- # {
138
- # "class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
139
- # "wrapped" => "MyWrappedJob",
140
- # # ...
141
- # }
142
- def parse_active_job_action_name_from_wrapped(job)
143
- job_class = job["wrapped"]
144
- case job_class
145
- when "ActionMailer::DeliveryJob"
146
- extract_action_mailer_name job["args"]
147
- when String
148
- job_class
149
- else
150
- unknown_action_name_for job
151
- end
152
- end
153
-
154
- # Return the ActiveJob job name based on the job's arguments.
155
- #
156
- # Returns "unknown" if no acceptable job class name could be found.
157
- #
158
- # @example Payload without "wrapped" value
159
- # {
160
- # "class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
161
- # "args" => [{
162
- # "job_class" => "MyWrappedJob",
163
- # # ...
164
- # }]
165
- # # ...
166
- # }
167
- def parse_active_job_action_name_from_arguments(job)
168
- args = job.fetch("args", [])
169
- first_arg = args[0]
170
- if first_arg == "ActionMailer::DeliveryJob"
171
- extract_action_mailer_name args
172
- elsif active_job_payload?(first_arg)
173
- first_arg["job_class"]
174
- else
175
- unknown_action_name_for job
176
- end
177
- end
178
-
179
- # Checks if the first argument in the job payload is an ActiveJob payload.
180
- def active_job_payload?(arg)
181
- arg.is_a?(Hash) && arg["job_class"].is_a?(String)
182
- end
183
-
184
- def unknown_action_name_for(job)
185
- Appsignal.logger.debug \
186
- "Unable to determine an action name from Sidekiq payload: #{job}"
187
- UNKNOWN_ACTION_NAME
188
- end
189
-
190
- def extract_action_mailer_name(args)
191
- # Returns in format: MailerClass#mailer_method
192
- args[0]["arguments"][0..1].join("#")
193
- end
194
-
195
132
  # Based on: https://github.com/mperham/sidekiq/blob/63ee43353bd3b753beb0233f64865e658abeb1c3/lib/sidekiq/api.rb#L336-L358
196
133
  def parse_arguments(job)
197
134
  args = job.fetch("args", [])
@@ -201,20 +138,7 @@ module Appsignal
201
138
  arg
202
139
  end
203
140
  when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
204
- is_wrapped = job["wrapped"]
205
- first_arg = args[0]
206
- job_args =
207
- if is_wrapped || active_job_payload?(first_arg)
208
- first_arg["arguments"]
209
- else
210
- []
211
- end
212
- if (is_wrapped || first_arg) == "ActionMailer::DeliveryJob"
213
- # Remove MailerClass, mailer_method and "deliver_now"
214
- job_args.drop(3)
215
- else
216
- job_args
217
- end
141
+ nil # Set in the ActiveJob integration
218
142
  else
219
143
  # Sidekiq Enterprise argument encryption.
220
144
  # More information: https://github.com/mperham/sidekiq/wiki/Ent-Encryption