appsignal 2.9.16-java → 2.9.17-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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f1973fb0dee0ffa4bf34c5d47687b466ecb10b29143ee58dcbf6ee10975650b
4
- data.tar.gz: 2be9da926d855415ee5c90ef33fe6726585bdf0a200569ed3647ad8865f0e2ff
3
+ metadata.gz: f02b2d17e2a2de9e6d2552c8f4fb4ff0d5d2335ec7bcbb17eaa2967c49c0945f
4
+ data.tar.gz: c50aa8e015192af38f991a38211cf29969d44d96184972a4f345e01451e5962a
5
5
  SHA512:
6
- metadata.gz: 7e549806bdd2cbc8bdec815053259137f821ff9a57de1015d249e9db839a23c60b36f8c72dd3847a91e44f57cdec2a5ca0f0bb1591850517308c6ac763af54da
7
- data.tar.gz: 2b61cc4e4f2398b629a3a2d9f4d23ccffa504a400757541c409ec4ae00be2f5e2725ac17f0d5b8fbb2feaeb966b8c6c235f4475cd2dd1ddc0f36d949c24a9a2d
6
+ metadata.gz: 76f2fd7223f354b00104dfc38a690e38fe3a5c01ce89a1996916b3ceea3f29fcc45b80c95e0fc63f88a99246ce251070ec53e30c316f19d1789b09d71a25f6ef
7
+ data.tar.gz: 79e193ac1d6d5e5c84cb192c59505351fdf372e5840d9f9403df2eeeef62619d88961b4acce27248874480455123fe29b62ee8cb17e039c45b8e0c1e01ea6001
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.9.17
4
+ - Handle missing file and load errors from `application.rb` in `appsignal
5
+ install` for Rails apps. PR #568
6
+ - Support minutely probes for Puma in clustered mode. PR #570
7
+ See the installation instructions for the Puma plugin:
8
+ https://docs.appsignal.com/ruby/integrations/puma.html
9
+
3
10
  ## 2.9.16
4
11
  - Check set_error arguments for Exceptions. PR #565
5
12
  - Bump agent to v-1d8917f - commit 737d6b1b8fc9cd2c0564050bb04246d9267dceb7
@@ -75,18 +75,39 @@ module Appsignal
75
75
  def install_for_rails(config)
76
76
  puts "Installing for Ruby on Rails"
77
77
 
78
- require File.expand_path(File.join(Dir.pwd, "config/application.rb"))
78
+ name_overwritten = configure_rails_app_name(config)
79
+ configure(config, rails_environments, name_overwritten)
80
+ done_notice
81
+ end
79
82
 
80
- config[:name] = Appsignal::Utils::RailsHelper.detected_rails_app_name
81
- name_overwritten = yes_or_no(" Your app's name is: '#{config[:name]}' \n Do you want to change how this is displayed in AppSignal? (y/n): ")
82
- puts
83
- if name_overwritten
84
- config[:name] = required_input(" Choose app's display name: ")
83
+ def configure_rails_app_name(config)
84
+ loaded =
85
+ begin
86
+ load Appsignal::Utils::RailsHelper.application_config_path
87
+ true
88
+ rescue LoadError, StandardError
89
+ false
90
+ end
91
+
92
+ name_overwritten = false
93
+ if loaded
94
+ config[:name] = Appsignal::Utils::RailsHelper.detected_rails_app_name
95
+ puts
96
+ name_overwritten = yes_or_no(
97
+ " Your app's name is: '#{config[:name]}' \n " \
98
+ "Do you want to change how this is displayed in AppSignal? " \
99
+ "(y/n): "
100
+ )
101
+ if name_overwritten
102
+ config[:name] = required_input(" Choose app's display name: ")
103
+ puts
104
+ end
105
+ else
106
+ puts " Unable to automatically detect your Rails app's name."
107
+ config[:name] = required_input(" Choose your app's display name for AppSignal.com: ")
85
108
  puts
86
109
  end
87
-
88
- configure(config, rails_environments, name_overwritten)
89
- done_notice
110
+ name_overwritten
90
111
  end
91
112
 
92
113
  def install_for_sinatra(config)
@@ -227,7 +248,10 @@ module Appsignal
227
248
 
228
249
  def installed_frameworks
229
250
  [].tap do |out|
