appsignal 2.11.0.alpha.1-java → 2.11.0.beta.4-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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/.semaphore/semaphore.yml +75 -61
  4. data/CHANGELOG.md +21 -1
  5. data/build_matrix.yml +13 -7
  6. data/ext/agent.yml +19 -19
  7. data/gemfiles/padrino.gemfile +2 -2
  8. data/gemfiles/rails-4.2.gemfile +9 -2
  9. data/gemfiles/rails-5.0.gemfile +1 -0
  10. data/gemfiles/rails-5.1.gemfile +1 -0
  11. data/gemfiles/rails-5.2.gemfile +1 -0
  12. data/gemfiles/rails-6.0.gemfile +1 -0
  13. data/gemfiles/resque-1.gemfile +7 -0
  14. data/gemfiles/{resque.gemfile → resque-2.gemfile} +1 -1
  15. data/lib/appsignal/hooks.rb +2 -0
  16. data/lib/appsignal/hooks/active_job.rb +114 -0
  17. data/lib/appsignal/hooks/puma.rb +2 -58
  18. data/lib/appsignal/hooks/resque.rb +60 -0
  19. data/lib/appsignal/hooks/sidekiq.rb +19 -192
  20. data/lib/appsignal/integrations/delayed_job_plugin.rb +1 -1
  21. data/lib/appsignal/integrations/que.rb +1 -1
  22. data/lib/appsignal/integrations/resque.rb +9 -12
  23. data/lib/appsignal/integrations/resque_active_job.rb +9 -32
  24. data/lib/appsignal/probes/puma.rb +61 -0
  25. data/lib/appsignal/probes/sidekiq.rb +102 -0
  26. data/lib/appsignal/rack/js_exception_catcher.rb +5 -2
  27. data/lib/appsignal/transaction.rb +10 -0
  28. data/lib/appsignal/utils/deprecation_message.rb +5 -1
  29. data/lib/appsignal/version.rb +1 -1
  30. data/lib/puma/plugin/appsignal.rb +2 -1
  31. data/spec/lib/appsignal/hooks/activejob_spec.rb +548 -0
  32. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +3 -14
  33. data/spec/lib/appsignal/hooks/puma_spec.rb +2 -181
  34. data/spec/lib/appsignal/hooks/resque_spec.rb +185 -0
  35. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +297 -549
  36. data/spec/lib/appsignal/integrations/padrino_spec.rb +1 -1
  37. data/spec/lib/appsignal/integrations/que_spec.rb +25 -6
  38. data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +20 -179
  39. data/spec/lib/appsignal/integrations/resque_spec.rb +20 -85
  40. data/spec/lib/appsignal/probes/puma_spec.rb +180 -0
  41. data/spec/lib/appsignal/probes/sidekiq_spec.rb +204 -0
  42. data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +9 -4
  43. data/spec/lib/appsignal/transaction_spec.rb +5 -7
  44. data/spec/lib/puma/appsignal_spec.rb +1 -1
  45. data/spec/support/helpers/action_mailer_helpers.rb +25 -0
  46. data/spec/support/helpers/dependency_helper.rb +9 -2
  47. data/spec/support/helpers/transaction_helpers.rb +6 -0
  48. data/spec/support/stubs/sidekiq/api.rb +2 -2
  49. metadata +18 -3
