appsignal 3.9.3-java → 3.11.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.
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