230
- out << :rails if framework_available? "rails"
251
+ if framework_available?("rails") &&
252
+ File.exist?(Appsignal::Utils::RailsHelper.application_config_path)
253
+ out << :rails
254
+ end
231
255
  out << :sinatra if framework_available? "sinatra"
232
256
  out << :padrino if framework_available? "padrino"
233
257
  out << :grape if framework_available? "grape"
@@ -11,27 +11,22 @@ module Appsignal
11
11
  end
12
12
 
13
13
  def install
14
- if ::Puma.respond_to?(:stats)
14
+ if ::Puma.respond_to?(:stats) && !defined?(APPSIGNAL_PUMA_PLUGIN_LOADED)
15
+ # Only install the minutely probe if a user isn't using our Puma
16
+ # plugin, which lives in `lib/puma/appsignal.rb`. This plugin defines
17
+ # the {APPSIGNAL_PUMA_PLUGIN_LOADED} constant.
18
+ #
19
+ # We prefer people use the AppSignal Puma plugin. This fallback is
20
+ # only there when users relied on our *magic* integration.
21
+ #
22
+ # Using the Puma plugin, the minutely probe thread will still run in
23
+ # Puma workers, for other non-Puma probes, but the Puma probe only
24
+ # runs in the Puma main process.
25
+ # For more information:
26
+ # https://docs.appsignal.com/ruby/integrations/puma.html
15
27
  Appsignal::Minutely.probes.register :puma, PumaProbe
16
28
  end
17
29
 
18
- if ::Puma.respond_to?(:cli_config) && ::Puma.cli_config
19
- ::Puma.cli_config.options[:before_fork] ||= []
20
- ::Puma.cli_config.options[:before_fork] << proc do |_id|
21
- Appsignal::Minutely.start
22
- end
23
-
24
- ::Puma.cli_config.options[:before_worker_boot] ||= []
25
- ::Puma.cli_config.options[:before_worker_boot] << proc do |_id|
26
- Appsignal.forked
27
- end
28
-
29
- ::Puma.cli_config.options[:before_worker_shutdown] ||= []
30
- ::Puma.cli_config.options[:before_worker_shutdown] << proc do |_id|
31
- Appsignal.stop("puma before_worker_shutdown")
32
- end
33
- end
34
-
35
30
  return unless defined?(::Puma::Cluster)
36
31
  # For clustered mode with multiple workers
37
32
  ::Puma::Cluster.class_eval do
@@ -11,6 +11,10 @@ module Appsignal
11
11
  rails_class.parent_name
12
12
  end
13
13
  end
14
+
15
+ def self.application_config_path
16
+ File.expand_path(File.join(Dir.pwd, "config/application.rb"))
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "2.9.16".freeze
4
+ VERSION = "2.9.17".freeze
5
5
  end
@@ -0,0 +1,26 @@
1
+ APPSIGNAL_PUMA_PLUGIN_LOADED = true
2
+
3
+ # AppSignal Puma plugin
4
+ #
5
+ # This plugin ensures the minutely probe thread is started with the Puma
6
+ # minutely probe in the Puma master process.
7
+ #
8
+ # The constant {APPSIGNAL_PUMA_PLUGIN_LOADED} is here to mark the Plugin as
9
+ # loaded by the rest of the AppSignal gem. This ensures that the Puma minutely
10
+ # probe is not also started in every Puma workers, which was the old behavior.
11
+ # See {Appsignal::Hooks::PumaHook#install} for more information.
12
+ #
13
+ # For even more information:
14
+ # https://docs.appsignal.com/ruby/integrations/puma.html
15
+ Puma::Plugin.create do
16
+ def start(launcher = nil)
17
+ launcher.events.on_booted do
18
+ require "appsignal"
19
+ if ::Puma.respond_to?(:stats)
20
+ Appsignal::Minutely.probes.register :puma, Appsignal::Hooks::PumaProbe
21
+ end
22
+ Appsignal.start
23
+ Appsignal.start_logger
24
+ end
25
+ end
26
+ end
@@ -16,6 +16,10 @@ describe Appsignal::CLI::Install do
16
16
  allow(described_class).to receive(:press_any_key)
17
17
  allow(Appsignal::Demo).to receive(:transmit).and_return(true)
18
18
  end
