appsignal 3.9.3-java → 3.11.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +22 -19
  3. data/.rubocop.yml +1 -1
  4. data/CHANGELOG.md +180 -0
  5. data/Gemfile +1 -0
  6. data/README.md +0 -1
  7. data/Rakefile +1 -1
  8. data/benchmark.rake +99 -42
  9. data/build_matrix.yml +10 -12
  10. data/gemfiles/webmachine1.gemfile +5 -4
  11. data/lib/appsignal/cli/demo.rb +0 -1
  12. data/lib/appsignal/config.rb +57 -97
  13. data/lib/appsignal/demo.rb +15 -20
  14. data/lib/appsignal/environment.rb +6 -1
  15. data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -0
  16. data/lib/appsignal/event_formatter.rb +3 -2
  17. data/lib/appsignal/helpers/instrumentation.rb +490 -16
  18. data/lib/appsignal/hooks/action_cable.rb +21 -16
  19. data/lib/appsignal/hooks/active_job.rb +15 -14
  20. data/lib/appsignal/hooks/delayed_job.rb +1 -1
  21. data/lib/appsignal/hooks/shoryuken.rb +3 -63
  22. data/lib/appsignal/integrations/action_cable.rb +5 -7
  23. data/lib/appsignal/integrations/active_support_notifications.rb +1 -0
  24. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +36 -35
  25. data/lib/appsignal/integrations/data_mapper.rb +1 -0
  26. data/lib/appsignal/integrations/delayed_job_plugin.rb +27 -33
  27. data/lib/appsignal/integrations/dry_monitor.rb +1 -0
  28. data/lib/appsignal/integrations/excon.rb +1 -0
  29. data/lib/appsignal/integrations/http.rb +1 -0
  30. data/lib/appsignal/integrations/net_http.rb +1 -0
  31. data/lib/appsignal/integrations/object.rb +6 -0
  32. data/lib/appsignal/integrations/padrino.rb +21 -25
  33. data/lib/appsignal/integrations/que.rb +13 -20
  34. data/lib/appsignal/integrations/railtie.rb +1 -1
  35. data/lib/appsignal/integrations/rake.rb +45 -15
  36. data/lib/appsignal/integrations/redis.rb +1 -0
  37. data/lib/appsignal/integrations/redis_client.rb +1 -0
  38. data/lib/appsignal/integrations/resque.rb +2 -5
  39. data/lib/appsignal/integrations/shoryuken.rb +75 -0
  40. data/lib/appsignal/integrations/sidekiq.rb +7 -25
  41. data/lib/appsignal/integrations/unicorn.rb +1 -0
  42. data/lib/appsignal/integrations/webmachine.rb +12 -9
  43. data/lib/appsignal/logger.rb +7 -3
  44. data/lib/appsignal/probes/helpers.rb +1 -0
  45. data/lib/appsignal/probes/mri.rb +1 -0
  46. data/lib/appsignal/probes/sidekiq.rb +1 -0
  47. data/lib/appsignal/probes.rb +3 -0
  48. data/lib/appsignal/rack/abstract_middleware.rb +67 -24
  49. data/lib/appsignal/rack/body_wrapper.rb +143 -0
  50. data/lib/appsignal/rack/event_handler.rb +39 -8
  51. data/lib/appsignal/rack/generic_instrumentation.rb +6 -4
  52. data/lib/appsignal/rack/grape_middleware.rb +3 -2
  53. data/lib/appsignal/rack/hanami_middleware.rb +1 -1
  54. data/lib/appsignal/rack/instrumentation_middleware.rb +62 -0
  55. data/lib/appsignal/rack/rails_instrumentation.rb +1 -3
  56. data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -3
  57. data/lib/appsignal/rack/streaming_listener.rb +14 -59
  58. data/lib/appsignal/rack.rb +60 -0
  59. data/lib/appsignal/span.rb +1 -0
  60. data/lib/appsignal/transaction.rb +353 -104
  61. data/lib/appsignal/utils/data.rb +0 -1
  62. data/lib/appsignal/utils/hash_sanitizer.rb +0 -1
  63. data/lib/appsignal/utils/integration_logger.rb +0 -13
  64. data/lib/appsignal/utils/integration_memory_logger.rb +0 -13
  65. data/lib/appsignal/utils/json.rb +0 -1
  66. data/lib/appsignal/utils/query_params_sanitizer.rb +0 -1
  67. data/lib/appsignal/utils/stdout_and_logger_message.rb +0 -1
  68. data/lib/appsignal/utils.rb +6 -0
  69. data/lib/appsignal/version.rb +1 -1
  70. data/lib/appsignal.rb +9 -6
  71. data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
  72. data/spec/lib/appsignal/config_spec.rb +139 -43
  73. data/spec/lib/appsignal/hooks/action_cable_spec.rb +43 -74
  74. data/spec/lib/appsignal/hooks/activejob_spec.rb +9 -0
  75. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +2 -443
  76. data/spec/lib/appsignal/hooks/rake_spec.rb +100 -17
  77. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -171
  78. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
  79. data/spec/lib/appsignal/integrations/padrino_spec.rb +181 -131
  80. data/spec/lib/appsignal/integrations/que_spec.rb +3 -4
  81. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +167 -0
  82. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +4 -4
  83. data/spec/lib/appsignal/integrations/sinatra_spec.rb +10 -2
  84. data/spec/lib/appsignal/integrations/webmachine_spec.rb +77 -17
  85. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +144 -11
  86. data/spec/lib/appsignal/rack/body_wrapper_spec.rb +263 -0
  87. data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -10
  88. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +70 -17
  89. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +1 -1
  90. data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +38 -0
  91. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
  92. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +43 -120
  93. data/spec/lib/appsignal/rack_spec.rb +63 -0
  94. data/spec/lib/appsignal/transaction_spec.rb +1675 -953
  95. data/spec/lib/appsignal/utils/integration_logger_spec.rb +12 -16
  96. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -10
  97. data/spec/lib/appsignal_spec.rb +517 -13
  98. data/spec/support/helpers/transaction_helpers.rb +44 -20
  99. data/spec/support/matchers/transaction.rb +15 -1
  100. data/spec/support/mocks/dummy_app.rb +1 -1
  101. data/spec/support/testing.rb +1 -1
  102. metadata +12 -4
  103. data/support/check_versions +0 -22