@@ -0,0 +1,204 @@
1
+ require "appsignal/probes/sidekiq"
2
+
3
+ describe Appsignal::Probes::SidekiqProbe do
4
+ describe "#call" do
5
+ let(:probe) { described_class.new }
6
+ let(:redis_hostname) { "localhost" }
7
+ let(:expected_default_tags) { { :hostname => "localhost" } }
8
+ before do
9
+ Appsignal.config = project_fixture_config
10
+ module SidekiqMock
11
+ def self.redis_info
12
+ {
13
+ "connected_clients" => 2,
14
+ "used_memory" => 1024,
15
+ "used_memory_rss" => 512
16
+ }
17
+ end
18
+
19
+ def self.redis
20
+ yield Client.new
21
+ end
22
+
23
+ class Client
24
+ def connection
25
+ { :host => "localhost" }
26
+ end
27
+ end
28
+
29
+ class Stats
30
+ class << self
31
+ attr_reader :calls
32
+
33
+ def count_call
34
+ @calls ||= -1
35
+ @calls += 1
36
+ end
37
+ end
38
+
39
+ def workers_size
40
+ # First method called, so count it towards a call
41
+ self.class.count_call
42
+ 24
43
+ end
44
+
45
+ def processes_size
46
+ 25
47
+ end
48
+
49
+ # Return two different values for two separate calls.
50
+ # This allows us to test the delta of the value send as a gauge.
51
+ def processed
52
+ [10, 15][self.class.calls]
53
+ end
54
+
55
+ # Return two different values for two separate calls.
56
+ # This allows us to test the delta of the value send as a gauge.
57
+ def failed
58
+ [10, 13][self.class.calls]
59
+ end
60
+
61
+ def retry_size
62
+ 12
63
+ end
64
+
65
+ # Return two different values for two separate calls.
66
+ # This allows us to test the delta of the value send as a gauge.
67
+ def dead_size
68
+ [10, 12][self.class.calls]
69
+ end
70
+
71
+ def scheduled_size
72
+ 14
73
+ end
74
+
75
+ def enqueued
76
+ 15
77
+ end
78
+ end
79
+
80
+ class Queue
81
+ Queue = Struct.new(:name, :size, :latency)
82
+
83
+ def self.all
84
+ [
85
+ Queue.new("default", 10, 12),
86
+ Queue.new("critical", 1, 2)
87
+ ]
88
+ end
89
+ end
90
+ end
91
+ stub_const("Sidekiq", SidekiqMock)
92
+ end
93
+ after { Object.send(:remove_const, :SidekiqMock) }
94
+
95
+ describe ".dependencies_present?" do
96
+ before do
97
+ stub_const("Redis::VERSION", version)
98
+ end
99
+
100
+ context "when Redis version is < 3.3.5" do
101
+ let(:version) { "3.3.4" }
102
+
103
+ it "does not start probe" do
104
+ expect(described_class.dependencies_present?).to be_falsy
105
+ end
106
+ end
107
+
108
+ context "when Redis version is >= 3.3.5" do
109
+ let(:version) { "3.3.5" }
110
+
111
+ it "does not start probe" do
112
+ expect(described_class.dependencies_present?).to be_truthy
113
+ end
114
+ end
115
+ end
116
+
117
+ it "loads Sidekiq::API" do
118
+ # Hide the Sidekiq constant if it was already loaded. It will be
119
+ # redefined by loading "sidekiq/api" in the probe.
120
+ hide_const "Sidekiq::Stats"
121
+
122
+ expect(defined?(Sidekiq::Stats)).to be_falsy
123
+ probe
124
+ expect(defined?(Sidekiq::Stats)).to be_truthy
125
+ end
126
+
127
+ it "logs config on initialize" do
128
+ log = capture_logs { probe }
129
+ expect(log).to contains_log(:debug, "Initializing Sidekiq probe\n")
130
+ end
131
+
132
+ it "logs used hostname on call once" do
133
+ log = capture_logs { probe.call }
134
+ expect(log).to contains_log(
135
+ :debug,
136
+ %(Sidekiq probe: Using Redis server hostname "localhost" as hostname)
137
+ )
138
+ log = capture_logs { probe.call }
139
+ # Match more logs with incompelete message
140
+ expect(log).to_not contains_log(:debug, %(Sidekiq probe: ))
141
+ end
142
+
143
+ it "collects custom metrics" do
144
+ expect_gauge("worker_count", 24).twice
145
+ expect_gauge("process_count", 25).twice
146
+ expect_gauge("connection_count", 2).twice
147
+ expect_gauge("memory_usage", 1024).twice
148
+ expect_gauge("memory_usage_rss", 512).twice
149
+ expect_gauge("job_count", 5, :status => :processed) # Gauge delta
150
+ expect_gauge("job_count", 3, :status => :failed) # Gauge delta
151
+ expect_gauge("job_count", 12, :status => :retry_queue).twice
152
+ expect_gauge("job_count", 2, :status => :died) # Gauge delta
153
+ expect_gauge("job_count", 14, :status => :scheduled).twice
154
+ expect_gauge("job_count", 15, :status => :enqueued).twice
155
+ expect_gauge("queue_length", 10, :queue => "default").twice
156
+ expect_gauge("queue_latency", 12_000, :queue => "default").twice
157
+ expect_gauge("queue_length", 1, :queue => "critical").twice
158
+ expect_gauge("queue_latency", 2_000, :queue => "critical").twice
159
+ # Call probe twice so we can calculate the delta for some gauge values
160
+ probe.call
161
+ probe.call
162
+ end
163
+
164
+ context "when `redis_info` is not defined" do
165
+ before do
166
+ allow(Sidekiq).to receive(:respond_to?).with(:redis_info).and_return(false)
167
+ end
168
+
169
+ it "does not collect redis metrics" do
170
+ expect_gauge("connection_count", 2).never
171
+ expect_gauge("memory_usage", 1024).never
172
+ expect_gauge("memory_usage_rss", 512).never
173
+ probe.call
174
+ end
175
+ end
176
+
177
+ context "when hostname is configured for probe" do
178
+ let(:redis_hostname) { "my_redis_server" }
179
+ let(:probe) { described_class.new(:hostname => redis_hostname) }
180
+
181
+ it "uses the redis hostname for the hostname tag" do
182
+ allow(Appsignal).to receive(:set_gauge).and_call_original
183
+ log = capture_logs { probe }
184
+ expect(log).to contains_log(
185
+ :debug,
186
+ %(Initializing Sidekiq probe with config: {:hostname=>"#{redis_hostname}"})
187
+ )
188
+ log = capture_logs { probe.call }
189
+ expect(log).to contains_log(
190
+ :debug,
191
+ "Sidekiq probe: Using hostname config option #{redis_hostname.inspect} as hostname"
192
+ )
193
+ expect(Appsignal).to have_received(:set_gauge)
194
+ .with(anything, anything, :hostname => redis_hostname).at_least(:once)
195
+ end
196
+ end
197
+
198
+ def expect_gauge(key, value, tags = {})
199
+ expect(Appsignal).to receive(:set_gauge)
200
+ .with("sidekiq_#{key}", value, expected_default_tags.merge(tags))
201
+ .and_call_original
202
+ end
203
+ end
204
+ end
@@ -4,9 +4,12 @@ describe Appsignal::Rack::JSExceptionCatcher do
4
4
  let(:config_options) { { :enable_frontend_error_catching => true } }