19
+ after do
20
+ FileUtils.rm_rf(tmp_dir)
21
+ FileUtils.mkdir_p(tmp_dir)
22
+ end
19
23
  around do |example|
20
24
  original_stdin = $stdin
21
25
  $stdin = StringIO.new
@@ -157,16 +161,10 @@ describe Appsignal::CLI::Install do
157
161
  shared_examples "capistrano install" do
158
162
  let(:capfile) { File.join(tmp_dir, "Capfile") }
159
163
  before do
160
- FileUtils.mkdir_p(tmp_dir)
161
-
162
164
  enter_app_name "foo"
163
165
  add_cli_input "n"
164
166
  choose_environment_config
165
167
  end
166
- after do
167
- FileUtils.rm_rf(tmp_dir)
168
- FileUtils.mkdir_p(tmp_dir)
169
- end
170
168
 
171
169
  context "without Capfile" do
172
170
  it "does nothing" do
@@ -260,7 +258,6 @@ describe Appsignal::CLI::Install do
260
258
  FileUtils.touch(File.join(environments_dir, "development.rb"))
261
259
  FileUtils.touch(File.join(environments_dir, "staging.rb"))
262
260
  FileUtils.touch(File.join(environments_dir, "production.rb"))
263
- enter_app_name app_name
264
261
  end
265
262
 
266
263
  describe "environments" do
@@ -410,6 +407,53 @@ describe Appsignal::CLI::Install do
410
407
  end
411
408
  end
412
409
  end
410
+
411
+ context "when there is no Rails application.rb file" do
412
+ before do
413
+ # Do not detect it as another framework for testing
414
+ allow(described_class).to receive(:framework_available?).and_call_original
415
+ allow(described_class).to receive(:framework_available?).with("sinatra").and_return(false)
416
+
417
+ File.delete(File.join(config_dir, "application.rb"))
418
+ expect(File.exist?(File.join(config_dir, "application.rb"))).to eql(false)
419
+ end
420
+
421
+ it "fails the installation" do
422
+ run
423
+
424
+ expect(output).to include("We could not detect which framework you are using.")
425
+ expect(output).to_not include("Installing for Ruby on Rails")
426
+ expect(output).to include_complete_install
427
+
428
+ expect(File.exist?(config_file_path)).to be(false)
429
+ end
430
+ end
431
+
432
+ context "when failed to load the Rails application.rb file" do
433
+ before do
434
+ File.open(File.join(config_dir, "application.rb"), "w") do |file|
435
+ file.write("I am invalid code")
436
+ end
437
+ end
438
+
439
+ it "prompts the user to fill in an app name" do
440
+ enter_app_name app_name
441
+ choose_config_file
442
+ run
443
+
444
+ expect(output).to include("Installing for Ruby on Rails")
445
+ expect(output).to include("Unable to automatically detect your Rails app's name.")
446
+ expect(output).to include("Choose your app's display name for AppSignal.com:")
447
+ expect(output).to include_file_config
448
+ expect(output).to include_complete_install
449
+
450
+ expect(config_file).to configure_app_name(app_name)
451
+ expect(config_file).to configure_push_api_key(push_api_key)
452
+ expect(config_file).to configure_environment("development")
453
+ expect(config_file).to configure_environment("staging")
454
+ expect(config_file).to configure_environment("production")
455
+ end
456
+ end
413
457
  end
414
458
  end
415
459
 
@@ -27,6 +27,8 @@ describe Appsignal::Hooks::PumaHook do
27
27
  end
28
28
 
29
29
  describe "installation" do
30
+ before { Appsignal::Minutely.probes.clear }
31
+
30
32
  context "when not clustered mode" do
31
33
  it "does not add AppSignal stop behavior Puma::Cluster" do
32
34
  expect(defined?(::Puma::Cluster)).to be_falsy
@@ -34,9 +36,27 @@ describe Appsignal::Hooks::PumaHook do
34
36
  Appsignal::Hooks::PumaHook.new.install
35
37
  end
36
38
 
