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 +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/appsignal/cli/install.rb +34 -10
- data/lib/appsignal/hooks/puma.rb +13 -18
- data/lib/appsignal/utils/rails_helper.rb +4 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/puma/plugin/appsignal.rb +26 -0
- data/spec/lib/appsignal/cli/install_spec.rb +51 -7
- data/spec/lib/appsignal/hooks/puma_spec.rb +43 -35
- data/spec/lib/appsignal/minutely_spec.rb +11 -48
- data/spec/lib/puma/appsignal_spec.rb +91 -0
- data/spec/support/helpers/wait_for_helper.rb +28 -0
- data/spec/support/mocks/mock_probe.rb +11 -0
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f02b2d17e2a2de9e6d2552c8f4fb4ff0d5d2335ec7bcbb17eaa2967c49c0945f
|
4
|
+
data.tar.gz: c50aa8e015192af38f991a38211cf29969d44d96184972a4f345e01451e5962a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76f2fd7223f354b00104dfc38a690e38fe3a5c01ce89a1996916b3ceea3f29fcc45b80c95e0fc63f88a99246ce251070ec53e30c316f19d1789b09d71a25f6ef
|
7
|
+
data.tar.gz: 79e193ac1d6d5e5c84cb192c59505351fdf372e5840d9f9403df2eeeef62619d88961b4acce27248874480455123fe29b62ee8cb17e039c45b8e0c1e01ea6001
|
data/CHANGELOG.md
CHANGED
@@ -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
|
-
|
78
|
+
name_overwritten = configure_rails_app_name(config)
|
79
|
+
configure(config, rails_environments, name_overwritten)
|
80
|
+
done_notice
|
81
|
+
end
|
79
82
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
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"
|
data/lib/appsignal/hooks/puma.rb
CHANGED
@@ -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
|
data/lib/appsignal/version.rb
CHANGED
@@ -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
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
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 <
|
18
|
+
class ProbeWithMissingDependency < MockProbe
|
29
19
|
def self.dependencies_present?
|
30
20
|
false
|
31
21
|
end
|
32
22
|
end
|
33
23
|
|
34
|
-
class BrokenProbe <
|
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 <
|
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 =
|
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 =
|
94
|
-
probe_instance =
|
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 =
|
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 =
|
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
|
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.
|
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-
|
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.
|
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
|