@@ -1,25 +1,21 @@
1
1
  describe Appsignal::Utils::IntegrationLogger do
2
- let(:log) { std_stream }
2
+ let(:log_stream) { std_stream }
3
+ let(:logs) { log_contents(log_stream) }
3
4
  let(:logger) do
4
- Appsignal::Utils::IntegrationLogger.new(log).tap do |l|
5
+ Appsignal::Utils::IntegrationLogger.new(log_stream).tap do |l|
5
6
  l.formatter = logger_formatter
6
7
  end
7
8
  end
8
9
 
9
- describe "#seen_keys" do
10
- it "returns a Set" do
11
- expect(logger.seen_keys).to be_a(Set)
12
- end
13
- end
10
+ it "logs messages" do
11
+ logger.debug("debug message")
12
+ logger.info("info message")
13
+ logger.warn("warning message")
14
+ logger.error("error message")
14
15
 
15
- describe "#warn_once_then_debug" do
16
- it "only warns once, then uses debug" do
17
- message = "This is a log line"
18
- 3.times { logger.warn_once_then_debug(:key, message) }
19
-
20
- logs = log_contents(log)
21
- expect(logs.scan(/#{Regexp.escape(log_line(:WARN, message))}/).count).to eql(1)
22
- expect(logs.scan(/#{Regexp.escape(log_line(:DEBUG, message))}/).count).to eql(2)
23
- end
16
+ expect(logs).to contains_log(:debug, "debug message")
17
+ expect(logs).to contains_log(:info, "info message")
18
+ expect(logs).to contains_log(:warn, "warning message")
19
+ expect(logs).to contains_log(:error, "error message")
24
20
  end
25
21
  end
@@ -68,16 +68,6 @@ describe Appsignal::Utils::IntegrationLogger do
68
68
  end
69
69
  end
70
70
 
71
- describe "#warn_once_then_debug" do
72
- it "only warns once, then uses debug" do
73
- message = "This is a log line"
74
- 3.times { logger.warn_once_then_debug(:key, message) }
75
-
76
- expect(logger.messages[:WARN]).to eq([message])
77
- expect(logger.messages[:DEBUG]).to eq([message, message])
78
- end
79
- end
80
-
81
71
  describe "#error" do
82
72
  it "adds a log message with the error severity" do
83
73
  logger.error("error message")
@@ -321,6 +321,20 @@ describe Appsignal do
321
321
  end
322
322
  end
323
323
 
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
332
+ expect do
333
+ Appsignal.report_error(error)
334
+ end.to_not(change { created_transactions.count })
335
+ end
336
+ end
337
+
324
338
  describe ".set_namespace" do
325
339
  it "does not raise an error" do
326
340
  Appsignal.set_namespace("custom")
@@ -332,13 +346,190 @@ describe Appsignal do
332
346
  Appsignal.tag_request(:tag => "tag")
333
347
  end
334
348
  end
349
+
350
+ describe ".set_custom_data" do
351
+ it "does not raise an error" do
352
+ Appsignal.set_custom_data(:data => "value")
353
+ end
354
+ end
335
355
  end
336
356
 
337
357
  context "with config and started" do
338
358
  before { start_agent }
339
359
  around { |example| keep_transactions { example.run } }
340
360
 
361
+ describe ".monitor" do
362
+ it "creates a transaction" do
363
+ expect do
364
+ Appsignal.monitor(:action => "MyAction")
365
+ end.to(change { created_transactions.count }.by(1))
366
+
367
+ transaction = last_transaction
368
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
369
+ expect(transaction).to have_action("MyAction")
370
+ expect(transaction).to_not have_error
371
+ expect(transaction).to_not include_events
372
+ expect(transaction).to_not have_queue_start
373
+ expect(transaction).to be_completed
374
+ end
375
+
376
+ it "returns the block's return value" do
377
+ expect(Appsignal.monitor(:action => nil) { :return_value }).to eq(:return_value)
378
+ end
379
+
380
+ it "sets a custom namespace via the namespace argument" do
381
+ Appsignal.monitor(:namespace => "custom", :action => nil)
382
+
383
+ expect(last_transaction).to have_namespace("custom")
384
+ end
385
+
386
+ it "doesn't overwrite custom namespace set in the block" do
387
+ Appsignal.monitor(:namespace => "custom", :action => nil) do
388
+ Appsignal.set_namespace("more custom")
389
+ end
390
+
391
+ expect(last_transaction).to have_namespace("more custom")
392
+ end
393
+
394
+ it "sets the action via the action argument using a string" do
395
+ Appsignal.monitor(:action => "custom")
396
+
397
+ expect(last_transaction).to have_action("custom")
398
+ end
399
+
400
+ it "sets the action via the action argument using a symbol" do
401
+ Appsignal.monitor(:action => :custom)
402
+
403
+ expect(last_transaction).to have_action("custom")
404
+ end
405
+
406
+ it "doesn't overwrite custom action set in the block" do
407
+ Appsignal.monitor(:action => "custom") do
408
+ Appsignal.set_action("more custom")
409
+ end
410
+
411
+ expect(last_transaction).to have_action("more custom")
412
+ end
413
+
414
+ it "doesn't set the action when value is nil" do
415
+ Appsignal.monitor(:action => nil)
416
+
417
+ expect(last_transaction).to_not have_action
418
+ end
419
+
420
+ it "doesn't set the action when value is :set_later" do
421
+ Appsignal.monitor(:action => :set_later)
422
+
423
+ expect(last_transaction).to_not have_action
424
+ end
425
+
426
+ it "reports exceptions that occur in the block" do
427
+ expect do
428
+ Appsignal.monitor :action => nil do
429
+ raise ExampleException, "error message"
430
+ end
431
+ end.to raise_error(ExampleException, "error message")
432
+
433
+ expect(last_transaction).to have_error("ExampleException", "error message")
434
+ end
435
+
436
+ context "with already active transction" do
437
+ let(:err_stream) { std_stream }
438
+ let(:stderr) { err_stream.read }
439
+ let(:transaction) { http_request_transaction }
440
+ before do
441
+ set_current_transaction(transaction)
442
+ transaction.set_action("My action")
443
+ end
444
+
445
+ it "doesn't create a new transaction" do
446
+ logs = nil
447
+ expect do
448
+ logs =
449
+ capture_logs do
450
+ capture_std_streams(std_stream, err_stream) do
451
+ Appsignal.monitor(:action => nil)
452
+ end
453
+ end
454
+ end.to_not(change { created_transactions.count })
455
+
456
+ warning = "An active transaction around this 'Appsignal.monitor' call."
457
+ expect(logs).to contains_log(:warn, warning)
458
+ expect(stderr).to include("appsignal WARNING: #{warning}")
459
+ end
460
+
461
+ it "does not overwrite the parent transaction's namespace" do
462
+ silence { Appsignal.monitor(:namespace => "custom", :action => nil) }
463
+
464
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
465
+ end
466
+
467
+ it "does not overwrite the parent transaction's action" do
468
+ silence { Appsignal.monitor(:action => "custom") }
469
+
470
+ expect(transaction).to have_action("My action")
471
+ end
472
+
473
+ it "doesn't complete the parent transaction" do
474
+ silence { Appsignal.monitor(:action => nil) }
475
+
476
+ expect(transaction).to_not be_completed
477
+ end
478
+ end
479
+ end
480
+
481
+ describe ".monitor_and_stop" do
482
+ it "calls Appsignal.stop after the block" do
483
+ allow(Appsignal).to receive(:stop)
484
+ Appsignal.monitor_and_stop(:namespace => "custom", :action => "My Action")
485
+
486
+ transaction = last_transaction
487
+ expect(transaction).to have_namespace("custom")
488
+ expect(transaction).to have_action("My Action")
489
+ expect(transaction).to be_completed
490
+
491
+ expect(Appsignal).to have_received(:stop).with("monitor_and_stop")
492
+ end
493
+ end
494
+
341
495
  describe ".monitor_transaction" do
496
+ it "prints a deprecation warning" do
497
+ err_stream = std_stream
498
+ capture_std_streams(std_stream, err_stream) do
499
+ Appsignal.monitor_transaction(
500
+ "perform_job.something",
501
+ :class => "BackgroundJob",
502
+ :method => "perform"
503
+ ) do
504
+ :return_value
505
+ end
506
+ end
507
+
508
+ expect(err_stream.read).to include(
509
+ "appsignal WARNING: The `Appsignal.monitor_transaction` helper is deprecated."
510
+ )
511
+ end
512
+
513
+ it "logs a deprecation warning" do
514
+ logs =
515
+ capture_logs do
516
+ silence do
517
+ Appsignal.monitor_transaction(
518
+ "perform_job.something",
519
+ :class => "BackgroundJob",
520
+ :method => "perform"
521
+ ) do
522
+ :return_value
523
+ end
524
+ end
525
+ end
526
+
527
+ expect(logs).to contains_log(
528
+ :warn,
529
+ "The `Appsignal.monitor_transaction` helper is deprecated."
530
+ )
531
+ end
532
+
342
533
  context "with a successful call" do
343
534
  it "instruments and completes for a background job" do
344
535
  return_value = nil
@@ -348,7 +539,8 @@ describe Appsignal do
348
539
  "perform_job.something",
349
540
  {
350
541
  :class => "BackgroundJob",
351
- :method => "perform"
542
+ :method => "perform",
543
+ :queue_start => fixed_time.to_i
352
544
  }
353
545
  ) do
354
546
  :return_value
@@ -360,6 +552,7 @@ describe Appsignal do
360
552
  expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
361
553
  expect(transaction).to have_action("BackgroundJob#perform")
362
554
  expect(transaction).to include_event("name" => "perform_job.something")
555
+ expect(transaction).to have_queue_start(1_389_783_600_000)
363
556
  expect(transaction).to be_completed
364
557
  end
365
558
 
@@ -371,7 +564,8 @@ describe Appsignal do
371
564
  "process_action.something",
372
565
  {
373
566
  :controller => "BlogPostsController",
374
- :action => "show"
567
+ :action => "show",
568
+ "HTTP_X_REQUEST_START" => "t=#{fixed_time.to_i * 1000}"
375
569
  }
376
570
  ) do
377
571
  :return_value
@@ -383,6 +577,7 @@ describe Appsignal do
383
577
  expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
384
578
  expect(transaction).to have_action("BlogPostsController#show")
385
579
  expect(transaction).to include_event("name" => "process_action.something")
580
+ expect(transaction).to have_queue_start(1_389_783_600_000)
386
581
  expect(transaction).to be_completed
387
582
  end
388
583
  end
@@ -424,6 +619,43 @@ describe Appsignal do
424
619
  end
425
620
 
426
621
  describe ".monitor_single_transaction" do
622
+ it "prints a deprecation warning" do
623
+ err_stream = std_stream
624
+ capture_std_streams(std_stream, err_stream) do
625
+ Appsignal.monitor_single_transaction(
626
+ "perform_job.something",
627
+ :class => "BackgroundJob",
628
+ :method => "perform"
629
+ ) do
630
+ :return_value
631
+ end
632
+ end
633
+
634
+ expect(err_stream.read).to include(
635
+ "appsignal WARNING: The `Appsignal.monitor_single_transaction` helper is deprecated."
636
+ )
637
+ end
638
+
639
+ it "logs a deprecation warning" do
640
+ logs =
641
+ capture_logs do
642
+ silence do
643
+ Appsignal.monitor_single_transaction(
644
+ "perform_job.something",
645
+ :class => "BackgroundJob",
646
+ :method => "perform"
647
+ ) do
648
+ :return_value
649
+ end
650
+ end
651
+ end
652
+
653
+ expect(logs).to contains_log(
654
+ :warn,
655
+ "The `Appsignal.monitor_single_transaction` helper is deprecated."
656
+ )
657
+ end
658
+
427
659
  context "with a successful call" do
428
660
  it "calls monitor_transaction and Appsignal.stop" do
429
661
  expect(Appsignal).to receive(:stop)
@@ -466,15 +698,13 @@ describe Appsignal do
466
698
  end
467
699
 
468
700
  describe ".tag_request" do
469
- around do |example|
470
- start_agent
471
- with_current_transaction(transaction) { example.run }
472
- end
701
+ before { start_agent }
473
702
 
474
703
  context "with transaction" do
475
704
  let(:transaction) { http_request_transaction }
705
+ before { set_current_transaction(transaction) }
476
706
 
477
- it "calls set_tags on the current transaction" do
707
+ it "sets tags on the current transaction" do
478
708
  Appsignal.tag_request("a" => "b")
479
709
 
480
710
  transaction._sample
@@ -494,7 +724,161 @@ describe Appsignal do
494
724
  end
495
725
 
496
726
  it "also listens to tag_job" do
497
- expect(Appsignal).to respond_to(:tag_job)
727
+ expect(Appsignal.method(:tag_job)).to eq(Appsignal.method(:tag_request))
728
+ end
729
+
730
+ it "also listens to set_tags" do
731
+ expect(Appsignal.method(:set_tags)).to eq(Appsignal.method(:tag_request))
732
+ end
733
+ end
734
+
735
+ describe ".set_params" do
736
+ before { start_agent }
737
+
738
+ context "with transaction" do
739
+ let(:transaction) { http_request_transaction }
740
+ before { set_current_transaction(transaction) }
741
+
742
+ it "sets parameters on the transaction" do
743
+ Appsignal.set_params("param1" => "value1")
744
+
745
+ transaction._sample
746
+ expect(transaction).to include_params("param1" => "value1")
747
+ end
748
+
749
+ it "overwrites the params if called multiple times" do
750
+ Appsignal.set_params("param1" => "value1")
751
+ Appsignal.set_params("param2" => "value2")
752
+
753
+ transaction._sample
754
+ expect(transaction).to include_params("param2" => "value2")
755
+ end
756
+
757
+ it "sets parameters with a block on the transaction" do
758
+ Appsignal.set_params { { "param1" => "value1" } }
759
+
760
+ transaction._sample
761
+ expect(transaction).to include_params("param1" => "value1")
762
+ end
763
+ end
764
+
765
+ context "without transaction" do
766
+ it "does not set tags on the transaction" do
767
+ Appsignal.set_params("a" => "b")
768
+
769
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_params)
770
+ end
771
+ end
772
+ end
773
+
774
+ describe ".set_session_data" do
775
+ before { start_agent }
776
+
777
+ context "with transaction" do
778
+ let(:transaction) { http_request_transaction }
779
+ before { set_current_transaction(transaction) }
780
+
781
+ it "sets session data on the transaction" do
782
+ Appsignal.set_session_data("data" => "value1")
783
+
784
+ transaction._sample
785
+ expect(transaction).to include_session_data("data" => "value1")
786
+ end
787
+
788
+ it "overwrites the session data if called multiple times" do
789
+ Appsignal.set_session_data("data" => "value1")
790
+ Appsignal.set_session_data("data" => "value2")
791
+
792
+ transaction._sample
793
+ expect(transaction).to include_session_data("data" => "value2")
794
+ end
795
+
796
+ it "sets session data with a block on the transaction" do
797
+ Appsignal.set_session_data { { "data" => "value1" } }
798
+
799
+ transaction._sample
800
+ expect(transaction).to include_session_data("data" => "value1")
801
+ end
802
+ end
803
+
804
+ context "without transaction" do
805
+ it "does not set session data on the transaction" do
806
+ Appsignal.set_session_data("a" => "b")
807
+
808
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_session_data)
809
+ end
810
+ end
811
+ end
812
+
813
+ describe ".set_headers" do
814
+ before { start_agent }
815
+
816
+ context "with transaction" do
817
+ let(:transaction) { http_request_transaction }
818
+ before { set_current_transaction(transaction) }
819
+
820
+ it "sets request headers on the transaction" do
821
+ Appsignal.set_headers("PATH_INFO" => "/some-path")
822
+
823
+ transaction._sample
824
+ expect(transaction).to include_environment("PATH_INFO" => "/some-path")
825
+ end
826
+
827
+ it "overwrites the request headers if called multiple times" do
828
+ Appsignal.set_headers("PATH_INFO" => "/some-path1")
829
+ Appsignal.set_headers("PATH_INFO" => "/some-path2")
830
+
831
+ transaction._sample
832
+ expect(transaction).to include_environment("PATH_INFO" => "/some-path2")
833
+ end
834
+
835
+ it "sets request headers with a block on the transaction" do
836
+ Appsignal.set_headers { { "PATH_INFO" => "/some-path" } }
837
+
838
+ transaction._sample
839
+ expect(transaction).to include_environment("PATH_INFO" => "/some-path")
840
+ end
841
+ end
842
+
843
+ context "without transaction" do
844
+ it "does not set request headers on the transaction" do
845
+ Appsignal.set_headers("PATH_INFO" => "/some-path")
846
+
847
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_headers)
848
+ end
849
+ end
850
+ end
851
+
852
+ describe ".set_custom_data" do
853
+ before { start_agent }
854
+
855
+ context "with transaction" do
856
+ let(:transaction) { http_request_transaction }
857
+ before { set_current_transaction transaction }
858
+
859
+ it "sets custom data on the current transaction" do
860
+ Appsignal.set_custom_data(
861
+ :user => { :id => 123 },
862
+ :organization => { :slug => "appsignal" }
863
+ )
864
+
865
+ transaction._sample
866
+ expect(transaction).to include_custom_data(
867
+ "user" => { "id" => 123 },
868
+ "organization" => { "slug" => "appsignal" }
869
+ )
870
+ end
871
+ end
872
+
873
+ context "without transaction" do
874
+ it "does not set tags on the transaction" do
875
+ Appsignal.set_custom_data(
876
+ :user => { :id => 123 },
877
+ :organization => { :slug => "appsignal" }
878
+ )
879
+
880
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_custom_data)
881
+ end
498
882
  end