37
- it "adds the Puma minutely probe" do
38
- probe = Appsignal::Minutely.probes[:puma]
39
- expect(probe).to eql(Appsignal::Hooks::PumaProbe)
39
+ context "with APPSIGNAL_PUMA_PLUGIN_LOADED defined" do
40
+ before do
41
+ # Set in lib/puma/appsignal.rb
42
+ APPSIGNAL_PUMA_PLUGIN_LOADED = true
43
+ end
44
+ after { Object.send :remove_const, :APPSIGNAL_PUMA_PLUGIN_LOADED }
45
+
46
+ it "does not add the Puma minutely probe" do
47
+ Appsignal::Hooks::PumaHook.new.install
48
+ expect(Appsignal::Minutely.probes[:puma]).to be_nil
49
+ end
50
+ end
51
+
52
+ context "without APPSIGNAL_PUMA_PLUGIN_LOADED defined" do
53
+ it "adds the Puma minutely probe" do
54
+ expect(defined?(APPSIGNAL_PUMA_PLUGIN_LOADED)).to be_nil
55
+
56
+ Appsignal::Hooks::PumaHook.new.install
57
+ probe = Appsignal::Minutely.probes[:puma]
58
+ expect(probe).to eql(Appsignal::Hooks::PumaProbe)
59
+ end
40
60
  end
41
61
  end
42
62
 
@@ -49,11 +69,11 @@ describe Appsignal::Hooks::PumaHook do
49
69
  end
50
70
  end
51
71
  end
52
- Appsignal::Hooks::PumaHook.new.install
53
72
  end
54
73
  after { Puma.send(:remove_const, :Cluster) }
55
74
 
56
75
  it "adds behavior to Puma::Cluster.stop_workers" do
76
+ Appsignal::Hooks::PumaHook.new.install
57
77
  cluster = Puma::Cluster.new
58
78
 
59
79
  expect(cluster.instance_variable_defined?(:@called)).to be_falsy
@@ -62,40 +82,28 @@ describe Appsignal::Hooks::PumaHook do
62
82
  expect(cluster.instance_variable_get(:@called)).to be(true)
63
83
  end
64
84
 
65
- it "adds the Puma minutely probe" do
66
- probe = Appsignal::Minutely.probes[:puma]
67
- expect(probe).to eql(Appsignal::Hooks::PumaProbe)
68
- end
69
- end
70
- end
71
-
72
- context "with nil hooks" do
73
- before do
74
- Puma.cli_config.options.delete(:before_fork)
75
- Puma.cli_config.options.delete(:before_worker_boot)
76
- Puma.cli_config.options.delete(:before_worker_shutdown)
77
- Appsignal::Hooks::PumaHook.new.install
78
- end
85
+ context "with APPSIGNAL_PUMA_PLUGIN_LOADED defined" do
86
+ before do
87
+ # Set in lib/puma/appsignal.rb
88
+ APPSIGNAL_PUMA_PLUGIN_LOADED = true
89
+ end
90
+ after { Object.send :remove_const, :APPSIGNAL_PUMA_PLUGIN_LOADED }
79
91
 
80
- it "should add a before shutdown worker callback" do
81
- expect(Puma.cli_config.options[:before_fork].first).to be_a(Proc)
82
- expect(Puma.cli_config.options[:before_worker_boot].first).to be_a(Proc)
83
- expect(Puma.cli_config.options[:before_worker_shutdown].first).to be_a(Proc)
84
- end
85
- end
92
+ it "does not add the Puma minutely probe" do
93
+ Appsignal::Hooks::PumaHook.new.install
94
+ expect(Appsignal::Minutely.probes[:puma]).to be_nil
95
+ end
96
+ end
86
97
 
87
- context "with existing hooks" do
88
- before do
89
- Puma.cli_config.options[:before_fork] = []
90
- Puma.cli_config.options[:before_worker_boot] = []
91
- Puma.cli_config.options[:before_worker_shutdown] = []
92
- Appsignal::Hooks::PumaHook.new.install
93
- end
98
+ context "without APPSIGNAL_PUMA_PLUGIN_LOADED defined" do
99
+ it "adds the Puma minutely probe" do
100
+ expect(defined?(APPSIGNAL_PUMA_PLUGIN_LOADED)).to be_nil
94
101
 
95
- it "should add a before shutdown worker callback" do
96
- expect(Puma.cli_config.options[:before_fork].first).to be_a(Proc)
97
- expect(Puma.cli_config.options[:before_worker_boot].first).to be_a(Proc)
98
- expect(Puma.cli_config.options[:before_worker_shutdown].first).to be_a(Proc)
102
+ Appsignal::Hooks::PumaHook.new.install
103
+ probe = Appsignal::Minutely.probes[:puma]
104
+ expect(probe).to eql(Appsignal::Hooks::PumaProbe)
105
+ end
106
+ end
99
107
  end