5
5
  let(:config) { project_fixture_config("production", config_options) }
6
6
  let(:deprecation_message) do
7
- "The Appsignal::Rack::JSExceptionCatcher is deprecated. " \
8
- "Please use the official AppSignal JavaScript integration instead. " \
9
- "https://docs.appsignal.com/front-end/"
7
+ "The Appsignal::Rack::JSExceptionCatcher is " \
8
+ "deprecated and will be removed in a future version. Please use " \
9
+ "the official AppSignal JavaScript integration by disabling " \
10
+ "`enable_frontend_error_catching` in your configuration and " \
11
+ "installing AppSignal for JavaScript instead. " \
12
+ "(https://docs.appsignal.com/front-end/)"
10
13
  end
11
14
  before { Appsignal.config = config }
12
15
 
@@ -32,7 +35,9 @@ describe Appsignal::Rack::JSExceptionCatcher do
32
35
 
33
36
  describe "#call" do
34
37
  let(:catcher) do
35
- silence { Appsignal::Rack::JSExceptionCatcher.new(app, options) }
38
+ silence :allowed => ["enable_frontend_error_catching"] do
39
+ Appsignal::Rack::JSExceptionCatcher.new(app, options)
40
+ end
36
41
  end
37
42
  after { catcher.call(env) }
