appsignal 3.11.0-java → 3.12.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +115 -0
  3. data/Rakefile +1 -1
  4. data/lib/appsignal/cli/diagnose.rb +1 -1
  5. data/lib/appsignal/config.rb +150 -32
  6. data/lib/appsignal/demo.rb +1 -6
  7. data/lib/appsignal/helpers/instrumentation.rb +2 -2
  8. data/lib/appsignal/integrations/grape.rb +7 -0
  9. data/lib/appsignal/integrations/hanami.rb +8 -43
  10. data/lib/appsignal/integrations/padrino.rb +8 -73
  11. data/lib/appsignal/integrations/railtie.rb +35 -13
  12. data/lib/appsignal/integrations/sinatra.rb +8 -19
  13. data/lib/appsignal/loaders/grape.rb +13 -0
  14. data/lib/appsignal/loaders/hanami.rb +40 -0
  15. data/lib/appsignal/loaders/padrino.rb +68 -0
  16. data/lib/appsignal/loaders/sinatra.rb +24 -0
  17. data/lib/appsignal/loaders.rb +92 -0
  18. data/lib/appsignal/rack/abstract_middleware.rb +2 -1
  19. data/lib/appsignal/rack/event_handler.rb +5 -5
  20. data/lib/appsignal/rack.rb +6 -0
  21. data/lib/appsignal/version.rb +1 -1
  22. data/lib/appsignal.rb +163 -9
  23. data/spec/lib/appsignal/cli/demo_spec.rb +0 -1
  24. data/spec/lib/appsignal/cli/diagnose/paths_spec.rb +1 -1
  25. data/spec/lib/appsignal/cli/diagnose_spec.rb +0 -1
  26. data/spec/lib/appsignal/config_spec.rb +153 -1
  27. data/spec/lib/appsignal/demo_spec.rb +1 -2
  28. data/spec/lib/appsignal/environment_spec.rb +4 -2
  29. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +3 -6
  30. data/spec/lib/appsignal/hooks/activejob_spec.rb +3 -3
  31. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +4 -7
  32. data/spec/lib/appsignal/hooks/excon_spec.rb +3 -6
  33. data/spec/lib/appsignal/hooks/gvl_spec.rb +2 -2
  34. data/spec/lib/appsignal/hooks/http_spec.rb +1 -3
  35. data/spec/lib/appsignal/hooks/net_http_spec.rb +1 -1
  36. data/spec/lib/appsignal/hooks/redis_client_spec.rb +5 -8
  37. data/spec/lib/appsignal/hooks/redis_spec.rb +3 -6
  38. data/spec/lib/appsignal/hooks/resque_spec.rb +1 -1
  39. data/spec/lib/appsignal/hooks/sequel_spec.rb +3 -5
  40. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +1 -1
  41. data/spec/lib/appsignal/hooks/webmachine_spec.rb +1 -1
  42. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +2 -2
  43. data/spec/lib/appsignal/integrations/grape_spec.rb +36 -0
  44. data/spec/lib/appsignal/integrations/hanami_spec.rb +9 -178
  45. data/spec/lib/appsignal/integrations/http_spec.rb +1 -5
  46. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +4 -2
  47. data/spec/lib/appsignal/integrations/net_http_spec.rb +1 -1
  48. data/spec/lib/appsignal/integrations/object_spec.rb +1 -3
  49. data/spec/lib/appsignal/integrations/padrino_spec.rb +8 -330
  50. data/spec/lib/appsignal/integrations/railtie_spec.rb +275 -191
  51. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +1 -1
  52. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +11 -9
  53. data/spec/lib/appsignal/integrations/sinatra_spec.rb +9 -104
  54. data/spec/lib/appsignal/loaders/grape_spec.rb +12 -0
  55. data/spec/lib/appsignal/loaders/hanami_spec.rb +95 -0
  56. data/spec/lib/appsignal/loaders/padrino_spec.rb +277 -0
  57. data/spec/lib/appsignal/loaders/sinatra_spec.rb +47 -0
  58. data/spec/lib/appsignal/loaders_spec.rb +137 -0
  59. data/spec/lib/appsignal/probes/sidekiq_spec.rb +1 -1
  60. data/spec/lib/appsignal/probes_spec.rb +6 -5
  61. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +3 -2
  62. data/spec/lib/appsignal/rack/event_handler_spec.rb +33 -0
  63. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +1 -1
  64. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +2 -35
  65. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +1 -1
  66. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +3 -3
  67. data/spec/lib/appsignal/span_spec.rb +1 -3
  68. data/spec/lib/appsignal/transaction_spec.rb +61 -70
  69. data/spec/lib/appsignal_spec.rb +284 -26
  70. data/spec/lib/puma/appsignal_spec.rb +0 -3
  71. data/spec/spec_helper.rb +5 -4
  72. data/spec/support/helpers/config_helpers.rb +2 -1
  73. data/spec/support/helpers/loader_helper.rb +21 -0
  74. data/spec/support/matchers/transaction.rb +3 -2
  75. data/spec/support/stubs/appsignal/loaders/loader_stub.rb +7 -0
  76. data/spec/support/testing.rb +46 -0
  77. metadata +15 -2