100
108
  end
101
109
  end
@@ -1,4 +1,6 @@
1
1
  describe Appsignal::Minutely do
2
+ include WaitForHelper
3
+
2
4
  before { Appsignal::Minutely.probes.clear }
3
5
 
4
6
  it "returns a ProbeCollection" do
@@ -7,38 +9,26 @@ describe Appsignal::Minutely do
7
9
  end
8
10
 
9
11
  describe ".start" do
10
- class Probe
11
- attr_reader :calls
12
-
13
- def initialize
14
- @calls = 0
15
- end
16
-
17
- def call
18
- @calls += 1
19
- end
20
- end
21
-
22
- class ProbeWithoutDependency < Probe
12
+ class ProbeWithoutDependency < MockProbe
23
13
  def self.dependencies_present?
24
14
  true
25
15
  end
26
16
  end
27
17
 
28
- class ProbeWithMissingDependency < Probe
18
+ class ProbeWithMissingDependency < MockProbe
29
19
  def self.dependencies_present?
30
20
  false
31
21
  end
32
22
  end
33
23
 
34
- class BrokenProbe < Probe
24
+ class BrokenProbe < MockProbe
35
25
  def call
36
26
  super
37
27
  raise "oh no!"
38
28
  end
39
29
  end
40
30
 
41
- class BrokenProbeOnInitialize < Probe
31
+ class BrokenProbeOnInitialize < MockProbe
42
32
  def initialize
43
33
  super
44
34
  raise "oh no initialize!"
@@ -60,7 +50,7 @@ describe Appsignal::Minutely do
60
50
 
61
51
  context "with an instance of a class" do
62
52
  it "calls the probe every <wait_time>" do
63
- probe = Probe.new
53
+ probe = MockProbe.new
64
54
  Appsignal::Minutely.probes.register :my_probe, probe
65
55
  Appsignal::Minutely.start
66
56
 
@@ -90,8 +80,8 @@ describe Appsignal::Minutely do
90
80
 
91
81
  context "with probe class" do
92
82
  it "creates an instance of the class and call that every <wait time>" do
93
- probe = Probe
94
- probe_instance = Probe.new
83
+ probe = MockProbe
84
+ probe_instance = MockProbe.new
95
85
  expect(probe).to receive(:new).and_return(probe_instance)
96
86
  Appsignal::Minutely.probes.register :my_probe, probe
97
87
  Appsignal::Minutely.start
@@ -163,7 +153,7 @@ describe Appsignal::Minutely do
163
153
 
164
154
  context "with a broken probe" do
165
155
  it "logs the error and continues calling the probes every <wait_time>" do
166
- probe = Probe.new
156
+ probe = MockProbe.new
167
157
  broken_probe = BrokenProbe.new
168
158
  Appsignal::Minutely.probes.register :my_probe, probe
169
159
  Appsignal::Minutely.probes.register :broken_probe, broken_probe
@@ -183,7 +173,7 @@ describe Appsignal::Minutely do
183
173
 
184
174
  it "ensures only one minutely probes thread is active at a time" do
185
175
  alive_thread_counter = proc { Thread.list.reject { |t| t.status == "dead" }.length }
186
- probe = Probe.new
176
+ probe = MockProbe.new
187
177
  Appsignal::Minutely.probes.register :my_probe, probe
188
178
  expect do
189
179
  Appsignal::Minutely.start
@@ -349,31 +339,4 @@ describe Appsignal::Minutely do
349
339
  end
350
340
  end
351
341
  end
352
-
353
- # Wait for a condition to be met
354
- #
355
- # @example
356
- # # Perform threaded operation
357
- # wait_for("enough probe calls") { probe.calls >= 2 }
358
- # # Assert on result
359
- #
360
- # @param name [String] The name of the condition to check. Used in the
361
- # error when it fails.
362
- # @yield Assertion to check.
363
- # @yieldreturn [Boolean] True/False value that indicates if the condition
364
- # is met.
365
- # @raise [StandardError] Raises error if the condition is not met after 5
366
- # seconds, 5_000 tries.
367
- def wait_for(name)
368
- max_wait = 5_000
369
- i = 0
370
- while i <= max_wait
371
- break if yield
372
- i += 1
373
- sleep 0.001
374
- end
375
-
376
- return unless i == max_wait
377
- raise "Waited 5 seconds for #{name} condition, but was not met."
378
- end
379
342
  end