38
43
 
@@ -473,22 +473,20 @@ describe Appsignal::Transaction do
473
473
  end
474
474
  end
475
475
 
476
- describe "set_queue_start" do
477
- it "should set the queue start in extension" do
478
- expect(transaction.ext).to receive(:set_queue_start).with(
479
- 10.0
480
- ).once
476
+ describe "#set_queue_start" do
477
+ it "sets the queue start in extension" do
478
+ expect(transaction.ext).to receive(:set_queue_start).with(10.0).once
481
479
 
482
480
  transaction.set_queue_start(10.0)
483
481
  end
484
482
 
485
- it "should not set the queue start in extension when value is nil" do
483
+ it "does not set the queue start in extension when value is nil" do
486
484
  expect(transaction.ext).to_not receive(:set_queue_start)
487
485
 
488
486
  transaction.set_queue_start(nil)
489
487
  end
490
488
 
491
- it "should not raise an error when the queue start is too big" do
489
+ it "does not raise an error when the queue start is too big" do
492
490
  expect(transaction.ext).to receive(:set_queue_start).and_raise(RangeError)
493
491
 
494
492
  expect(Appsignal.logger).to receive(:warn).with("Queue start value 10 is too big")
@@ -62,7 +62,7 @@ RSpec.describe "Puma plugin" do
62
62
  expect(launcher.events.on_booted).to_not be_nil
63
63
 
64
64
  launcher.events.on_booted.call
65
- expect(Appsignal::Minutely.probes[:puma]).to eql(Appsignal::Hooks::PumaProbe)
65
+ expect(Appsignal::Minutely.probes[:puma]).to eql(Appsignal::Probes::PumaProbe)
66
66
 
67
67
  # Minutely probes started and called
68
68
  wait_for("enough probe calls") { probe.calls >= 2 }
@@ -0,0 +1,25 @@
1
+ module ActionMailerHelpers
2
+ def perform_action_mailer(mailer, method, args = nil)
3
+ if DependencyHelper.rails_version >= Gem::Version.new("5.2.0")
4
+ case args
5
+ when Array
6
+ mailer.send(method, *args).deliver_later
7
+ when Hash
8
+ mailer.with(args).send(method).deliver_later
9
+ when NilClass
10
+ mailer.send(method).deliver_later
11
+ else
12
+ raise "Unknown scenario for arguments: #{args}"
13
+ end
14
+ else
15
+ # Rails 5.1 and lower
16
+ mailer_object =
17
+ if args
18
+ mailer.send(method, *args)
19
+ else
20
+ mailer.send(method)
21
+ end
22
+ mailer_object.deliver_later
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,10 @@
1
1
  module DependencyHelper
2
2
  module_function
3
3
 
4
+ def ruby_version
5
+ Gem::Version.new(RUBY_VERSION)
6
+ end
7
+
4
8
  def running_jruby?
5
9
  defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
6
10
  end
@@ -10,8 +14,11 @@ module DependencyHelper
10
14
  end
11
15
 
12
16
  def rails6_present?
13
- rails_present? &&
14
- Gem.loaded_specs["rails"].version >= Gem::Version.new("6.0.0")
17
+ rails_present? && rails_version >= Gem::Version.new("6.0.0")
18
+ end
19
+
20
+ def rails_version
21
+ Gem.loaded_specs["rails"].version
15
22
  end
16
23
 
17
24
  def sequel_present?
@@ -44,6 +44,12 @@ module TransactionHelpers
44
44
  created_transactions.last
