appsignal 3.9.2-java → 3.10.0-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/.github/workflows/ci.yml +3138 -0
- data/.rubocop.yml +28 -20
- data/.rubocop_todo.yml +7 -33
- data/CHANGELOG.md +130 -0
- data/README.md +0 -1
- data/Rakefile +80 -65
- data/appsignal.gemspec +1 -1
- data/build_matrix.yml +112 -184
- data/ext/base.rb +1 -1
- data/gemfiles/hanami-2.1.gemfile +7 -0
- data/gemfiles/webmachine1.gemfile +5 -4
- data/lib/appsignal/cli/diagnose.rb +1 -1
- data/lib/appsignal/config.rb +5 -1
- data/lib/appsignal/demo.rb +0 -1
- data/lib/appsignal/environment.rb +11 -2
- data/lib/appsignal/extension/jruby.rb +1 -1
- data/lib/appsignal/helpers/instrumentation.rb +164 -2
- data/lib/appsignal/hooks/active_job.rb +1 -6
- data/lib/appsignal/integrations/grape.rb +19 -47
- data/lib/appsignal/integrations/hanami.rb +8 -7
- data/lib/appsignal/integrations/padrino.rb +51 -52
- data/lib/appsignal/integrations/railtie.rb +0 -3
- data/lib/appsignal/integrations/rake.rb +46 -12
- data/lib/appsignal/integrations/sidekiq.rb +1 -11
- data/lib/appsignal/integrations/sinatra.rb +0 -1
- data/lib/appsignal/integrations/webmachine.rb +15 -9
- data/lib/appsignal/probes/gvl.rb +24 -2
- data/lib/appsignal/probes/sidekiq.rb +1 -1
- data/lib/appsignal/probes.rb +1 -1
- data/lib/appsignal/rack/abstract_middleware.rb +104 -33
- data/lib/appsignal/rack/body_wrapper.rb +143 -0
- data/lib/appsignal/rack/event_handler.rb +12 -3
- data/lib/appsignal/rack/generic_instrumentation.rb +5 -4
- data/lib/appsignal/rack/grape_middleware.rb +40 -0
- data/lib/appsignal/rack/hanami_middleware.rb +2 -12
- data/lib/appsignal/rack/instrumentation_middleware.rb +62 -0
- data/lib/appsignal/rack/rails_instrumentation.rb +14 -57
- data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -3
- data/lib/appsignal/rack/streaming_listener.rb +13 -59
- data/lib/appsignal/rack.rb +31 -0
- data/lib/appsignal/transaction.rb +50 -8
- data/lib/appsignal/utils/integration_memory_logger.rb +78 -0
- data/lib/appsignal/utils.rb +1 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +36 -33
- data/spec/.rubocop.yml +1 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +1 -1
- data/spec/lib/appsignal/cli/install_spec.rb +3 -3
- data/spec/lib/appsignal/config_spec.rb +8 -5
- data/spec/lib/appsignal/demo_spec.rb +38 -41
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +86 -167
- data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +8 -20
- data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +38 -84
- data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +16 -37
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +4 -4
- data/spec/lib/appsignal/hooks/activejob_spec.rb +111 -200
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +54 -91
- data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +14 -32
- data/spec/lib/appsignal/hooks/excon_spec.rb +8 -12
- data/spec/lib/appsignal/hooks/net_http_spec.rb +7 -42
- data/spec/lib/appsignal/hooks/rake_spec.rb +107 -34
- data/spec/lib/appsignal/hooks/redis_client_spec.rb +18 -30
- data/spec/lib/appsignal/hooks/redis_spec.rb +10 -16
- data/spec/lib/appsignal/hooks/resque_spec.rb +42 -62
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +33 -74
- data/spec/lib/appsignal/integrations/hanami_spec.rb +79 -21
- data/spec/lib/appsignal/integrations/http_spec.rb +12 -20
- data/spec/lib/appsignal/integrations/net_http_spec.rb +33 -0
- data/spec/lib/appsignal/integrations/object_spec.rb +29 -36
- data/spec/lib/appsignal/integrations/padrino_spec.rb +190 -163
- data/spec/lib/appsignal/integrations/que_spec.rb +43 -70
- data/spec/lib/appsignal/integrations/railtie_spec.rb +26 -67
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +86 -160
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +10 -3
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +77 -40
- data/spec/lib/appsignal/probes/gvl_spec.rb +80 -3
- data/spec/lib/appsignal/probes_spec.rb +7 -4
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +302 -105
- data/spec/lib/appsignal/rack/body_wrapper_spec.rb +263 -0
- data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -78
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +70 -27
- data/spec/lib/appsignal/rack/grape_middleware_spec.rb +234 -0
- data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +2 -16
- data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +38 -0
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +67 -131
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +36 -44
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +44 -139
- data/spec/lib/appsignal/transaction_spec.rb +239 -94
- data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +163 -0
- data/spec/lib/appsignal_spec.rb +556 -344
- data/spec/support/helpers/dependency_helper.rb +6 -1
- data/spec/support/helpers/std_streams_helper.rb +1 -1
- data/spec/support/helpers/transaction_helpers.rb +8 -0
- data/spec/support/matchers/transaction.rb +185 -0
- data/spec/support/mocks/dummy_app.rb +20 -0
- data/spec/support/shared_examples/instrument.rb +17 -12
- data/spec/support/testing.rb +18 -9
- metadata +20 -11
- data/.semaphore/semaphore.yml +0 -2347
- data/script/lint_git +0 -22
- data/spec/lib/appsignal/integrations/grape_spec.rb +0 -239
- data/spec/support/matchers/be_completed.rb +0 -5
- data/support/check_versions +0 -22
- /data/gemfiles/{hanami.gemfile → hanami-2.0.gemfile} +0 -0
data/spec/lib/appsignal_spec.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
describe Appsignal do
|
|
2
2
|
include EnvironmentMetadataHelper
|
|
3
|
+
around { |example| keep_transactions { example.run } }
|
|
3
4
|
|
|
4
5
|
before do
|
|
5
6
|
# Make sure we have a clean state because we want to test
|
|
@@ -21,21 +22,30 @@ describe Appsignal do
|
|
|
21
22
|
|
|
22
23
|
describe ".start" do
|
|
23
24
|
context "with no config set beforehand" do
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
let(:stdout_stream) { std_stream }
|
|
26
|
+
let(:stdout) { stdout_stream.read }
|
|
27
|
+
let(:stderr_stream) { std_stream }
|
|
28
|
+
let(:stderr) { stderr_stream.read }
|
|
29
|
+
before { ENV["APPSIGNAL_LOG"] = "stdout" }
|
|
30
|
+
|
|
31
|
+
it "does nothing when config is not set and there is no valid config in the env" do
|
|
29
32
|
expect(Appsignal::Extension).to_not receive(:start)
|
|
30
|
-
Appsignal.start
|
|
33
|
+
capture_std_streams(stdout_stream, stderr_stream) { Appsignal.start }
|
|
34
|
+
|
|
35
|
+
expect(stdout).to contains_log(
|
|
36
|
+
:error,
|
|
37
|
+
"appsignal: Not starting, no valid config for this environment"
|
|
38
|
+
)
|
|
31
39
|
end
|
|
32
40
|
|
|
33
41
|
it "should create a config from the env" do
|
|
34
42
|
ENV["APPSIGNAL_PUSH_API_KEY"] = "something"
|
|
35
43
|
expect(Appsignal::Extension).to receive(:start)
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
capture_std_streams(stdout_stream, stderr_stream) { Appsignal.start }
|
|
45
|
+
|
|
38
46
|
expect(Appsignal.config[:push_api_key]).to eq("something")
|
|
47
|
+
expect(stderr).to_not include("[ERROR]")
|
|
48
|
+
expect(stdout).to_not include("[ERROR]")
|
|
39
49
|
end
|
|
40
50
|
end
|
|
41
51
|
|
|
@@ -129,7 +139,7 @@ describe Appsignal do
|
|
|
129
139
|
|
|
130
140
|
describe ".forked" do
|
|
131
141
|
context "when not active" do
|
|
132
|
-
it "
|
|
142
|
+
it "does nothing" do
|
|
133
143
|
expect(Appsignal::Extension).to_not receive(:start)
|
|
134
144
|
|
|
135
145
|
Appsignal.forked
|
|
@@ -141,8 +151,8 @@ describe Appsignal do
|
|
|
141
151
|
Appsignal.config = project_fixture_config
|
|
142
152
|
end
|
|
143
153
|
|
|
144
|
-
it "
|
|
145
|
-
expect(Appsignal).to receive(:
|
|
154
|
+
it "starts the logger and extension" do
|
|
155
|
+
expect(Appsignal).to receive(:_start_logger)
|
|
146
156
|
expect(Appsignal::Extension).to receive(:start)
|
|
147
157
|
|
|
148
158
|
Appsignal.forked
|
|
@@ -222,28 +232,26 @@ describe Appsignal do
|
|
|
222
232
|
end
|
|
223
233
|
|
|
224
234
|
context "not active" do
|
|
225
|
-
|
|
226
|
-
let(:log_stream) { StringIO.new }
|
|
227
|
-
let(:log) { log_contents(log_stream) }
|
|
228
|
-
before do
|
|
229
|
-
Appsignal.config = project_fixture_config("not_active")
|
|
230
|
-
Appsignal.start
|
|
231
|
-
Appsignal.start_logger
|
|
232
|
-
Appsignal.internal_logger = test_logger(log_stream)
|
|
233
|
-
end
|
|
234
|
-
after { Appsignal.internal_logger = nil }
|
|
235
|
+
before { Appsignal.config = project_fixture_config("not_active") }
|
|
235
236
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
object = double
|
|
240
|
-
expect(object).to receive(:some_method).and_return(1)
|
|
237
|
+
describe ".monitor_transaction" do
|
|
238
|
+
it "does not create a transaction" do
|
|
239
|
+
object = double(:some_method => 1)
|
|
241
240
|
|
|
242
241
|
expect do
|
|
243
|
-
|
|
242
|
+
Appsignal.monitor_transaction("perform_job.nothing") do
|
|
244
243
|
object.some_method
|
|
245
|
-
end
|
|
246
|
-
end.to_not
|
|
244
|
+
end
|
|
245
|
+
end.to_not(change { created_transactions.count })
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it "returns the block's return value" do
|
|
249
|
+
object = double(:some_method => 1)
|
|
250
|
+
|
|
251
|
+
return_value = Appsignal.monitor_transaction("perform_job.nothing") do
|
|
252
|
+
object.some_method
|
|
253
|
+
end
|
|
254
|
+
expect(return_value).to eq 1
|
|
247
255
|
end
|
|
248
256
|
|
|
249
257
|
context "with an unknown event type" do
|
|
@@ -254,8 +262,11 @@ describe Appsignal do
|
|
|
254
262
|
end
|
|
255
263
|
|
|
256
264
|
it "logs an error" do
|
|
257
|
-
|
|
258
|
-
|
|
265
|
+
logs =
|
|
266
|
+
capture_logs do
|
|
267
|
+
Appsignal.monitor_transaction("unknown.sidekiq") {} # rubocop:disable Lint/EmptyBlock
|
|
268
|
+
end
|
|
269
|
+
expect(logs).to contains_log(
|
|
259
270
|
:error,
|
|
260
271
|
"Unrecognized name 'unknown.sidekiq': names must start with either 'perform_job' " \
|
|
261
272
|
"(for jobs and tasks) or 'process_action' (for HTTP requests)"
|
|
@@ -265,111 +276,149 @@ describe Appsignal do
|
|
|
265
276
|
end
|
|
266
277
|
|
|
267
278
|
describe ".listen_for_error" do
|
|
268
|
-
|
|
269
|
-
|
|
279
|
+
let(:error) { ExampleException.new("specific error") }
|
|
280
|
+
|
|
281
|
+
it "reraises the error" do
|
|
270
282
|
expect do
|
|
271
|
-
Appsignal.listen_for_error
|
|
272
|
-
raise error
|
|
273
|
-
end
|
|
283
|
+
Appsignal.listen_for_error { raise error }
|
|
274
284
|
end.to raise_error(error)
|
|
275
285
|
end
|
|
286
|
+
|
|
287
|
+
it "does not create a transaction" do
|
|
288
|
+
expect do
|
|
289
|
+
expect do
|
|
290
|
+
Appsignal.listen_for_error { raise error }
|
|
291
|
+
end.to raise_error(error)
|
|
292
|
+
end.to_not(change { created_transactions.count })
|
|
293
|
+
end
|
|
276
294
|
end
|
|
277
295
|
|
|
278
296
|
describe ".send_error" do
|
|
279
|
-
|
|
297
|
+
let(:error) { ExampleException.new("specific error") }
|
|
298
|
+
|
|
299
|
+
it "does not raise an error" do
|
|
300
|
+
Appsignal.send_error(error)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
it "does not create a transaction" do
|
|
280
304
|
expect do
|
|
281
|
-
Appsignal.send_error(
|
|
282
|
-
end.to_not
|
|
305
|
+
Appsignal.send_error(error)
|
|
306
|
+
end.to_not(change { created_transactions.count })
|
|
283
307
|
end
|
|
284
308
|
end
|
|
285
309
|
|
|
286
310
|
describe ".set_error" do
|
|
287
|
-
|
|
311
|
+
let(:error) { ExampleException.new("specific error") }
|
|
312
|
+
|
|
313
|
+
it "does not raise an error" do
|
|
314
|
+
Appsignal.set_error(error)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it "does not create a transaction" do
|
|
288
318
|
expect do
|
|
289
|
-
Appsignal.set_error(
|
|
290
|
-
end.to_not
|
|
319
|
+
Appsignal.set_error(error)
|
|
320
|
+
end.to_not(change { created_transactions.count })
|
|
291
321
|
end
|
|
292
322
|
end
|
|
293
323
|
|
|
294
|
-
describe ".
|
|
295
|
-
|
|
324
|
+
describe ".report_error" do
|
|
325
|
+
let(:error) { ExampleException.new("specific error") }
|
|
326
|
+
|
|
327
|
+
it "does not raise an error" do
|
|
328
|
+
Appsignal.report_error(error)
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
it "does not create a transaction" do
|
|
296
332
|
expect do
|
|
297
|
-
Appsignal.
|
|
298
|
-
end.to_not
|
|
333
|
+
Appsignal.report_error(error)
|
|
334
|
+
end.to_not(change { created_transactions.count })
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
describe ".set_namespace" do
|
|
339
|
+
it "does not raise an error" do
|
|
340
|
+
Appsignal.set_namespace("custom")
|
|
299
341
|
end
|
|
300
342
|
end
|
|
301
343
|
|
|
302
344
|
describe ".tag_request" do
|
|
303
|
-
it "
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
345
|
+
it "does not raise an error" do
|
|
346
|
+
Appsignal.tag_request(:tag => "tag")
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
describe ".set_custom_data" do
|
|
351
|
+
it "does not raise an error" do
|
|
352
|
+
Appsignal.set_custom_data(:data => "value")
|
|
307
353
|
end
|
|
308
354
|
end
|
|
309
355
|
end
|
|
310
356
|
|
|
311
357
|
context "with config and started" do
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
before do
|
|
315
|
-
Appsignal.config = project_fixture_config
|
|
316
|
-
Appsignal.start
|
|
317
|
-
Appsignal.start_logger
|
|
318
|
-
Appsignal.internal_logger = test_logger(log_stream)
|
|
319
|
-
end
|
|
320
|
-
after { Appsignal.internal_logger = nil }
|
|
358
|
+
before { start_agent }
|
|
359
|
+
around { |example| keep_transactions { example.run } }
|
|
321
360
|
|
|
322
361
|
describe ".monitor_transaction" do
|
|
323
362
|
context "with a successful call" do
|
|
324
|
-
it "
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
363
|
+
it "instruments and completes for a background job" do
|
|
364
|
+
return_value = nil
|
|
365
|
+
expect do
|
|
366
|
+
return_value =
|
|
367
|
+
Appsignal.monitor_transaction(
|
|
368
|
+
"perform_job.something",
|
|
369
|
+
{
|
|
370
|
+
:class => "BackgroundJob",
|
|
371
|
+
:method => "perform"
|
|
372
|
+
}
|
|
373
|
+
) do
|
|
374
|
+
:return_value
|
|
375
|
+
end
|
|
376
|
+
end.to(change { created_transactions.count }.by(1))
|
|
377
|
+
expect(return_value).to eq(:return_value)
|
|
378
|
+
|
|
379
|
+
transaction = last_transaction
|
|
380
|
+
expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
|
|
381
|
+
expect(transaction).to have_action("BackgroundJob#perform")
|
|
382
|
+
expect(transaction).to include_event("name" => "perform_job.something")
|
|
383
|
+
expect(transaction).to be_completed
|
|
340
384
|
end
|
|
341
385
|
|
|
342
|
-
it "
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
386
|
+
it "instruments and completes for a http request" do
|
|
387
|
+
return_value = nil
|
|
388
|
+
expect do
|
|
389
|
+
return_value =
|
|
390
|
+
Appsignal.monitor_transaction(
|
|
391
|
+
"process_action.something",
|
|
392
|
+
{
|
|
393
|
+
:controller => "BlogPostsController",
|
|
394
|
+
:action => "show"
|
|
395
|
+
}
|
|
396
|
+
) do
|
|
397
|
+
:return_value
|
|
398
|
+
end
|
|
399
|
+
end.to(change { created_transactions.count }.by(1))
|
|
400
|
+
expect(return_value).to eq(:return_value)
|
|
348
401
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
)
|
|
353
|
-
|
|
354
|
-
expect(current.namespace).to eq Appsignal::Transaction::HTTP_REQUEST
|
|
355
|
-
expect(current.request).to be_a(::Rack::Request)
|
|
356
|
-
object.some_method
|
|
357
|
-
end
|
|
402
|
+
transaction = last_transaction
|
|
403
|
+
expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
404
|
+
expect(transaction).to have_action("BlogPostsController#show")
|
|
405
|
+
expect(transaction).to include_event("name" => "process_action.something")
|
|
406
|
+
expect(transaction).to be_completed
|
|
358
407
|
end
|
|
359
408
|
end
|
|
360
409
|
|
|
361
410
|
context "with an erroring call" do
|
|
362
|
-
let(:error) { ExampleException.new }
|
|
363
|
-
|
|
364
|
-
it "should add the error to the current transaction and complete" do
|
|
365
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_error).with(error)
|
|
366
|
-
expect(Appsignal::Transaction).to receive(:complete_current!)
|
|
411
|
+
let(:error) { ExampleException.new("error message") }
|
|
367
412
|
|
|
413
|
+
it "adds the error to the current transaction and complete" do
|
|
368
414
|
expect do
|
|
369
415
|
Appsignal.monitor_transaction("perform_job.something") do
|
|
370
416
|
raise error
|
|
371
417
|
end
|
|
372
418
|
end.to raise_error(error)
|
|
419
|
+
|
|
420
|
+
expect(last_transaction).to have_error("ExampleException", "error message")
|
|
421
|
+
expect(last_transaction).to be_completed
|
|
373
422
|
end
|
|
374
423
|
end
|
|
375
424
|
|
|
@@ -381,8 +430,11 @@ describe Appsignal do
|
|
|
381
430
|
end
|
|
382
431
|
|
|
383
432
|
it "logs an error" do
|
|
384
|
-
|
|
385
|
-
|
|
433
|
+
logs =
|
|
434
|
+
capture_logs do
|
|
435
|
+
Appsignal.monitor_transaction("unknown.sidekiq") {} # rubocop:disable Lint/EmptyBlock
|
|
436
|
+
end
|
|
437
|
+
expect(logs).to contains_log(
|
|
386
438
|
:error,
|
|
387
439
|
"Unrecognized name 'unknown.sidekiq': names must start with either 'perform_job' " \
|
|
388
440
|
"(for jobs and tasks) or 'process_action' (for HTTP requests)"
|
|
@@ -392,8 +444,6 @@ describe Appsignal do
|
|
|
392
444
|
end
|
|
393
445
|
|
|
394
446
|
describe ".monitor_single_transaction" do
|
|
395
|
-
around { |example| keep_transactions { example.run } }
|
|
396
|
-
|
|
397
447
|
context "with a successful call" do
|
|
398
448
|
it "calls monitor_transaction and Appsignal.stop" do
|
|
399
449
|
expect(Appsignal).to receive(:stop)
|
|
@@ -407,18 +457,8 @@ describe Appsignal do
|
|
|
407
457
|
end
|
|
408
458
|
|
|
409
459
|
transaction = last_transaction
|
|
410
|
-
|
|
411
|
-
expect(
|
|
412
|
-
"action" => "my_controller#my_action"
|
|
413
|
-
)
|
|
414
|
-
expect(transaction_hash["events"]).to match([
|
|
415
|
-
hash_including(
|
|
416
|
-
"name" => "perform_job.something",
|
|
417
|
-
"title" => "",
|
|
418
|
-
"body" => "",
|
|
419
|
-
"body_format" => Appsignal::EventFormatter::DEFAULT
|
|
420
|
-
)
|
|
421
|
-
])
|
|
460
|
+
expect(transaction).to have_action("my_controller#my_action")
|
|
461
|
+
expect(transaction).to include_event("name" => "perform_job.something")
|
|
422
462
|
end
|
|
423
463
|
end
|
|
424
464
|
|
|
@@ -439,75 +479,131 @@ describe Appsignal do
|
|
|
439
479
|
end.to raise_error(error)
|
|
440
480
|
|
|
441
481
|
transaction = last_transaction
|
|
442
|
-
|
|
443
|
-
expect(
|
|
444
|
-
"action" => "my_controller#my_action"
|
|
445
|
-
)
|
|
446
|
-
expect(transaction_hash["events"]).to match([
|
|
447
|
-
hash_including(
|
|
448
|
-
"name" => "perform_job.something",
|
|
449
|
-
"title" => "",
|
|
450
|
-
"body" => "",
|
|
451
|
-
"body_format" => Appsignal::EventFormatter::DEFAULT
|
|
452
|
-
)
|
|
453
|
-
])
|
|
482
|
+
expect(transaction).to have_action("my_controller#my_action")
|
|
483
|
+
expect(transaction).to include_event("name" => "perform_job.something")
|
|
454
484
|
end
|
|
455
485
|
end
|
|
456
486
|
end
|
|
457
487
|
|
|
458
488
|
describe ".tag_request" do
|
|
459
|
-
|
|
460
|
-
around do |example|
|
|
461
|
-
start_agent
|
|
462
|
-
with_current_transaction transaction do
|
|
463
|
-
keep_transactions { example.run }
|
|
464
|
-
end
|
|
465
|
-
end
|
|
489
|
+
before { start_agent }
|
|
466
490
|
|
|
467
491
|
context "with transaction" do
|
|
468
|
-
|
|
492
|
+
let(:transaction) { http_request_transaction }
|
|
493
|
+
before { set_current_transaction(transaction) }
|
|
494
|
+
|
|
495
|
+
it "sets tags on the current transaction" do
|
|
469
496
|
Appsignal.tag_request("a" => "b")
|
|
470
|
-
transaction.complete # Manually trigger transaction sampling
|
|
471
497
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
"tags" => { "a" => "b" }
|
|
475
|
-
)
|
|
476
|
-
)
|
|
498
|
+
transaction._sample
|
|
499
|
+
expect(transaction).to include_tags("a" => "b")
|
|
477
500
|
end
|
|
478
501
|
end
|
|
479
502
|
|
|
480
503
|
context "without transaction" do
|
|
481
504
|
let(:transaction) { nil }
|
|
482
505
|
|
|
483
|
-
it "
|
|
506
|
+
it "does not set tags on the transaction" do
|
|
484
507
|
expect(Appsignal.tag_request).to be_falsy
|
|
508
|
+
Appsignal.tag_request("a" => "b")
|
|
509
|
+
|
|
510
|
+
expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_tags)
|
|
485
511
|
end
|
|
486
512
|
end
|
|
487
513
|
|
|
488
|
-
it "
|
|
489
|
-
expect(Appsignal).to
|
|
514
|
+
it "also listens to tag_job" do
|
|
515
|
+
expect(Appsignal.method(:tag_job)).to eq(Appsignal.method(:tag_request))
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
it "also listens to set_tags" do
|
|
519
|
+
expect(Appsignal.method(:set_tags)).to eq(Appsignal.method(:tag_request))
|
|
490
520
|
end
|
|
491
521
|
end
|
|
492
522
|
|
|
493
|
-
describe ".
|
|
494
|
-
before
|
|
523
|
+
describe ".set_params" do
|
|
524
|
+
before do
|
|
525
|
+
start_agent
|
|
526
|
+
end
|
|
495
527
|
|
|
496
528
|
context "with transaction" do
|
|
497
529
|
let(:transaction) { http_request_transaction }
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
530
|
+
before { set_current_transaction(transaction) }
|
|
531
|
+
|
|
532
|
+
it "sets parameters on the transaction" do
|
|
533
|
+
Appsignal.set_params("param1" => "value1")
|
|
534
|
+
|
|
535
|
+
transaction._sample
|
|
536
|
+
expect(transaction).to include_params("param1" => "value1")
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
it "overwrites the params if called multiple times" do
|
|
540
|
+
Appsignal.set_params("param1" => "value1")
|
|
541
|
+
Appsignal.set_params("param2" => "value2")
|
|
542
|
+
|
|
543
|
+
transaction._sample
|
|
544
|
+
expect(transaction).to include_params("param2" => "value2")
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
it "sets parameters with a block on the transaction" do
|
|
548
|
+
Appsignal.set_params { { "param1" => "value1" } }
|
|
549
|
+
|
|
550
|
+
transaction._sample
|
|
551
|
+
expect(transaction).to include_params("param1" => "value1")
|
|
552
|
+
end
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
context "without transaction" do
|
|
556
|
+
it "does not set tags on the transaction" do
|
|
557
|
+
Appsignal.set_params("a" => "b")
|
|
558
|
+
|
|
559
|
+
expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_params)
|
|
560
|
+
end
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
describe ".set_custom_data" do
|
|
565
|
+
before { start_agent }
|
|
566
|
+
|
|
567
|
+
context "with transaction" do
|
|
568
|
+
let(:transaction) { http_request_transaction }
|
|
569
|
+
before { set_current_transaction transaction }
|
|
570
|
+
|
|
571
|
+
it "sets custom data on the current transaction" do
|
|
572
|
+
Appsignal.set_custom_data(
|
|
573
|
+
:user => { :id => 123 },
|
|
574
|
+
:organization => { :slug => "appsignal" }
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
transaction._sample
|
|
578
|
+
expect(transaction).to include_custom_data(
|
|
579
|
+
"user" => { "id" => 123 },
|
|
580
|
+
"organization" => { "slug" => "appsignal" }
|
|
581
|
+
)
|
|
503
582
|
end
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
context "without transaction" do
|
|
586
|
+
it "does not set tags on the transaction" do
|
|
587
|
+
Appsignal.set_custom_data(
|
|
588
|
+
:user => { :id => 123 },
|
|
589
|
+
:organization => { :slug => "appsignal" }
|
|
590
|
+
)
|
|
504
591
|
|
|
505
|
-
|
|
506
|
-
expect(transaction).to receive(:add_breadcrumb)
|
|
507
|
-
.with("Network", "http", "User made network request", { :response => 200 }, fixed_time)
|
|
592
|
+
expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_custom_data)
|
|
508
593
|
end
|
|
594
|
+
end
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
describe ".add_breadcrumb" do
|
|
598
|
+
around do |example|
|
|
599
|
+
start_agent
|
|
600
|
+
with_current_transaction(transaction) { example.run }
|
|
601
|
+
end
|
|
509
602
|
|
|
510
|
-
|
|
603
|
+
context "with transaction" do
|
|
604
|
+
let(:transaction) { http_request_transaction }
|
|
605
|
+
|
|
606
|
+
it "adds the breadcrumb to the transaction" do
|
|
511
607
|
Appsignal.add_breadcrumb(
|
|
512
608
|
"Network",
|
|
513
609
|
"http",
|
|
@@ -515,13 +611,22 @@ describe Appsignal do
|
|
|
515
611
|
{ :response => 200 },
|
|
516
612
|
fixed_time
|
|
517
613
|
)
|
|
614
|
+
|
|
615
|
+
transaction._sample
|
|
616
|
+
expect(transaction).to include_breadcrumb(
|
|
617
|
+
"http",
|
|
618
|
+
"Network",
|
|
619
|
+
"User made network request",
|
|
620
|
+
{ "response" => 200 },
|
|
621
|
+
fixed_time
|
|
622
|
+
)
|
|
518
623
|
end
|
|
519
624
|
end
|
|
520
625
|
|
|
521
626
|
context "without transaction" do
|
|
522
627
|
let(:transaction) { nil }
|
|
523
628
|
|
|
524
|
-
it "
|
|
629
|
+
it "does not add a breadcrumb to any transaction" do
|
|
525
630
|
expect(Appsignal.add_breadcrumb("Network", "http")).to be_falsy
|
|
526
631
|
end
|
|
527
632
|
end
|
|
@@ -550,13 +655,15 @@ describe Appsignal do
|
|
|
550
655
|
end
|
|
551
656
|
|
|
552
657
|
it "should not raise an exception when out of range" do
|
|
553
|
-
expect(Appsignal::Extension).to receive(:set_gauge).with(
|
|
554
|
-
|
|
658
|
+
expect(Appsignal::Extension).to receive(:set_gauge).with(
|
|
659
|
+
"key",
|
|
660
|
+
10,
|
|
661
|
+
Appsignal::Extension.data_map_new
|
|
662
|
+
).and_raise(RangeError)
|
|
555
663
|
expect(Appsignal.internal_logger).to receive(:warn)
|
|
556
664
|
.with("Gauge value 10 for key 'key' is too big")
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
end.to_not raise_error
|
|
665
|
+
|
|
666
|
+
Appsignal.set_gauge("key", 10)
|
|
560
667
|
end
|
|
561
668
|
end
|
|
562
669
|
|
|
@@ -634,9 +741,8 @@ describe Appsignal do
|
|
|
634
741
|
.with("key", 10, Appsignal::Extension.data_map_new).and_raise(RangeError)
|
|
635
742
|
expect(Appsignal.internal_logger).to receive(:warn)
|
|
636
743
|
.with("Counter value 10 for key 'key' is too big")
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
end.to_not raise_error
|
|
744
|
+
|
|
745
|
+
Appsignal.increment_counter("key", 10)
|
|
640
746
|
end
|
|
641
747
|
end
|
|
642
748
|
|
|
@@ -664,9 +770,8 @@ describe Appsignal do
|
|
|
664
770
|
.with("key", 10, Appsignal::Extension.data_map_new).and_raise(RangeError)
|
|
665
771
|
expect(Appsignal.internal_logger).to receive(:warn)
|
|
666
772
|
.with("Distribution value 10 for key 'key' is too big")
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
end.to_not raise_error
|
|
773
|
+
|
|
774
|
+
Appsignal.add_distribution_value("key", 10)
|
|
670
775
|
end
|
|
671
776
|
end
|
|
672
777
|
end
|
|
@@ -706,46 +811,39 @@ describe Appsignal do
|
|
|
706
811
|
end
|
|
707
812
|
|
|
708
813
|
describe ".send_error" do
|
|
709
|
-
let(:
|
|
710
|
-
Appsignal::Transaction.new(
|
|
711
|
-
SecureRandom.uuid,
|
|
712
|
-
Appsignal::Transaction::HTTP_REQUEST,
|
|
713
|
-
Appsignal::Transaction::GenericRequest.new({})
|
|
714
|
-
)
|
|
715
|
-
end
|
|
716
|
-
let(:error) { ExampleException.new }
|
|
814
|
+
let(:error) { ExampleException.new("error message") }
|
|
717
815
|
let(:err_stream) { std_stream }
|
|
718
816
|
let(:stderr) { err_stream.read }
|
|
719
|
-
around
|
|
817
|
+
around do |example|
|
|
818
|
+
keep_transactions { example.run }
|
|
819
|
+
end
|
|
720
820
|
|
|
721
821
|
it "sends the error to AppSignal" do
|
|
722
|
-
expect(
|
|
723
|
-
kind_of(String),
|
|
724
|
-
Appsignal::Transaction::HTTP_REQUEST,
|
|
725
|
-
kind_of(Appsignal::Transaction::GenericRequest)
|
|
726
|
-
).and_return(transaction)
|
|
727
|
-
expect(transaction).to receive(:set_error).with(error)
|
|
728
|
-
expect(transaction).to_not receive(:set_tags)
|
|
729
|
-
expect(transaction).to receive(:complete)
|
|
822
|
+
expect { Appsignal.send_error(error) }.to(change { created_transactions.count }.by(1))
|
|
730
823
|
|
|
731
|
-
|
|
824
|
+
transaction = last_transaction
|
|
825
|
+
expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
826
|
+
expect(transaction).to_not have_action
|
|
827
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
|
828
|
+
expect(transaction).to_not include_tags
|
|
829
|
+
expect(transaction).to be_completed
|
|
732
830
|
end
|
|
733
831
|
|
|
734
832
|
context "when given error is not an Exception" do
|
|
735
|
-
let(:error) {
|
|
833
|
+
let(:error) { "string value" }
|
|
736
834
|
|
|
737
835
|
it "logs an error message" do
|
|
738
|
-
|
|
836
|
+
logs = capture_logs { Appsignal.send_error(error) }
|
|
837
|
+
expect(logs).to contains_log(
|
|
838
|
+
:error,
|
|
739
839
|
"Appsignal.send_error: Cannot send error. " \
|
|
740
840
|
"The given value is not an exception: #{error.inspect}"
|
|
741
841
|
)
|
|
742
842
|
end
|
|
743
843
|
|
|
744
844
|
it "does not send the error" do
|
|
745
|
-
expect(
|
|
845
|
+
expect { Appsignal.send_error(error) }.to_not(change { created_transactions.count })
|
|
746
846
|
end
|
|
747
|
-
|
|
748
|
-
after { Appsignal.send_error(error) }
|
|
749
847
|
end
|
|
750
848
|
|
|
751
849
|
context "with tags" do
|
|
@@ -760,13 +858,7 @@ describe Appsignal do
|
|
|
760
858
|
end.to change { created_transactions.count }.by(1)
|
|
761
859
|
end
|
|
762
860
|
|
|
763
|
-
|
|
764
|
-
transaction_hash = transaction.to_h
|
|
765
|
-
expect(transaction_hash).to include(
|
|
766
|
-
"sample_data" => hash_including(
|
|
767
|
-
"tags" => { "a" => "a", "b" => "b" }
|
|
768
|
-
)
|
|
769
|
-
)
|
|
861
|
+
expect(last_transaction).to include_tags("a" => "a", "b" => "b")
|
|
770
862
|
|
|
771
863
|
message = "The tags argument for `Appsignal.send_error` is deprecated. " \
|
|
772
864
|
"Please use the block method to set tags instead.\n\n" \
|
|
@@ -791,9 +883,7 @@ describe Appsignal do
|
|
|
791
883
|
end.to change { created_transactions.count }.by(1)
|
|
792
884
|
end
|
|
793
885
|
|
|
794
|
-
|
|
795
|
-
transaction_hash = transaction.to_h
|
|
796
|
-
expect(transaction_hash).to include("namespace" => namespace)
|
|
886
|
+
expect(last_transaction).to have_namespace(namespace)
|
|
797
887
|
|
|
798
888
|
message = "The namespace argument for `Appsignal.send_error` is deprecated. " \
|
|
799
889
|
"Please use the block method to set the namespace instead.\n\n" \
|
|
@@ -808,23 +898,15 @@ describe Appsignal do
|
|
|
808
898
|
|
|
809
899
|
context "when given a block" do
|
|
810
900
|
it "yields the transaction and allows additional metadata to be set" do
|
|
811
|
-
captured_transaction = nil
|
|
812
901
|
keep_transactions do
|
|
813
902
|
Appsignal.send_error(StandardError.new("my_error")) do |transaction|
|
|
814
|
-
captured_transaction = transaction
|
|
815
903
|
transaction.set_action("my_action")
|
|
816
904
|
transaction.set_namespace("my_namespace")
|
|
817
905
|
end
|
|
818
906
|
end
|
|
819
|
-
expect(
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
"error" => {
|
|
823
|
-
"name" => "StandardError",
|
|
824
|
-
"message" => "my_error",
|
|
825
|
-
"backtrace" => kind_of(String) # TODO: should be Array
|
|
826
|
-
}
|
|
827
|
-
)
|
|
907
|
+
expect(last_transaction).to have_namespace("my_namespace")
|
|
908
|
+
expect(last_transaction).to have_action("my_action")
|
|
909
|
+
expect(last_transaction).to have_error("StandardError", "my_error")
|
|
828
910
|
end
|
|
829
911
|
end
|
|
830
912
|
end
|
|
@@ -841,17 +923,10 @@ describe Appsignal do
|
|
|
841
923
|
end.to raise_error(ExampleException, "I am an exception")
|
|
842
924
|
end.to change { created_transactions.count }.by(1)
|
|
843
925
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
"backtrace" => kind_of(String)
|
|
849
|
-
},
|
|
850
|
-
"namespace" => Appsignal::Transaction::HTTP_REQUEST, # Default namespace
|
|
851
|
-
"sample_data" => hash_including(
|
|
852
|
-
"tags" => {}
|
|
853
|
-
)
|
|
854
|
-
)
|
|
926
|
+
# Default namespace
|
|
927
|
+
expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
928
|
+
expect(last_transaction).to have_error("ExampleException", "I am an exception")
|
|
929
|
+
expect(last_transaction).to_not include_tags
|
|
855
930
|
end
|
|
856
931
|
|
|
857
932
|
context "with tags" do
|
|
@@ -864,17 +939,10 @@ describe Appsignal do
|
|
|
864
939
|
end.to raise_error(ExampleException, "I am an exception")
|
|
865
940
|
end.to change { created_transactions.count }.by(1)
|
|
866
941
|
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
"backtrace" => kind_of(String)
|
|
872
|
-
},
|
|
873
|
-
"namespace" => Appsignal::Transaction::HTTP_REQUEST, # Default namespace
|
|
874
|
-
"sample_data" => hash_including(
|
|
875
|
-
"tags" => { "foo" => "bar" }
|
|
876
|
-
)
|
|
877
|
-
)
|
|
942
|
+
# Default namespace
|
|
943
|
+
expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
944
|
+
expect(last_transaction).to have_error("ExampleException", "I am an exception")
|
|
945
|
+
expect(last_transaction).to include_tags("foo" => "bar")
|
|
878
946
|
end
|
|
879
947
|
end
|
|
880
948
|
|
|
@@ -888,17 +956,10 @@ describe Appsignal do
|
|
|
888
956
|
end.to raise_error(ExampleException, "I am an exception")
|
|
889
957
|
end.to change { created_transactions.count }.by(1)
|
|
890
958
|
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
"backtrace" => kind_of(String)
|
|
896
|
-
},
|
|
897
|
-
"namespace" => "custom_namespace",
|
|
898
|
-
"sample_data" => hash_including(
|
|
899
|
-
"tags" => {}
|
|
900
|
-
)
|
|
901
|
-
)
|
|
959
|
+
# Default namespace
|
|
960
|
+
expect(last_transaction).to have_namespace("custom_namespace")
|
|
961
|
+
expect(last_transaction).to have_error("ExampleException", "I am an exception")
|
|
962
|
+
expect(last_transaction).to_not include_tags
|
|
902
963
|
end
|
|
903
964
|
end
|
|
904
965
|
end
|
|
@@ -907,42 +968,56 @@ describe Appsignal do
|
|
|
907
968
|
let(:err_stream) { std_stream }
|
|
908
969
|
let(:stderr) { err_stream.read }
|
|
909
970
|
let(:error) { ExampleException.new("I am an exception") }
|
|
910
|
-
|
|
971
|
+
let(:transaction) { http_request_transaction }
|
|
911
972
|
around { |example| keep_transactions { example.run } }
|
|
912
973
|
|
|
913
974
|
context "when there is an active transaction" do
|
|
914
|
-
|
|
915
|
-
expect(transaction).to receive(:set_error).with(error)
|
|
916
|
-
expect(transaction).to_not receive(:set_tags)
|
|
917
|
-
expect(transaction).to_not receive(:set_namespace)
|
|
975
|
+
before { set_current_transaction(transaction) }
|
|
918
976
|
|
|
977
|
+
it "adds the error to the active transaction" do
|
|
919
978
|
Appsignal.set_error(error)
|
|
979
|
+
|
|
980
|
+
transaction._sample
|
|
981
|
+
expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
982
|
+
expect(transaction).to have_error("ExampleException", "I am an exception")
|
|
983
|
+
expect(transaction).to_not include_tags
|
|
920
984
|
end
|
|
921
985
|
|
|
922
986
|
context "when the error is not an Exception" do
|
|
923
987
|
let(:error) { Object.new }
|
|
924
988
|
|
|
989
|
+
it "does not set an error" do
|
|
990
|
+
silence { Appsignal.set_error(error) }
|
|
991
|
+
|
|
992
|
+
transaction._sample
|
|
993
|
+
expect(transaction).to_not have_error
|
|
994
|
+
expect(transaction).to_not include_tags
|
|
995
|
+
end
|
|
996
|
+
|
|
925
997
|
it "logs an error" do
|
|
926
|
-
|
|
998
|
+
logs = capture_logs { Appsignal.set_error(error) }
|
|
999
|
+
expect(logs).to contains_log(
|
|
1000
|
+
:error,
|
|
927
1001
|
"Appsignal.set_error: Cannot set error. " \
|
|
928
1002
|
"The given value is not an exception: #{error.inspect}"
|
|
929
1003
|
)
|
|
930
|
-
expect(transaction).to_not receive(:set_error)
|
|
931
|
-
expect(transaction).to_not receive(:set_tags)
|
|
932
|
-
expect(transaction).to_not receive(:set_namespace)
|
|
933
|
-
|
|
934
|
-
Appsignal.set_error(error)
|
|
935
1004
|
end
|
|
936
1005
|
end
|
|
937
1006
|
|
|
938
1007
|
context "with tags" do
|
|
939
1008
|
let(:tags) { { "foo" => "bar" } }
|
|
940
1009
|
|
|
941
|
-
it "
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1010
|
+
it "tags the transaction" do
|
|
1011
|
+
silence(:allowed => ["set_error", "The tags argument for"]) do
|
|
1012
|
+
Appsignal.set_error(error, tags)
|
|
1013
|
+
end
|
|
1014
|
+
|
|
1015
|
+
transaction._sample
|
|
1016
|
+
expect(transaction).to have_error(error)
|
|
1017
|
+
expect(transaction).to include_tags(tags)
|
|
1018
|
+
end
|
|
945
1019
|
|
|
1020
|
+
it "prints a deprecation warning and tags the transaction" do
|
|
946
1021
|
logs = capture_logs do
|
|
947
1022
|
capture_std_streams(std_stream, err_stream) do
|
|
948
1023
|
Appsignal.set_error(error, tags)
|
|
@@ -963,11 +1038,17 @@ describe Appsignal do
|
|
|
963
1038
|
context "with namespace" do
|
|
964
1039
|
let(:namespace) { "admin" }
|
|
965
1040
|
|
|
966
|
-
it "
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1041
|
+
it "sets the namespace on the transaction" do
|
|
1042
|
+
silence(:allowed => ["set_error", "The namespace argument for"]) do
|
|
1043
|
+
Appsignal.set_error(error, nil, namespace)
|
|
1044
|
+
end
|
|
970
1045
|
|
|
1046
|
+
expect(transaction).to have_error("ExampleException", "I am an exception")
|
|
1047
|
+
expect(transaction).to have_namespace(namespace)
|
|
1048
|
+
expect(transaction).to_not include_tags
|
|
1049
|
+
end
|
|
1050
|
+
|
|
1051
|
+
it "prints a deprecation warning andsets the namespace on the transaction" do
|
|
971
1052
|
logs = capture_logs do
|
|
972
1053
|
capture_std_streams(std_stream, err_stream) do
|
|
973
1054
|
Appsignal.set_error(error, nil, namespace)
|
|
@@ -987,135 +1068,232 @@ describe Appsignal do
|
|
|
987
1068
|
|
|
988
1069
|
context "when given a block" do
|
|
989
1070
|
it "yields the transaction and allows additional metadata to be set" do
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
captured_transaction = transaction
|
|
994
|
-
transaction.set_action("my_action")
|
|
995
|
-
transaction.set_namespace("my_namespace")
|
|
996
|
-
end
|
|
1071
|
+
Appsignal.set_error(StandardError.new("my_error")) do |t|
|
|
1072
|
+
t.set_action("my_action")
|
|
1073
|
+
t.set_namespace("my_namespace")
|
|
997
1074
|
end
|
|
998
1075
|
|
|
999
|
-
expect(transaction).to
|
|
1000
|
-
expect(
|
|
1001
|
-
|
|
1002
|
-
"action" => "my_action",
|
|
1003
|
-
"error" => {
|
|
1004
|
-
"name" => "StandardError",
|
|
1005
|
-
"message" => "my_error",
|
|
1006
|
-
"backtrace" => kind_of(String)
|
|
1007
|
-
}
|
|
1008
|
-
)
|
|
1076
|
+
expect(transaction).to have_namespace("my_namespace")
|
|
1077
|
+
expect(transaction).to have_action("my_action")
|
|
1078
|
+
expect(transaction).to have_error("StandardError", "my_error")
|
|
1009
1079
|
end
|
|
1010
1080
|
end
|
|
1011
1081
|
end
|
|
1012
1082
|
|
|
1013
1083
|
context "when there is no active transaction" do
|
|
1014
1084
|
it "does nothing" do
|
|
1015
|
-
|
|
1085
|
+
Appsignal.set_error(error)
|
|
1016
1086
|
|
|
1017
|
-
expect(transaction).to_not
|
|
1087
|
+
expect(transaction).to_not have_error
|
|
1088
|
+
end
|
|
1089
|
+
end
|
|
1090
|
+
end
|
|
1018
1091
|
|
|
1019
|
-
|
|
1092
|
+
describe ".report_error" do
|
|
1093
|
+
let(:err_stream) { std_stream }
|
|
1094
|
+
let(:stderr) { err_stream.read }
|
|
1095
|
+
let(:error) { ExampleException.new("error message") }
|
|
1096
|
+
before { start_agent }
|
|
1097
|
+
around { |example| keep_transactions { example.run } }
|
|
1098
|
+
|
|
1099
|
+
context "when the error is not an Exception" do
|
|
1100
|
+
let(:error) { Object.new }
|
|
1101
|
+
|
|
1102
|
+
it "does not set an error" do
|
|
1103
|
+
silence { Appsignal.report_error(error) }
|
|
1104
|
+
|
|
1105
|
+
expect(last_transaction).to_not have_error
|
|
1106
|
+
end
|
|
1107
|
+
|
|
1108
|
+
it "logs an error" do
|
|
1109
|
+
logs = capture_logs { Appsignal.report_error(error) }
|
|
1110
|
+
expect(logs).to contains_log(
|
|
1111
|
+
:error,
|
|
1112
|
+
"Appsignal.report_error: Cannot set error. " \
|
|
1113
|
+
"The given value is not an exception: #{error.inspect}"
|
|
1114
|
+
)
|
|
1115
|
+
end
|
|
1116
|
+
end
|
|
1117
|
+
|
|
1118
|
+
context "when there is no active transaction" do
|
|
1119
|
+
it "creates a new transaction" do
|
|
1120
|
+
expect do
|
|
1121
|
+
Appsignal.report_error(error)
|
|
1122
|
+
end.to(change { created_transactions.count }.by(1))
|
|
1123
|
+
end
|
|
1124
|
+
|
|
1125
|
+
it "completes the transaction" do
|
|
1126
|
+
Appsignal.report_error(error)
|
|
1127
|
+
|
|
1128
|
+
expect(last_transaction).to be_completed
|
|
1129
|
+
end
|
|
1130
|
+
|
|
1131
|
+
context "when given a block" do
|
|
1132
|
+
it "yields the transaction and allows additional metadata to be set" do
|
|
1133
|
+
Appsignal.report_error(error) do |t|
|
|
1134
|
+
t.set_action("my_action")
|
|
1135
|
+
t.set_namespace("my_namespace")
|
|
1136
|
+
t.set_tags(:tag1 => "value1")
|
|
1137
|
+
end
|
|
1138
|
+
|
|
1139
|
+
transaction = last_transaction
|
|
1140
|
+
expect(transaction).to have_namespace("my_namespace")
|
|
1141
|
+
expect(transaction).to have_action("my_action")
|
|
1142
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
|
1143
|
+
expect(transaction).to include_tags("tag1" => "value1")
|
|
1144
|
+
expect(transaction).to be_completed
|
|
1145
|
+
end
|
|
1146
|
+
end
|
|
1147
|
+
end
|
|
1148
|
+
|
|
1149
|
+
context "when there is an active transaction" do
|
|
1150
|
+
let(:transaction) { http_request_transaction }
|
|
1151
|
+
before { set_current_transaction(transaction) }
|
|
1152
|
+
|
|
1153
|
+
it "adds the error to the active transaction" do
|
|
1154
|
+
Appsignal.report_error(error)
|
|
1155
|
+
|
|
1156
|
+
expect(last_transaction).to eq(transaction)
|
|
1157
|
+
transaction._sample
|
|
1158
|
+
expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
1159
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
|
1160
|
+
end
|
|
1161
|
+
|
|
1162
|
+
it "does not complete the transaction" do
|
|
1163
|
+
Appsignal.report_error(error)
|
|
1164
|
+
|
|
1165
|
+
expect(last_transaction).to_not be_completed
|
|
1166
|
+
end
|
|
1167
|
+
|
|
1168
|
+
context "when given a block" do
|
|
1169
|
+
it "yields the transaction and allows additional metadata to be set" do
|
|
1170
|
+
Appsignal.report_error(error) do |t|
|
|
1171
|
+
t.set_action("my_action")
|
|
1172
|
+
t.set_namespace("my_namespace")
|
|
1173
|
+
t.set_tags(:tag1 => "value1")
|
|
1174
|
+
end
|
|
1175
|
+
|
|
1176
|
+
transaction._sample
|
|
1177
|
+
expect(transaction).to have_namespace("my_namespace")
|
|
1178
|
+
expect(transaction).to have_action("my_action")
|
|
1179
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
|
1180
|
+
expect(transaction).to include_tags("tag1" => "value1")
|
|
1181
|
+
expect(transaction).to_not be_completed
|
|
1182
|
+
end
|
|
1020
1183
|
end
|
|
1021
1184
|
end
|
|
1022
1185
|
end
|
|
1023
1186
|
|
|
1024
1187
|
describe ".set_action" do
|
|
1025
|
-
|
|
1188
|
+
around { |example| keep_transactions { example.run } }
|
|
1026
1189
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1190
|
+
context "with current transaction" do
|
|
1191
|
+
before { set_current_transaction(transaction) }
|
|
1029
1192
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1193
|
+
it "sets the namespace on the current transaction" do
|
|
1194
|
+
Appsignal.set_action("custom")
|
|
1032
1195
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1196
|
+
expect(transaction).to have_action("custom")
|
|
1197
|
+
end
|
|
1035
1198
|
|
|
1036
|
-
|
|
1199
|
+
it "does not set the action if the action is nil" do
|
|
1200
|
+
Appsignal.set_action(nil)
|
|
1037
1201
|
|
|
1038
|
-
|
|
1202
|
+
expect(transaction).to_not have_action
|
|
1203
|
+
end
|
|
1039
1204
|
end
|
|
1040
1205
|
|
|
1041
|
-
|
|
1042
|
-
|
|
1206
|
+
context "without current transaction" do
|
|
1207
|
+
it "does not set ther action" do
|
|
1208
|
+
Appsignal.set_action("custom")
|
|
1043
1209
|
|
|
1044
|
-
|
|
1210
|
+
expect(transaction).to_not have_action
|
|
1211
|
+
end
|
|
1045
1212
|
end
|
|
1046
1213
|
end
|
|
1047
1214
|
|
|
1048
1215
|
describe ".set_namespace" do
|
|
1049
|
-
|
|
1216
|
+
around { |example| keep_transactions { example.run } }
|
|
1050
1217
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1218
|
+
context "with current transaction" do
|
|
1219
|
+
before { set_current_transaction(transaction) }
|
|
1053
1220
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1221
|
+
it "should set the namespace to the current transaction" do
|
|
1222
|
+
Appsignal.set_namespace("custom")
|
|
1056
1223
|
|
|
1057
|
-
|
|
1058
|
-
|
|
1224
|
+
expect(transaction).to have_namespace("custom")
|
|
1225
|
+
end
|
|
1059
1226
|
|
|
1060
|
-
|
|
1227
|
+
it "does not update the namespace if the namespace is nil" do
|
|
1228
|
+
Appsignal.set_namespace(nil)
|
|
1061
1229
|
|
|
1062
|
-
|
|
1230
|
+
expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
1231
|
+
end
|
|
1063
1232
|
end
|
|
1064
1233
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1234
|
+
context "without current transaction" do
|
|
1235
|
+
it "does not update the namespace" do
|
|
1236
|
+
expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
1237
|
+
|
|
1238
|
+
Appsignal.set_namespace("custom")
|
|
1067
1239
|
|
|
1068
|
-
|
|
1240
|
+
expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
1241
|
+
end
|
|
1069
1242
|
end
|
|
1070
1243
|
end
|
|
1071
1244
|
|
|
1072
1245
|
describe ".instrument" do
|
|
1073
1246
|
it_behaves_like "instrument helper" do
|
|
1074
1247
|
let(:instrumenter) { Appsignal }
|
|
1075
|
-
before
|
|
1076
|
-
expect(Appsignal::Transaction).to receive(:current).at_least(:once)
|
|
1077
|
-
.and_return(transaction)
|
|
1078
|
-
end
|
|
1248
|
+
before { set_current_transaction(transaction) }
|
|
1079
1249
|
end
|
|
1080
1250
|
end
|
|
1081
1251
|
|
|
1082
1252
|
describe ".instrument_sql" do
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
.and_return(transaction)
|
|
1086
|
-
end
|
|
1253
|
+
around { |example| keep_transactions { example.run } }
|
|
1254
|
+
before { set_current_transaction(transaction) }
|
|
1087
1255
|
|
|
1088
1256
|
it "creates an SQL event on the transaction" do
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1257
|
+
result =
|
|
1258
|
+
Appsignal.instrument_sql "name", "title", "body" do
|
|
1259
|
+
"return value"
|
|
1260
|
+
end
|
|
1092
1261
|
|
|
1093
|
-
result = Appsignal.instrument_sql "name", "title", "body" do
|
|
1094
|
-
"return value"
|
|
1095
|
-
end
|
|
1096
1262
|
expect(result).to eq "return value"
|
|
1263
|
+
expect(transaction).to include_event(
|
|
1264
|
+
"name" => "name",
|
|
1265
|
+
"title" => "title",
|
|
1266
|
+
"body" => "body",
|
|
1267
|
+
"body_format" => Appsignal::EventFormatter::SQL_BODY_FORMAT
|
|
1268
|
+
)
|
|
1097
1269
|
end
|
|
1098
1270
|
end
|
|
1099
1271
|
|
|
1100
1272
|
describe ".without_instrumentation" do
|
|
1273
|
+
around { |example| keep_transactions { example.run } }
|
|
1101
1274
|
let(:transaction) { http_request_transaction }
|
|
1102
|
-
before { allow(Appsignal::Transaction).to receive(:current).and_return(transaction) }
|
|
1103
1275
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1276
|
+
context "with current transaction" do
|
|
1277
|
+
before { set_current_transaction(transaction) }
|
|
1278
|
+
|
|
1279
|
+
it "does not record events on the transaction" do
|
|
1280
|
+
expect(transaction).to receive(:pause!).and_call_original
|
|
1281
|
+
expect(transaction).to receive(:resume!).and_call_original
|
|
1282
|
+
|
|
1283
|
+
Appsignal.instrument("register.this.event") { :do_nothing }
|
|
1284
|
+
Appsignal.without_instrumentation do
|
|
1285
|
+
Appsignal.instrument("dont.register.this.event") { :do_nothing }
|
|
1286
|
+
end
|
|
1287
|
+
|
|
1288
|
+
expect(transaction).to include_event("name" => "register.this.event")
|
|
1289
|
+
expect(transaction).to_not include_event("name" => "dont.register.this.event")
|
|
1110
1290
|
end
|
|
1111
|
-
expect(transaction.to_h["events"].map { |e| e["name"] })
|
|
1112
|
-
.to match_array("register.this.event")
|
|
1113
1291
|
end
|
|
1114
1292
|
|
|
1115
|
-
context "without transaction" do
|
|
1293
|
+
context "without current transaction" do
|
|
1116
1294
|
let(:transaction) { nil }
|
|
1117
1295
|
|
|
1118
|
-
it "
|
|
1296
|
+
it "does not crash" do
|
|
1119
1297
|
Appsignal.without_instrumentation { :do_nothing }
|
|
1120
1298
|
end
|
|
1121
1299
|
end
|
|
@@ -1123,17 +1301,35 @@ describe Appsignal do
|
|
|
1123
1301
|
end
|
|
1124
1302
|
|
|
1125
1303
|
describe ".start_logger" do
|
|
1304
|
+
let(:stderr_stream) { std_stream }
|
|
1305
|
+
let(:stderr) { stderr_stream.read }
|
|
1306
|
+
let(:log_stream) { std_stream }
|
|
1307
|
+
let(:log) { log_contents(log_stream) }
|
|
1308
|
+
|
|
1309
|
+
it "prints and logs a deprecation warning" do
|
|
1310
|
+
use_logger_with(log_stream) do
|
|
1311
|
+
capture_std_streams(std_stream, stderr_stream) do
|
|
1312
|
+
Appsignal.start_logger
|
|
1313
|
+
end
|
|
1314
|
+
end
|
|
1315
|
+
expect(stderr).to include("appsignal WARNING: Callng 'Appsignal.start_logger' is deprecated.")
|
|
1316
|
+
expect(log).to contains_log(:warn, "Callng 'Appsignal.start_logger' is deprecated.")
|
|
1317
|
+
end
|
|
1318
|
+
end
|
|
1319
|
+
|
|
1320
|
+
describe "._start_logger" do
|
|
1126
1321
|
let(:out_stream) { std_stream }
|
|
1127
1322
|
let(:output) { out_stream.read }
|
|
1128
1323
|
let(:log_path) { File.join(tmp_dir, "log") }
|
|
1129
1324
|
let(:log_file) { File.join(log_path, "appsignal.log") }
|
|
1325
|
+
let(:log_level) { "debug" }
|
|
1130
1326
|
|
|
1131
1327
|
before do
|
|
1132
1328
|
FileUtils.mkdir_p(log_path)
|
|
1133
1329
|
# Clear state from previous test
|
|
1134
1330
|
Appsignal.internal_logger = nil
|
|
1135
|
-
if Appsignal.instance_variable_defined?(:@
|
|
1136
|
-
Appsignal.remove_instance_variable(:@
|
|
1331
|
+
if Appsignal.instance_variable_defined?(:@in_memory_logger)
|
|
1332
|
+
Appsignal.remove_instance_variable(:@in_memory_logger)
|
|
1137
1333
|
end
|
|
1138
1334
|
end
|
|
1139
1335
|
after { FileUtils.rm_rf(log_path) }
|
|
@@ -1141,10 +1337,12 @@ describe Appsignal do
|
|
|
1141
1337
|
def initialize_config
|
|
1142
1338
|
Appsignal.config = project_fixture_config(
|
|
1143
1339
|
"production",
|
|
1144
|
-
:log_path => log_path
|
|
1340
|
+
:log_path => log_path,
|
|
1341
|
+
:log_level => log_level
|
|
1145
1342
|
)
|
|
1146
|
-
Appsignal.internal_logger.error("Log in memory")
|
|
1147
|
-
|
|
1343
|
+
Appsignal.internal_logger.error("Log in memory line 1")
|
|
1344
|
+
Appsignal.internal_logger.debug("Log in memory line 2")
|
|
1345
|
+
expect(Appsignal.in_memory_logger.messages).to_not be_empty
|
|
1148
1346
|
end
|
|
1149
1347
|
|
|
1150
1348
|
context "when the log path is writable" do
|
|
@@ -1154,7 +1352,7 @@ describe Appsignal do
|
|
|
1154
1352
|
before do
|
|
1155
1353
|
capture_stdout(out_stream) do
|
|
1156
1354
|
initialize_config
|
|
1157
|
-
Appsignal.
|
|
1355
|
+
Appsignal._start_logger
|
|
1158
1356
|
Appsignal.internal_logger.error("Log to file")
|
|
1159
1357
|
end
|
|
1160
1358
|
expect(Appsignal.internal_logger).to be_a(Appsignal::Utils::IntegrationLogger)
|
|
@@ -1166,12 +1364,26 @@ describe Appsignal do
|
|
|
1166
1364
|
expect(output).to be_empty
|
|
1167
1365
|
end
|
|
1168
1366
|
|
|
1169
|
-
|
|
1170
|
-
|
|
1367
|
+
context "with log level info" do
|
|
1368
|
+
let(:log_level) { "info" }
|
|
1369
|
+
|
|
1370
|
+
it "amends info log level and higher memory log messages to log file" do
|
|
1371
|
+
expect(log_file_contents).to include "[ERROR] appsignal: Log in memory line 1"
|
|
1372
|
+
expect(log_file_contents).to_not include "[DEBUG]"
|
|
1373
|
+
end
|
|
1374
|
+
end
|
|
1375
|
+
|
|
1376
|
+
context "with log level debug" do
|
|
1377
|
+
let(:log_level) { "debug" }
|
|
1378
|
+
|
|
1379
|
+
it "amends debug log level and higher memory log messages to log file" do
|
|
1380
|
+
expect(log_file_contents).to include "[ERROR] appsignal: Log in memory line 1"
|
|
1381
|
+
expect(log_file_contents).to include "[DEBUG] appsignal: Log in memory line 2"
|
|
1382
|
+
end
|
|
1171
1383
|
end
|
|
1172
1384
|
|
|
1173
1385
|
it "clears the in memory log after writing to the new logger" do
|
|
1174
|
-
expect(Appsignal.
|
|
1386
|
+
expect(Appsignal.instance_variable_get(:@in_memory_logger)).to be_nil
|
|
1175
1387
|
end
|
|
1176
1388
|
end
|
|
1177
1389
|
|
|
@@ -1182,7 +1394,7 @@ describe Appsignal do
|
|
|
1182
1394
|
|
|
1183
1395
|
capture_stdout(out_stream) do
|
|
1184
1396
|
initialize_config
|
|
1185
|
-
Appsignal.
|
|
1397
|
+
Appsignal._start_logger
|
|
1186
1398
|
Appsignal.internal_logger.error("Log to not writable log file")
|
|
1187
1399
|
expect(Appsignal.internal_logger).to be_a(Appsignal::Utils::IntegrationLogger)
|
|
1188
1400
|
end
|
|
@@ -1198,7 +1410,7 @@ describe Appsignal do
|
|
|
1198
1410
|
end
|
|
1199
1411
|
|
|
1200
1412
|
it "clears the in memory log after writing to the new logger" do
|
|
1201
|
-
expect(Appsignal.
|
|
1413
|
+
expect(Appsignal.instance_variable_get(:@in_memory_logger)).to be_nil
|
|
1202
1414
|
end
|
|
1203
1415
|
|
|
1204
1416
|
it "outputs a warning" do
|
|
@@ -1216,7 +1428,7 @@ describe Appsignal do
|
|
|
1216
1428
|
|
|
1217
1429
|
capture_stdout(out_stream) do
|
|
1218
1430
|
initialize_config
|
|
1219
|
-
Appsignal.
|
|
1431
|
+
Appsignal._start_logger
|
|
1220
1432
|
Appsignal.internal_logger.error("Log to not writable log path")
|
|
1221
1433
|
end
|
|
1222
1434
|
expect(Appsignal.internal_logger).to be_a(Appsignal::Utils::IntegrationLogger)
|
|
@@ -1245,7 +1457,7 @@ describe Appsignal do
|
|
|
1245
1457
|
before do
|
|
1246
1458
|
capture_stdout(out_stream) do
|
|
1247
1459
|
initialize_config
|
|
1248
|
-
Appsignal.
|
|
1460
|
+
Appsignal._start_logger
|
|
1249
1461
|
Appsignal.internal_logger.error("Log to stdout")
|
|
1250
1462
|
end
|
|
1251
1463
|
expect(Appsignal.internal_logger).to be_a(Appsignal::Utils::IntegrationLogger)
|
|
@@ -1261,7 +1473,7 @@ describe Appsignal do
|
|
|
1261
1473
|
end
|
|
1262
1474
|
|
|
1263
1475
|
it "clears the in memory log after writing to the new logger" do
|
|
1264
|
-
expect(Appsignal.
|
|
1476
|
+
expect(Appsignal.instance_variable_get(:@in_memory_logger)).to be_nil
|
|
1265
1477
|
end
|
|
1266
1478
|
end
|
|
1267
1479
|
|
|
@@ -1272,7 +1484,7 @@ describe Appsignal do
|
|
|
1272
1484
|
before do
|
|
1273
1485
|
Appsignal.config = nil
|
|
1274
1486
|
capture_stdout(out_stream) do
|
|
1275
|
-
Appsignal.
|
|
1487
|
+
Appsignal._start_logger
|
|
1276
1488
|
end
|
|
1277
1489
|
end
|
|
1278
1490
|
|
|
@@ -1287,7 +1499,7 @@ describe Appsignal do
|
|
|
1287
1499
|
capture_stdout(out_stream) do
|
|
1288
1500
|
initialize_config
|
|
1289
1501
|
Appsignal.config[:log_level] = "debug"
|
|
1290
|
-
Appsignal.
|
|
1502
|
+
Appsignal._start_logger
|
|
1291
1503
|
end
|
|
1292
1504
|
end
|
|
1293
1505
|
|