@@ -0,0 +1,91 @@
1
+ RSpec.describe "Puma plugin" do
2
+ include WaitForHelper
3
+
4
+ class MockPumaLauncher
5
+ def events
6
+ return @events if defined?(@events)
7
+
8
+ @events = MockPumaEvents.new
9
+ end
10
+ end
11
+
12
+ class MockPumaEvents
13
+ def on_booted(&block)
14
+ @on_booted = block if block_given?
15
+ @on_booted if defined?(@on_booted)
16
+ end
17
+ end
18
+
19
+ let(:probe) { MockProbe.new }
20
+ let(:launcher) { MockPumaLauncher.new }
21
+ before do
22
+ module Puma
23
+ def self.stats
24
+ end
25
+
26
+ class Plugin
27
+ class << self
28
+ attr_reader :plugin
29
+
30
+ def create(&block)
31
+ @plugin = Class.new(::Puma::Plugin)
32
+ @plugin.class_eval(&block)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ Appsignal::Minutely.probes.clear
39
+ ENV["APPSIGNAL_ENABLE_MINUTELY_PROBES"] = "true"
40
+ Appsignal.config = project_fixture_config
41
+ # Speed up test time
42
+ allow(Appsignal::Minutely).to receive(:initial_wait_time).and_return(0.001)
43
+ allow(Appsignal::Minutely).to receive(:wait_time).and_return(0.001)
44
+
45
+ Appsignal::Minutely.probes.register :my_probe, probe
46
+ load File.expand_path("../lib/puma/plugin/appsignal.rb", APPSIGNAL_SPEC_DIR)
47
+ end
48
+ after do
49
+ Appsignal.config = nil
50
+ Object.send :remove_const, :Puma
51
+ Object.send :remove_const, :APPSIGNAL_PUMA_PLUGIN_LOADED
52
+ end
53
+
54
+ it "registers the PumaProbe" do
55
+ expect(Appsignal::Minutely.probes[:my_probe]).to eql(probe)
56
+ expect(Appsignal::Minutely.probes[:puma]).to be_nil
57
+ plugin = Puma::Plugin.plugin.new
58
+ expect(launcher.events.on_booted).to be_nil
59
+
60
+ plugin.start(launcher)
61
+ expect(Appsignal::Minutely.probes[:puma]).to be_nil
62
+ expect(launcher.events.on_booted).to_not be_nil
63
+
64
+ launcher.events.on_booted.call
65
+ expect(Appsignal::Minutely.probes[:puma]).to eql(Appsignal::Hooks::PumaProbe)
66
+
67
+ # Minutely probes started and called
68
+ wait_for("enough probe calls") { probe.calls >= 2 }
69
+ end
70
+
71
+ context "without Puma.stats" do
72
+ before { Puma.singleton_class.send(:remove_method, :stats) }
73
+
74
+ it "does not register the PumaProbe" do
75
+ expect(Appsignal::Minutely.probes[:my_probe]).to eql(probe)
76
+ expect(Appsignal::Minutely.probes[:puma]).to be_nil
77
+ plugin = Puma::Plugin.plugin.new
78
+ expect(launcher.events.on_booted).to be_nil
79
+
80
+ plugin.start(launcher)
81
+ expect(Appsignal::Minutely.probes[:puma]).to be_nil
82
+ expect(launcher.events.on_booted).to_not be_nil
83
+
84
+ launcher.events.on_booted.call
85
+ expect(Appsignal::Minutely.probes[:puma]).to be_nil
86
+
87
+ # Minutely probes started and called
88
+ wait_for("enough probe calls") { probe.calls >= 2 }
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,28 @@
1
+ module WaitForHelper
2
+ # Wait for a condition to be met
3
+ #
4
+ # @example
5
+ # # Perform threaded operation
6
+ # wait_for("enough probe calls") { probe.calls >= 2 }
7
+ # # Assert on result
8
+ #
9
+ # @param name [String] The name of the condition to check. Used in the
10
+ # error when it fails.
11
+ # @yield Assertion to check.
12
+ # @yieldreturn [Boolean] True/False value that indicates if the condition
13
+ # is met.
14
+ # @raise [StandardError] Raises error if the condition is not met after 5
15
+ # seconds, 5_000 tries.
16
+ def wait_for(name)
17
+ max_wait = 5_000
18
+ i = 0
19
+ while i <= max_wait
20
+ break if yield
21
+ i += 1
22
+ sleep 0.001
23
+ end
24
+
25
+ return unless i == max_wait
26
+ raise "Waited 5 seconds for #{name} condition, but was not met."
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ class MockProbe
2
+ attr_reader :calls
3
+
4
+ def initialize
5
+ @calls = 0
6
+ end
7
+
8
+ def call
9
+ @calls += 1
10
+ end
11
+ 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.9.16
4
+ version: 2.9.17
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: 2019-09-30 00:00:00.000000000 Z
13
+ date: 2019-11-07 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -269,6 +269,7 @@ files:
269
269
  - lib/appsignal/utils/query_params_sanitizer.rb