499
883
  end
500
884
 
@@ -993,6 +1377,101 @@ describe Appsignal do
993
1377
  end
994
1378
  end
995
1379
 
1380
+ describe ".report_error" do
1381
+ let(:err_stream) { std_stream }
1382
+ let(:stderr) { err_stream.read }
1383
+ let(:error) { ExampleException.new("error message") }
1384
+ before { start_agent }
1385
+ around { |example| keep_transactions { example.run } }
1386
+
1387
+ context "when the error is not an Exception" do
1388
+ let(:error) { Object.new }
1389
+
1390
+ it "does not set an error" do
1391
+ silence { Appsignal.report_error(error) }
1392
+
1393
+ expect(last_transaction).to_not have_error
1394
+ end
1395
+
1396
+ it "logs an error" do
1397
+ logs = capture_logs { Appsignal.report_error(error) }
1398
+ expect(logs).to contains_log(
1399
+ :error,
1400
+ "Appsignal.report_error: Cannot set error. " \
1401
+ "The given value is not an exception: #{error.inspect}"
1402
+ )
1403
+ end
1404
+ end
1405
+
1406
+ context "when there is no active transaction" do
1407
+ it "creates a new transaction" do
1408
+ expect do
1409
+ Appsignal.report_error(error)
1410
+ end.to(change { created_transactions.count }.by(1))
1411
+ end
1412
+
1413
+ it "completes the transaction" do
1414
+ Appsignal.report_error(error)
1415
+
1416
+ expect(last_transaction).to be_completed
1417
+ end
1418
+
1419
+ context "when given a block" do
1420
+ it "yields the transaction and allows additional metadata to be set" do
1421
+ Appsignal.report_error(error) do |t|
1422
+ t.set_action("my_action")
1423
+ t.set_namespace("my_namespace")
1424
+ t.set_tags(:tag1 => "value1")
1425
+ end
1426
+
1427
+ transaction = last_transaction
1428
+ expect(transaction).to have_namespace("my_namespace")
1429
+ expect(transaction).to have_action("my_action")
1430
+ expect(transaction).to have_error("ExampleException", "error message")
1431
+ expect(transaction).to include_tags("tag1" => "value1")
1432
+ expect(transaction).to be_completed
1433
+ end
1434
+ end
1435
+ end
1436
+
1437
+ context "when there is an active transaction" do
1438
+ let(:transaction) { http_request_transaction }
1439
+ before { set_current_transaction(transaction) }
1440
+
1441
+ it "adds the error to the active transaction" do
1442
+ Appsignal.report_error(error)
1443
+
1444
+ expect(last_transaction).to eq(transaction)
1445
+ transaction._sample
1446
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
1447
+ expect(transaction).to have_error("ExampleException", "error message")
1448
+ end
1449
+
1450
+ it "does not complete the transaction" do
1451
+ Appsignal.report_error(error)
1452
+
1453
+ expect(last_transaction).to_not be_completed
1454
+ end
1455
+
1456
+ context "when given a block" do
1457
+ it "yields the transaction and allows additional metadata to be set" do
1458
+ Appsignal.report_error(error) do |t|
1459
+ t.set_action("my_action")
1460
+ t.set_namespace("my_namespace")
1461
+ t.set_tags(:tag1 => "value1")
1462
+ end
1463
+
1464
+ transaction._sample
1465
+ expect(transaction).to have_namespace("my_namespace")
1466
+ expect(transaction).to have_action("my_action")
1467
+ expect(transaction).to have_error("ExampleException", "error message")
1468
+ expect(transaction).to include_tags("tag1" => "value1")
1469
+ expect(transaction).to_not be_completed
1470
+ end
1471
+ end
1472
+ end
1473
+ end
1474
+
996
1475
  describe ".set_action" do