45
45
  end
46
46
 
47
+ # Set current transaction manually.
48
+ # Cleared by {clear_current_transaction!}
49
+ def set_current_transaction(transaction) # rubocop:disable Style/AccessorMethodName
50
+ Thread.current[:appsignal_transaction] = transaction
51
+ end
52
+
47
53
  # Use when {Appsignal::Transaction.clear_current_transaction!} is stubbed to
48
54
  # clear the current transaction on the current thread.
49
55
  def clear_current_transaction!
@@ -1,4 +1,4 @@
1
- class Sidekiq
2
- class API
1
+ module Sidekiq
2
+ class Stats
3
3
  end
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appsignal
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.11.0.alpha.1
4
+ version: 2.11.0.beta.4
5
5
  platform: java
6
6
  authors:
7
7
  - Robert Beekman
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-06-29 00:00:00.000000000 Z
13
+ date: 2020-07-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -186,7 +186,8 @@ files:
186
186
  - gemfiles/rails-5.1.gemfile
187
187
  - gemfiles/rails-5.2.gemfile
188
188
  - gemfiles/rails-6.0.gemfile
189
- - gemfiles/resque.gemfile
189
+ - gemfiles/resque-1.gemfile
190
+ - gemfiles/resque-2.gemfile
190
191
  - gemfiles/sequel-435.gemfile
191
192
  - gemfiles/sequel.gemfile
192
193
  - gemfiles/sinatra.gemfile
@@ -220,6 +221,7 @@ files:
220
221
  - lib/appsignal/helpers/metrics.rb
221
222
  - lib/appsignal/hooks.rb
222
223
  - lib/appsignal/hooks/action_cable.rb
224
+ - lib/appsignal/hooks/active_job.rb
223
225
  - lib/appsignal/hooks/active_support_notifications.rb
224
226
  - lib/appsignal/hooks/celluloid.rb
225
227
  - lib/appsignal/hooks/data_mapper.rb
@@ -231,6 +233,7 @@ files:
231
233
  - lib/appsignal/hooks/que.rb
232
234
  - lib/appsignal/hooks/rake.rb
233
235
  - lib/appsignal/hooks/redis.rb
236
+ - lib/appsignal/hooks/resque.rb
234
237
  - lib/appsignal/hooks/sequel.rb
235
238
  - lib/appsignal/hooks/shoryuken.rb
236
239
  - lib/appsignal/hooks/sidekiq.rb
@@ -255,6 +258,8 @@ files:
255
258
  - lib/appsignal/logger.rb
256
259
  - lib/appsignal/marker.rb
257
260
  - lib/appsignal/minutely.rb
261
+ - lib/appsignal/probes/puma.rb
262
+ - lib/appsignal/probes/sidekiq.rb
258
263
  - lib/appsignal/rack/generic_instrumentation.rb
259
264
  - lib/appsignal/rack/js_exception_catcher.rb
260
265
  - lib/appsignal/rack/rails_instrumentation.rb
@@ -303,6 +308,7 @@ files:
303
308
  - spec/lib/appsignal/garbage_collection_profiler_spec.rb
304
309
  - spec/lib/appsignal/hooks/action_cable_spec.rb
305
310
  - spec/lib/appsignal/hooks/active_support_notifications_spec.rb
311
+ - spec/lib/appsignal/hooks/activejob_spec.rb
306
312
  - spec/lib/appsignal/hooks/celluloid_spec.rb
307
313
  - spec/lib/appsignal/hooks/data_mapper_spec.rb
308
314
  - spec/lib/appsignal/hooks/delayed_job_spec.rb
@@ -313,6 +319,7 @@ files:
313
319
  - spec/lib/appsignal/hooks/que_spec.rb
314
320
  - spec/lib/appsignal/hooks/rake_spec.rb
315
321
  - spec/lib/appsignal/hooks/redis_spec.rb