270
270
  - lib/appsignal/utils/rails_helper.rb
271
271
  - lib/appsignal/version.rb
272
+ - lib/puma/plugin/appsignal.rb
272
273
  - lib/sequel/extensions/appsignal_integration.rb
273
274
  - resources/appsignal.yml.erb
274
275
  - resources/cacert.pem
@@ -342,6 +343,7 @@ files:
342
343
  - spec/lib/appsignal/utils/json_spec.rb
343
344
  - spec/lib/appsignal/utils/query_params_sanitizer_spec.rb
344
345
  - spec/lib/appsignal_spec.rb
346
+ - spec/lib/puma/appsignal_spec.rb
345
347
  - spec/spec_helper.rb
346
348
  - spec/support/fixtures/generated_config.yml
347
349
  - spec/support/fixtures/projects/valid/config/application.rb
@@ -364,9 +366,11 @@ files:
364
366
  - spec/support/helpers/system_helpers.rb
365
367
  - spec/support/helpers/time_helpers.rb
366
368
  - spec/support/helpers/transaction_helpers.rb
369
+ - spec/support/helpers/wait_for_helper.rb
367
370
  - spec/support/matchers/contains_log.rb
368
371
  - spec/support/mocks/fake_gc_profiler.rb
369
372
  - spec/support/mocks/mock_extension.rb
373
+ - spec/support/mocks/mock_probe.rb
370
374
  - spec/support/rails/my_app.rb
371
375
  - spec/support/shared_examples/instrument.rb
372
376
  - spec/support/stubs/delayed_job.rb
@@ -398,7 +402,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
398
402
  - !ruby/object:Gem::Version
399
403
  version: '0'
400
404
  requirements: []
401
- rubygems_version: 3.0.2
405
+ rubygems_version: 3.0.6
402
406
  signing_key:
403
407
  specification_version: 4
404
408
  summary: Logs performance and exception data from your app to appsignal.com
@@ -473,6 +477,7 @@ test_files:
473
477
  - spec/lib/appsignal/utils/json_spec.rb
474
478
  - spec/lib/appsignal/utils/query_params_sanitizer_spec.rb
475
479
  - spec/lib/appsignal_spec.rb
480
+ - spec/lib/puma/appsignal_spec.rb
476
481
  - spec/spec_helper.rb
477
482
  - spec/support/fixtures/generated_config.yml
478
483
  - spec/support/fixtures/projects/valid/config/application.rb
@@ -495,9 +500,11 @@ test_files:
495
500
  - spec/support/helpers/system_helpers.rb
496
501
  - spec/support/helpers/time_helpers.rb
497
502
  - spec/support/helpers/transaction_helpers.rb
503
+ - spec/support/helpers/wait_for_helper.rb
498
504
  - spec/support/matchers/contains_log.rb
499
505
  - spec/support/mocks/fake_gc_profiler.rb
500
506
  - spec/support/mocks/mock_extension.rb
507
+ - spec/support/mocks/mock_probe.rb
501
508
  - spec/support/rails/my_app.rb
502
509
  - spec/support/shared_examples/instrument.rb
503
510
  - spec/support/stubs/delayed_job.rb