997
1476
  around { |example| keep_transactions { example.run } }
998
1477
 
@@ -1078,7 +1557,7 @@ describe Appsignal do
1078
1557
  end
1079
1558
  end
1080
1559
 
1081
- describe ".without_instrumentation" do
1560
+ describe ".ignore_instrumentation_events" do
1082
1561
  around { |example| keep_transactions { example.run } }
1083
1562
  let(:transaction) { http_request_transaction }
1084
1563
 
@@ -1090,20 +1569,44 @@ describe Appsignal do
1090
1569
  expect(transaction).to receive(:resume!).and_call_original
1091
1570
 
1092
1571
  Appsignal.instrument("register.this.event") { :do_nothing }
1093
- Appsignal.without_instrumentation do
1572
+ Appsignal.ignore_instrumentation_events do
1094
1573
  Appsignal.instrument("dont.register.this.event") { :do_nothing }
1095
1574
  end
1096
1575
 
1097
1576
  expect(transaction).to include_event("name" => "register.this.event")
1098
1577
  expect(transaction).to_not include_event("name" => "dont.register.this.event")
1099
1578
  end
1579
+
1580
+ it "has a without_instrumentation alias that prints a deprecation warning" do
1581
+ Appsignal.instrument("register.this.event") { :do_nothing }
1582
+ err_stream = std_stream
1583
+ logs =
1584
+ capture_logs do
1585
+ capture_std_streams(std_stream, err_stream) do
1586
+ Appsignal.without_instrumentation do
1587
+ Appsignal.instrument("dont.register.this.event") { :do_nothing }
1588
+ end
1589
+ end
1590
+ end
1591
+
1592
+ expect(transaction).to include_event("name" => "register.this.event")
1593
+ expect(transaction).to_not include_event("name" => "dont.register.this.event")
1594
+
1595
+ expect(logs).to contains_log(
1596
+ :warn,
1597
+ "The `Appsignal.without_instrumentation` helper is deprecated."
1598
+ )
1599
+ expect(err_stream.read).to include(
1600
+ "appsignal WARNING: The `Appsignal.without_instrumentation` helper is deprecated."
1601
+ )
1602
+ end
1100
1603
  end
1101
1604
 
1102
1605
  context "without current transaction" do
1103
1606
  let(:transaction) { nil }
1104
1607
 
1105
1608
  it "does not crash" do
1106
- Appsignal.without_instrumentation { :do_nothing }
1609
+ Appsignal.ignore_instrumentation_events { :do_nothing }
1107
1610
  end
1108
1611
  end
1109
1612
  end
@@ -1121,8 +1624,9 @@ describe Appsignal do
1121
1624
  Appsignal.start_logger
1122
1625
  end
1123
1626
  end
1124
- expect(stderr).to include("appsignal WARNING: Callng 'Appsignal.start_logger' is deprecated.")
1125
- expect(log).to contains_log(:warn, "Callng 'Appsignal.start_logger' is deprecated.")
1627
+ expect(stderr)
1628
+ .to include("appsignal WARNING: Calling 'Appsignal.start_logger' is deprecated.")
1629
+ expect(log).to contains_log(:warn, "Calling 'Appsignal.start_logger' is deprecated.")
1126
1630
  end
1127
1631
  end
1128
1632