322
+ - spec/lib/appsignal/hooks/resque_spec.rb
316
323
  - spec/lib/appsignal/hooks/sequel_spec.rb
317
324
  - spec/lib/appsignal/hooks/shoryuken_spec.rb
318
325
  - spec/lib/appsignal/hooks/sidekiq_spec.rb
@@ -334,6 +341,8 @@ files:
334
341
  - spec/lib/appsignal/logger_spec.rb
335
342
  - spec/lib/appsignal/marker_spec.rb
336
343
  - spec/lib/appsignal/minutely_spec.rb
344
+ - spec/lib/appsignal/probes/puma_spec.rb
345
+ - spec/lib/appsignal/probes/sidekiq_spec.rb
337
346
  - spec/lib/appsignal/rack/generic_instrumentation_spec.rb
338
347
  - spec/lib/appsignal/rack/js_exception_catcher_spec.rb
339
348
  - spec/lib/appsignal/rack/rails_instrumentation_spec.rb
@@ -358,6 +367,7 @@ files:
358
367
  - spec/support/fixtures/projects/valid/config/environments/test.rb
359
368
  - spec/support/fixtures/projects/valid/log/.gitkeep
360
369
  - spec/support/fixtures/uploaded_file.txt
370
+ - spec/support/helpers/action_mailer_helpers.rb
361
371
  - spec/support/helpers/api_request_helper.rb
362
372
  - spec/support/helpers/cli_helpers.rb
363
373
  - spec/support/helpers/config_helpers.rb
@@ -445,6 +455,7 @@ test_files:
445
455
  - spec/lib/appsignal/garbage_collection_profiler_spec.rb
446
456
  - spec/lib/appsignal/hooks/action_cable_spec.rb
447
457
  - spec/lib/appsignal/hooks/active_support_notifications_spec.rb
458
+ - spec/lib/appsignal/hooks/activejob_spec.rb
448
459
  - spec/lib/appsignal/hooks/celluloid_spec.rb
449
460
  - spec/lib/appsignal/hooks/data_mapper_spec.rb
450
461
  - spec/lib/appsignal/hooks/delayed_job_spec.rb
@@ -455,6 +466,7 @@ test_files:
455
466
  - spec/lib/appsignal/hooks/que_spec.rb
456
467
  - spec/lib/appsignal/hooks/rake_spec.rb
457
468
  - spec/lib/appsignal/hooks/redis_spec.rb
469
+ - spec/lib/appsignal/hooks/resque_spec.rb
458
470
  - spec/lib/appsignal/hooks/sequel_spec.rb
459
471
  - spec/lib/appsignal/hooks/shoryuken_spec.rb
460
472
  - spec/lib/appsignal/hooks/sidekiq_spec.rb
@@ -476,6 +488,8 @@ test_files:
476
488
  - spec/lib/appsignal/logger_spec.rb
477
489
  - spec/lib/appsignal/marker_spec.rb
478
490
  - spec/lib/appsignal/minutely_spec.rb
491
+ - spec/lib/appsignal/probes/puma_spec.rb
492
+ - spec/lib/appsignal/probes/sidekiq_spec.rb
479
493
  - spec/lib/appsignal/rack/generic_instrumentation_spec.rb
480
494
  - spec/lib/appsignal/rack/js_exception_catcher_spec.rb
481
495
  - spec/lib/appsignal/rack/rails_instrumentation_spec.rb
@@ -500,6 +514,7 @@ test_files:
500
514
  - spec/support/fixtures/projects/valid/config/environments/test.rb
501
515
  - spec/support/fixtures/projects/valid/log/.gitkeep
502
516
  - spec/support/fixtures/uploaded_file.txt
517
+ - spec/support/helpers/action_mailer_helpers.rb
503
518
  - spec/support/helpers/api_request_helper.rb
504
519
  - spec/support/helpers/cli_helpers.rb
505
520
  - spec/support/helpers/config_helpers.rb