@@ -1,110 +1,15 @@
1
- if DependencyHelper.sinatra_present?
2
- require "appsignal/integrations/sinatra"
3
-
4
- def install_sinatra_integration
5
- load File.expand_path("lib/appsignal/integrations/sinatra.rb", project_dir)
6
- end
7
-
8
- # "Uninstall" the AppSignal integration
9
- def uninstall_sinatra_integration
10
- expected_middleware = [
11
- Rack::Events,
12
- Appsignal::Rack::SinatraBaseInstrumentation
13
- ]
14
- Sinatra::Base.instance_variable_get(:@middleware).delete_if do |middleware|
15
- expected_middleware.include?(middleware.first)
16
- end
17
- end
18
-
1
+ if DependencyHelper.padrino_present?
19
2
  describe "Sinatra integration" do
20
- before do
21
- Appsignal.config = nil
22
- end
23
- after { uninstall_sinatra_integration }
24
-
25
- context "when active" do
26
- before { allow(Appsignal).to receive(:active?).and_return(true) }
27
-
28
- it "does not start AppSignal again" do
29
- expect(Appsignal::Config).to_not receive(:new)
30
- expect(Appsignal).to_not receive(:start)
31
- install_sinatra_integration
32
- end
33
-
34
- it "adds the instrumentation middleware to Sinatra::Base" do
35
- install_sinatra_integration
36
- middlewares = Sinatra::Base.middleware.to_a
37
- expect(middlewares).to include(
38
- [Rack::Events, [[instance_of(Appsignal::Rack::EventHandler)]], nil]
39
- )
40
- expect(middlewares).to include(
41
- [Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
42
- )
43
- end
44
- end
45
-
46
- context "when not active" do
47
- context "Appsignal.internal_logger" do
48
- subject { Appsignal.internal_logger }
49
-
50
- it "sets a logger" do
51
- install_sinatra_integration
52
- is_expected.to be_a Logger
53
- end
54
- end
55
-
56
- describe "middleware" do
57
- context "when AppSignal is not active" do
58
- it "does not add the instrumentation middleware to Sinatra::Base" do
59
- install_sinatra_integration
60
- middlewares = Sinatra::Base.middleware.to_a
61
- expect(middlewares).to_not include(
62
- [Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
63
- )
64
- expect(middlewares).to_not include(
65
- [Rack::Events, [Appsignal::Rack::EventHandler], nil]
66
- )
67
- end
68
- end
69
-
70
- context "when the new AppSignal config is active" do
71
- it "adds the instrumentation middleware to Sinatra::Base" do
72
- ENV["APPSIGNAL_APP_NAME"] = "My Sinatra app name"
73
- ENV["APPSIGNAL_APP_ENV"] = "test"
74
- ENV["APPSIGNAL_PUSH_API_KEY"] = "my-key"
75
-
76
- install_sinatra_integration
77
- middlewares = Sinatra::Base.middleware.to_a
78
- expect(middlewares).to include(
79
- [Rack::Events, [[Appsignal::Rack::EventHandler]], nil],
80
- [Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
81
- )
82
- end
83
- end
84
- end
85
-
86
- describe "environment" do
87
- subject { Appsignal.config.env }
88
-
89
- context "without APPSIGNAL_APP_ENV" do
90
- before { install_sinatra_integration }
91
-
92
- it "uses the app environment" do
93
- expect(subject).to eq("test")
94
- end
95
- end
3
+ it "loads the Sinatra loader" do
4
+ ENV["APPSIGNAL_APP_NAME"] = "test/sinatra"
5
+ ENV["APPSIGNAL_PUSH_API_KEY"] = "test-key"
96
6
 
97
- context "with APPSIGNAL_APP_ENV" do
98
- before do
99
- ENV["APPSIGNAL_APP_ENV"] = "env-staging"
100
- install_sinatra_integration
101
- end
7
+ require "appsignal/integrations/sinatra"
102
8
 
103
- it "uses the environment variable" do
104
- expect(subject).to eq("env-staging")
105
- end
106
- end
107
- end
9
+ expect(Appsignal::Loaders.instances).to include(
10
+ :sinatra => kind_of(Appsignal::Loaders::SinatraLoader)
11
+ )
12
+ expect(Appsignal.active?).to be(true)
108
13
  end
109
14
  end
110
15
  end
@@ -0,0 +1,12 @@
1
+ if DependencyHelper.grape_present?
2
+ describe "Appsignal::Loaders::PadrinoLoader" do
3
+ describe "#on_load" do
4
+ it "ensures the Grape middleware is loaded" do
5
+ load_loader(:grape)
6
+
7
+ # Calling this doesn't raise a NameError
8
+ Appsignal::Rack::GrapeMiddleware
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,95 @@
1
+ if DependencyHelper.hanami_present?
2
+ describe "Appsignal::Loaders::HanamiLoader" do
3
+ before { Appsignal.config = nil }
4
+
5
+ describe "#on_load" do
6
+ it "registers Hanami default config" do
7
+ load_loader(:hanami)
8
+
9
+ expect(Appsignal::Config.loader_defaults).to include([
10
+ :hanami,
11
+ {
12
+ :env => :test,
13
+ :root_path => Dir.pwd
14
+ }
15
+ ])
16
+ end
17
+ end
18
+
19
+ describe "#on_start" do
20
+ before do
21
+ allow(::Hanami::Action).to receive(:prepend)
22
+ load_loader(:hanami)
23
+ start_loader(:hanami)
24
+ end
25
+ after { uninstall_hanami_middleware }
26
+
27
+ def uninstall_hanami_middleware
28
+ middleware_stack = ::Hanami.app.config.middleware.stack[::Hanami::Router::DEFAULT_PREFIX]
29
+ middleware_stack.delete_if do |middleware|
30
+ middleware.first == Appsignal::Rack::HanamiMiddleware ||
31
+ middleware.first == Rack::Events
32
+ end
33
+ end
34
+
35
+ it "adds the instrumentation middleware to Sinatra::Base" do
36
+ expect(::Hanami.app.config.middleware.stack[::Hanami::Router::DEFAULT_PREFIX])
37
+ .to include(
38
+ [Rack::Events, [[kind_of(Appsignal::Rack::EventHandler)]], *hanami_middleware_options],
39
+ [Appsignal::Rack::HanamiMiddleware, [], *hanami_middleware_options]
40
+ )
41
+ end
42
+
43
+ it "prepends the integration to Hanami::Action" do
44
+ expect(::Hanami::Action)
45
+ .to have_received(:prepend).with(Appsignal::Loaders::HanamiLoader::HanamiIntegration)
46
+ end
47
+
48
+ def hanami_middleware_options
49
+ if DependencyHelper.hanami2_1_present?
50
+ [{}, nil]
51
+ else
52
+ [nil]
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "Appsignal::Loaders::HanamiLoader::HanamiIntegration" do
58
+ let(:transaction) { http_request_transaction }
59
+ let(:app) { HanamiApp::Actions::Books::Index }
60
+ around { |example| keep_transactions { example.run } }
61
+ before do
62
+ expect(::Hanami.app.config).to receive(:root).and_return(project_fixture_path)
63
+ Appsignal.load(:hanami)
64
+ start_agent
65
+ end
66
+
67
+ def make_request(env)
68
+ action = app.new
69
+ action.call(env)
70
+ end
71
+
72
+ describe "#call" do
73
+ context "without an active transaction" do
74
+ let(:env) { {} }
75
+
76
+ it "does not set the action name" do
77
+ make_request(env)
78
+
79
+ expect(transaction).to_not have_action
80
+ end
81
+ end
82
+
83
+ context "with an active transaction" do
84
+ let(:env) { { Appsignal::Rack::APPSIGNAL_TRANSACTION => transaction } }
85
+
86
+ it "sets action name on the transaction" do
87
+ make_request(env)
88
+
89
+ expect(transaction).to have_action("HanamiApp::Actions::Books::Index")
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,277 @@
1
+ if DependencyHelper.padrino_present?
2
+ describe "Appsignal::Loaders::PadrinoLoader" do
3
+ before { Appsignal.config = nil }
4
+
5
+ describe "#on_load" do
6
+ it "registers Padrino default config" do
7
+ load_loader(:padrino)
8
+
9
+ expect(Appsignal::Config.loader_defaults).to include([
10
+ :padrino,
11
+ {
12
+ :env => :test,
13
+ :root_path => Padrino.mounted_root
14
+ }
15
+ ])
16
+ end
17
+ end
18
+
19
+ describe "#on_start" do
20
+ let(:callbacks) { { :before_load => nil } }
21
+ before do
22
+ allow(Padrino).to receive(:before_load)
23
+ .and_wrap_original do |original_method, *args, &block|
24
+ callbacks[:before_load] = block
25
+ original_method.call(*args, &block)
26
+ end
27
+ end
28
+ after { uninstall_padrino_integration }
29
+
30
+ def uninstall_padrino_integration
31
+ expected_middleware = [
32
+ Rack::Events,
33
+ Appsignal::Rack::SinatraBaseInstrumentation
34
+ ]
35
+ Padrino.middleware.delete_if do |middleware|
36
+ expected_middleware.include?(middleware.first)
37
+ end
38
+ end
39
+
40
+ it "adds the instrumentation middleware to Padrino" do
41
+ load_loader(:padrino)
42
+ start_loader(:padrino)
43
+
44
+ callbacks[:before_load].call
45
+
46
+ middlewares = Padrino.middleware
47
+ expect(middlewares).to include(
48
+ [Rack::Events, [[instance_of(Appsignal::Rack::EventHandler)]], nil]
49
+ )
50
+ expect(middlewares).to include(
51
+ [
52
+ Appsignal::Rack::SinatraBaseInstrumentation,
53
+ [
54
+ :instrument_event_name => "process_action.padrino"
55
+ ],
56
+ nil
57
+ ]
58
+ )
59
+ end
60
+ end
61
+
62
+ describe "Padrino integration" do
63
+ class PadrinoClassWithRouter
64
+ include Padrino::Routing
65
+ end
66
+
67
+ let(:base) { double }
68
+ let(:router) { PadrinoClassWithRouter.new }
69
+ let(:env) { {} }
70
+ # TODO: use an instance double
71
+ let(:settings) { double(:name => "TestApp") }
72
+ around { |example| keep_transactions { example.run } }
73
+ before { Appsignal.config = nil }
74
+
75
+ describe "routes" do
76
+ let(:env) do
77
+ {
78
+ "REQUEST_METHOD" => "GET",
79
+ "PATH_INFO" => path,
80
+ "REQUEST_PATH" => path,
81
+ "rack.input" => StringIO.new
82
+ }
83
+ end
84
+ let(:app) do
85
+ Class.new(Padrino::Application) do
86
+ def self.name
87
+ "PadrinoTestApp"
88
+ end
89
+ end
90
+ end
91
+ let(:response) { app.call(env) }
92
+
93
+ def fetch_body(body)
94
+ if body.respond_to?(:response)
95
+ _, _, nested_body = body.response.to_a
96
+ fetch_body(nested_body)
97
+ elsif body.respond_to?(:to_ary)
98
+ body.to_ary
99
+ else
100
+ body
101
+ end
102
+ end
103
+
104
+ RSpec::Matchers.define :match_response do |expected_status, expected_body|
105
+ match do |response|
106
+ status, _headers, potential_body = response
107
+ body = fetch_body(potential_body)
108
+
109
+ matches_body =
110
+ if expected_body.is_a?(Regexp)
111
+ body.join =~ expected_body
112
+ else
113
+ body == [expected_body].compact
114
+ end
115
+ status == expected_status && matches_body
116
+ end
117
+ end
118
+
119
+ context "when AppSignal is not active" do
120
+ let(:path) { "/foo" }
121
+ before { app.controllers { get(:foo) { "content" } } }
122
+
123
+ it "does not instrument the request" do
124
+ expect do
125
+ expect(response).to match_response(200, "content")
126
+ end.to_not(change { created_transactions.count })
127
+ end
128
+ end
129
+
130
+ context "when AppSignal is active" do
131
+ let(:transaction) { http_request_transaction }
132
+ before do
133
+ start_agent
134
+ set_current_transaction(transaction)
135
+ end
136
+
137
+ context "with not existing route" do
138
+ let(:path) { "/404" }
139
+
140
+ it "instruments the request" do
141
+ expect(response).to match_response(404, /^GET /404/)
142
+ expect(last_transaction).to have_action("PadrinoTestApp#unknown")
143
+ end
144
+ end
145
+
146
+ context "when Sinatra tells us it's a static file" do
147
+ let(:path) { "/static" }
148
+ before do
149
+ env["sinatra.static_file"] = true
150
+ app.controllers { get(:static) { "Static!" } }
151
+ end
152
+
153
+ it "does not instrument the request" do
154
+ expect(response).to match_response(200, "Static!")
155
+ expect(last_transaction).to_not have_action
156
+ end
157
+ end
158
+
159
+ # Older Padrino versions don't support `action` (v11.0+)
160
+ context "without #action on Sinatra::Request" do
161
+ let(:path) { "/my_original_path/10" }
162
+ before do
163
+ allow_any_instance_of(Sinatra::Request).to receive(:action).and_return(nil)
164
+ app.controllers { get(:my_original_path, :with => :id) { "content" } }
165
+ end
166
+
167
+ it "falls back on Sinatra::Request#route_obj.original_path" do
168
+ expect(response).to match_response(200, "content")
169
+ expect(last_transaction).to have_action("PadrinoTestApp:/my_original_path/:id")
170
+ end
171
+ end
172
+
173
+ context "without Sinatra::Request#route_obj.original_path" do
174
+ let(:path) { "/my_original_path" }
175
+ before do
176
+ allow_any_instance_of(Sinatra::Request).to receive(:action).and_return(nil)
177
+ allow_any_instance_of(Sinatra::Request).to receive(:route_obj).and_return(nil)
178
+ app.controllers { get(:my_original_path) { "content" } }
179
+ end
180
+
181
+ it "falls back on app name" do
182
+ expect(response).to match_response(200, "content")
183
+ expect(last_transaction).to have_action("PadrinoTestApp#unknown")
184
+ end
185
+ end
186
+
187
+ context "with existing route" do
188
+ let(:path) { "/" }
189
+ def make_request
190
+ expect(response).to match_response(200, "content")
191
+ end
192
+
193
+ context "with action name as symbol" do
194
+ context "with :index helper" do
195
+ before do
196
+ # :index == "/"
197
+ app.controllers { get(:index) { "content" } }
198
+ end
199
+
200
+ it "sets the action with the app name and action name" do
201
+ make_request
202
+ expect(last_transaction).to have_action("PadrinoTestApp:#index")
203
+ end
204
+ end
205
+
206
+ context "with custom action name" do
207
+ let(:path) { "/foo" }
208
+ before do
209
+ app.controllers { get(:foo) { "content" } }
210
+ end
211
+
212
+ it "sets the action with the app name and action name" do
213
+ make_request
214
+ expect(last_transaction).to have_action("PadrinoTestApp:#foo")
215
+ end
216
+ end
217
+ end
218
+
219
+ context "with an action defined with a path" do
220
+ context "with root path" do
221
+ before do
222
+ # :index == "/"
223
+ app.controllers { get("/") { "content" } }
224
+ end
225
+
226
+ it "sets the action with the app name and action path" do
227
+ make_request
228
+ expect(last_transaction).to have_action("PadrinoTestApp:#/")
229
+ end
230
+ end
231
+
232
+ context "with custom path" do
233
+ let(:path) { "/foo" }
234
+ before do
235
+ app.controllers { get("/foo") { "content" } }
236
+ end
237
+
238
+ it "sets the action with the app name and action path" do
239
+ make_request
240
+ expect(last_transaction).to have_action("PadrinoTestApp:#/foo")
241
+ end
242
+ end
243
+ end
244
+
245
+ context "with controller" do
246
+ let(:path) { "/my_controller" }
247
+
248
+ context "with controller as name" do
249
+ before do
250
+ # :index == "/"
251
+ app.controllers(:my_controller) { get(:index) { "content" } }
252
+ end
253
+
254
+ it "sets the action with the app name, controller name and action name" do
255
+ make_request
256
+ expect(last_transaction).to have_action("PadrinoTestApp:my_controller#index")
257
+ end
258
+ end
259
+
260
+ context "with controller as path" do
261
+ before do
262
+ # :index == "/"
263
+ app.controllers("/my_controller") { get(:index) { "content" } }
264
+ end
265
+
266
+ it "sets the action with the app name, controller name and action path" do
267
+ make_request
268
+ expect(last_transaction).to have_action("PadrinoTestApp:/my_controller#index")
269
+ end
270
+ end
271
+ end
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
277
+ end
@@ -0,0 +1,47 @@
1
+ if DependencyHelper.sinatra_present?
2
+ describe "Appsignal::Loaders::SinatraLoader" do
3
+ before { Appsignal.config = nil }
4
+
5
+ describe "#on_load" do
6
+ it "registers Sinatra default config" do
7
+ ::Sinatra::Application.settings.root = "/some/path"
8
+ load_loader(:sinatra)
9
+
10
+ expect(Appsignal::Config.loader_defaults).to include([
11
+ :sinatra,
12
+ {
13
+ :env => :test,
14
+ :root_path => "/some/path"
15
+ }
16
+ ])
17
+ end
18
+ end
19
+
20
+ describe "#on_start" do
21
+ after { uninstall_sinatra_integration }
22
+
23
+ def uninstall_sinatra_integration
24
+ expected_middleware = [
25
+ Rack::Events,
26
+ Appsignal::Rack::SinatraBaseInstrumentation
27
+ ]
28
+ Sinatra::Base.instance_variable_get(:@middleware).delete_if do |middleware|
29
+ expected_middleware.include?(middleware.first)
30
+ end
31
+ end
32
+
33
+ it "adds the instrumentation middleware to Sinatra::Base" do
34
+ load_loader(:sinatra)
35
+ start_loader(:sinatra)
36
+
37
+ middlewares = Sinatra::Base.middleware.to_a
38
+ expect(middlewares).to include(
39
+ [Rack::Events, [[instance_of(Appsignal::Rack::EventHandler)]], nil]
40
+ )
41
+ expect(middlewares).to include(
42
+ [Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
43
+ )
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,137 @@
1
+ describe Appsignal::Loaders do
2
+ describe ".register" do
3
+ before do
4
+ define_loader(:test_loader) do
5
+ def on_load
6
+ puts "do something on_load"
7
+ register_config_defaults(
8
+ :root_path => "/some/path",
9
+ :env => "test env",
10
+ :active => false
11
+ )
12
+ end
13
+ end
14
+ end
15
+
16
+ it "registers a loader" do
17
+ define_loader(:test_loader)
18
+ expect(Appsignal::Loaders.loaders).to have_key(:test_loader)
19
+ end
20
+ end
21
+
22
+ describe ".unregister" do
23
+ it "unregisters a loader" do
24
+ define_loader(:test_loader)
25
+ expect(Appsignal::Loaders.loaders).to have_key(:test_loader)
26
+
27
+ Appsignal::Loaders.unregister(:test_loader)
28
+ expect(Appsignal::Loaders.loaders).to_not have_key(:test_loader)
29
+ end
30
+ end
31
+
32
+ describe ".load" do
33
+ it "calls the Loader's on_loader method" do
34
+ Appsignal::Testing.store[:loader_loaded] = 0
35
+ define_loader(:test_loader) do
36
+ def on_load
37
+ Appsignal::Testing.store[:loader_loaded] += 1
38
+ end
39
+ end
40
+ Appsignal::Loaders.load(:test_loader)
41
+
42
+ expect(Appsignal::Testing.store[:loader_loaded]).to eq(1)
43
+ end
44
+
45
+ it "registers config defaults" do
46
+ define_loader(:test_loader) do
47
+ def on_load
48
+ register_config_defaults(:my_option => true)
49
+ end
50
+ end
51
+ Appsignal::Loaders.load(:test_loader)
52
+
53
+ expect(Appsignal::Config.loader_defaults).to eq([[:test_loader, { :my_option => true }]])
54
+ end
55
+
56
+ it "does not load errors that aren't registered" do
57
+ logs =
58
+ capture_logs do
59
+ Appsignal::Loaders.load(:unknown_loader)
60
+ end
61
+
62
+ expect(logs).to contains_log(:warn, "No loader found with the name 'unknown_loader'.")
63
+ end
64
+
65
+ it "loads the loader file on load" do
66
+ expect(Appsignal::Loaders.registered?(:loader_stub)).to be_falsy
67
+ Appsignal::Loaders.load(:loader_stub)
68
+
69
+ expect(Appsignal::Loaders.registered?(:loader_stub)).to be_truthy
70
+ end
71
+
72
+ it "does not error when a loader has no on_load method" do
73
+ define_loader(:test_loader) do
74
+ # Do nothing
75
+ end
76
+ Appsignal::Loaders.load(:test_loader)
77
+ end
78
+
79
+ it "logs an error when an error occurs on load" do
80
+ define_loader(:test_loader) do
81
+ def on_load
82
+ raise ExampleStandardError, "uh oh"
83
+ end
84
+ end
85
+ logs =
86
+ capture_logs do
87
+ Appsignal::Loaders.load(:test_loader)
88
+ end
89
+
90
+ expect(logs).to contains_log(
91
+ :error,
92
+ "An error occurred while loading the 'test_loader' loader: ExampleStandardError: uh oh"
93
+ )
94
+ end
95
+ end
96
+
97
+ describe ".start" do
98
+ it "starts all loaded loaders" do
99
+ Appsignal::Testing.store[:loader_started] = 0
100
+ define_loader(:test_loader) do
101
+ def on_start
102
+ Appsignal::Testing.store[:loader_started] += 1
103
+ end
104
+ end
105
+ Appsignal::Loaders.load(:test_loader)
106
+ Appsignal::Loaders.start
107
+
108
+ expect(Appsignal::Testing.store[:loader_started]).to eq(1)
109
+ end
110
+
111
+ it "does not error when a loader has no on_start method" do
112
+ define_loader(:test_loader) do
113
+ # Do nothing
114
+ end
115
+ Appsignal::Loaders.load(:test_loader)
116
+ Appsignal::Loaders.start
117
+ end
118
+
119
+ it "logs an error when an error occurs on start" do
120
+ define_loader(:test_loader) do
121
+ def on_start
122
+ raise ExampleStandardError, "uh oh"
123
+ end
124
+ end
125
+ logs =
126
+ capture_logs do
127
+ Appsignal::Loaders.load(:test_loader)
128
+ Appsignal::Loaders.start
129
+ end
130
+
131
+ expect(logs).to contains_log(
132
+ :error,
133
+ "An error occurred while starting the 'test_loader' loader: ExampleStandardError: uh oh"
134
+ )
135
+ end
136
+ end
137
+ end
@@ -6,7 +6,7 @@ describe Appsignal::Probes::SidekiqProbe do
6
6
  let(:redis_hostname) { "localhost" }
7
7
  let(:expected_default_tags) { { :hostname => "localhost" } }
8
8
  before do
9
- Appsignal.config = project_fixture_config
9
+ start_agent
10
10
 
11
11
  class SidekiqStats
12
12
  class << self