appsignal 3.13.0-java → 4.0.0.beta.2-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +499 -487
  3. data/CHANGELOG.md +121 -0
  4. data/Rakefile +31 -7
  5. data/benchmark.rake +4 -6
  6. data/build_matrix.yml +45 -39
  7. data/ext/agent.rb +27 -27
  8. data/ext/appsignal_extension.c +25 -0
  9. data/gemfiles/rails-7.2.gemfile +11 -0
  10. data/lib/appsignal/check_in/cron.rb +2 -15
  11. data/lib/appsignal/cli/diagnose.rb +37 -28
  12. data/lib/appsignal/cli/install.rb +5 -1
  13. data/lib/appsignal/config.rb +57 -119
  14. data/lib/appsignal/demo.rb +2 -2
  15. data/lib/appsignal/extension/jruby.rb +14 -0
  16. data/lib/appsignal/helpers/instrumentation.rb +152 -416
  17. data/lib/appsignal/helpers/metrics.rb +0 -16
  18. data/lib/appsignal/hooks/action_cable.rb +8 -8
  19. data/lib/appsignal/hooks/active_job.rb +2 -2
  20. data/lib/appsignal/hooks/at_exit.rb +37 -0
  21. data/lib/appsignal/hooks.rb +1 -16
  22. data/lib/appsignal/integrations/action_cable.rb +2 -2
  23. data/lib/appsignal/integrations/capistrano/appsignal.cap +2 -4
  24. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +1 -4
  25. data/lib/appsignal/integrations/delayed_job_plugin.rb +3 -3
  26. data/lib/appsignal/integrations/que.rb +2 -2
  27. data/lib/appsignal/integrations/railtie.rb +26 -59
  28. data/lib/appsignal/integrations/rake.rb +2 -2
  29. data/lib/appsignal/integrations/resque.rb +2 -2
  30. data/lib/appsignal/integrations/shoryuken.rb +4 -4
  31. data/lib/appsignal/integrations/sidekiq.rb +3 -3
  32. data/lib/appsignal/integrations/webmachine.rb +2 -2
  33. data/lib/appsignal/loaders.rb +1 -1
  34. data/lib/appsignal/probes.rb +0 -9
  35. data/lib/appsignal/rack/abstract_middleware.rb +4 -26
  36. data/lib/appsignal/rack/event_handler.rb +4 -4
  37. data/lib/appsignal/rack/rails_instrumentation.rb +1 -1
  38. data/lib/appsignal/rack.rb +0 -25
  39. data/lib/appsignal/sample_data.rb +108 -0
  40. data/lib/appsignal/transaction.rb +241 -359
  41. data/lib/appsignal/utils/rails_helper.rb +4 -0
  42. data/lib/appsignal/version.rb +1 -1
  43. data/lib/appsignal.rb +19 -71
  44. data/spec/lib/appsignal/auth_check_spec.rb +1 -1
  45. data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
  46. data/spec/lib/appsignal/capistrano3_spec.rb +53 -13
  47. data/spec/lib/appsignal/check_in_spec.rb +1 -207
  48. data/spec/lib/appsignal/cli/demo_spec.rb +7 -27
  49. data/spec/lib/appsignal/cli/diagnose_spec.rb +145 -110
  50. data/spec/lib/appsignal/config_spec.rb +304 -379
  51. data/spec/lib/appsignal/extension_install_failure_spec.rb +5 -1
  52. data/spec/lib/appsignal/extension_spec.rb +5 -1
  53. data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +1 -1
  54. data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +1 -2
  55. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +1 -0
  56. data/spec/lib/appsignal/hooks/activejob_spec.rb +7 -12
  57. data/spec/lib/appsignal/hooks/at_exit_spec.rb +72 -0
  58. data/spec/lib/appsignal/hooks/gvl_spec.rb +10 -5
  59. data/spec/lib/appsignal/hooks/http_spec.rb +3 -3
  60. data/spec/lib/appsignal/hooks/net_http_spec.rb +3 -3
  61. data/spec/lib/appsignal/hooks/rake_spec.rb +6 -9
  62. data/spec/lib/appsignal/hooks/redis_client_spec.rb +5 -10
  63. data/spec/lib/appsignal/hooks/redis_spec.rb +4 -7
  64. data/spec/lib/appsignal/hooks/resque_spec.rb +3 -5
  65. data/spec/lib/appsignal/hooks_spec.rb +0 -41
  66. data/spec/lib/appsignal/integrations/data_mapper_spec.rb +29 -20
  67. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +4 -9
  68. data/spec/lib/appsignal/integrations/railtie_spec.rb +179 -157
  69. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +3 -5
  70. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +48 -62
  71. data/spec/lib/appsignal/loaders/hanami_spec.rb +6 -9
  72. data/spec/lib/appsignal/loaders/padrino_spec.rb +6 -10
  73. data/spec/lib/appsignal/loaders/sinatra_spec.rb +6 -9
  74. data/spec/lib/appsignal/loaders_spec.rb +8 -1
  75. data/spec/lib/appsignal/marker_spec.rb +1 -1
  76. data/spec/lib/appsignal/probes_spec.rb +4 -83
  77. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +4 -63
  78. data/spec/lib/appsignal/rack/event_handler_spec.rb +18 -15
  79. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +3 -11
  80. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +4 -5
  81. data/spec/lib/appsignal/sample_data_spec.rb +213 -0
  82. data/spec/lib/appsignal/transaction_spec.rb +817 -1046
  83. data/spec/lib/appsignal/transmitter_spec.rb +6 -8
  84. data/spec/lib/appsignal_spec.rb +311 -643
  85. data/spec/spec_helper.rb +1 -3
  86. data/spec/support/fixtures/projects/valid/config/appsignal.yml +4 -7
  87. data/spec/support/fixtures/projects/valid_with_rails_app/config/application.rb +16 -0
  88. data/spec/support/fixtures/projects/valid_with_rails_app/config/appsignal.yml +56 -0
  89. data/spec/support/fixtures/projects/valid_with_rails_app/config/environment.rb +5 -0
  90. data/spec/support/helpers/api_request_helper.rb +3 -2
  91. data/spec/support/helpers/config_helpers.rb +41 -11
  92. data/spec/support/helpers/dependency_helper.rb +8 -0
  93. data/spec/support/helpers/log_helpers.rb +1 -0
  94. data/spec/support/helpers/rails_helper.rb +6 -6
  95. data/spec/support/helpers/transaction_helpers.rb +2 -24
  96. data/spec/support/matchers/transaction.rb +3 -3
  97. data/spec/support/mocks/appsignal_mock.rb +3 -3
  98. data/spec/support/mocks/mock_probe.rb +2 -0
  99. data/spec/support/testing.rb +2 -2
  100. metadata +12 -22
  101. data/gemfiles/que_beta.gemfile +0 -5
  102. data/lib/appsignal/helpers/heartbeat.rb +0 -20
  103. data/lib/appsignal/integrations/grape.rb +0 -35
  104. data/lib/appsignal/integrations/hanami.rb +0 -13
  105. data/lib/appsignal/integrations/padrino.rb +0 -13
  106. data/lib/appsignal/integrations/sinatra.rb +0 -13
  107. data/lib/appsignal/rack/generic_instrumentation.rb +0 -22
  108. data/lib/appsignal/rack/streaming_listener.rb +0 -28
  109. data/spec/lib/appsignal/integrations/grape_spec.rb +0 -36
  110. data/spec/lib/appsignal/integrations/hanami_spec.rb +0 -17
  111. data/spec/lib/appsignal/integrations/padrino_spec.rb +0 -15
  112. data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -15
  113. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +0 -81
  114. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +0 -69
  115. data/spec/support/fixtures/projects/valid/config/environments/development.rb +0 -0
  116. data/spec/support/fixtures/projects/valid/config/environments/production.rb +0 -0
  117. data/spec/support/fixtures/projects/valid/config/environments/test.rb +0 -0
  118. data/spec/support/rails/my_app.rb +0 -6
  119. /data/spec/support/fixtures/projects/{valid/config/application.rb → valid_with_rails_app/log/.gitkeep} +0 -0
@@ -4,34 +4,6 @@ describe Appsignal do
4
4
 
5
5
  let(:transaction) { http_request_transaction }
6
6
 
7
- describe ".config=" do
8
- it "sets the config" do
9
- config = project_fixture_config
10
- expect(Appsignal.internal_logger).to_not receive(:level=)
11
-
12
- silence { Appsignal.config = config }
13
- expect(Appsignal.config).to eq config
14
- end
15
-
16
- it "prints a deprecation warning" do
17
- err_stream = std_stream
18
- capture_std_streams(std_stream, err_stream) do
19
- Appsignal.config = project_fixture_config
20
- end
21
- expect(err_stream.read).to include(
22
- "appsignal WARNING: Configuring AppSignal with `Appsignal.config=` is deprecated."
23
- )
24
- end
25
-
26
- it "logs a deprecation warning" do
27
- logs = capture_logs { silence { Appsignal.config = project_fixture_config } }
28
- expect(logs).to contains_log(
29
- :warn,
30
- "Configuring AppSignal with `Appsignal.config=` is deprecated."
31
- )
32
- end
33
- end
34
-
35
7
  describe ".configure" do
36
8
  context "when active" do
37
9
  it "doesn't update the config" do
@@ -62,11 +34,9 @@ describe Appsignal do
62
34
 
63
35
  context "with config but not started" do
64
36
  it "reuses the already loaded config if no env arg is given" do
65
- Appsignal._config = Appsignal::Config.new(
66
- project_fixture_path,
67
- :my_env,
68
- :ignore_actions => ["My action"]
69
- )
37
+ Appsignal.configure(:my_env, :root_path => project_fixture_path) do |config|
38
+ config.ignore_actions = ["My action"]
39
+ end
70
40
 
71
41
  Appsignal.configure do |config|
72
42
  expect(config.env).to eq("my_env")
@@ -76,6 +46,8 @@ describe Appsignal do
76
46
  config.name = "My app"
77
47
  config.push_api_key = "key"
78
48
  end
49
+ Appsignal.start
50
+
79
51
  expect(Appsignal.config.valid?).to be(true)
80
52
  expect(Appsignal.config.env).to eq("my_env")
81
53
  expect(Appsignal.config[:name]).to eq("My app")
@@ -84,11 +56,9 @@ describe Appsignal do
84
56
  end
85
57
 
86
58
  it "reuses the already loaded config if the env is the same" do
87
- Appsignal._config = Appsignal::Config.new(
88
- project_fixture_path,
89
- :my_env,
90
- :ignore_actions => ["My action"]
91
- )
59
+ Appsignal.configure(:my_env, :root_path => project_fixture_path) do |config|
60
+ config.ignore_actions = ["My action"]
61
+ end
92
62
 
93
63
  Appsignal.configure(:my_env) do |config|
94
64
  expect(config.ignore_actions).to eq(["My action"])
@@ -96,6 +66,8 @@ describe Appsignal do
96
66
  config.name = "My app"
97
67
  config.push_api_key = "key"
98
68
  end
69
+ Appsignal.start
70
+
99
71
  expect(Appsignal.config.valid?).to be(true)
100
72
  expect(Appsignal.config.env).to eq("my_env")
101
73
  expect(Appsignal.config[:active]).to be(true)
@@ -104,13 +76,11 @@ describe Appsignal do
104
76
  end
105
77
 
106
78
  it "loads a new config if the env is not the same" do
107
- Appsignal._config = Appsignal::Config.new(
108
- project_fixture_path,
109
- :my_env,
110
- :name => "Some name",
111
- :push_api_key => "Some key",
112
- :ignore_actions => ["My action"]
113
- )
79
+ Appsignal.configure(:my_env, :root_path => project_fixture_path) do |config|
80
+ config.name = "Some name"
81
+ config.push_api_key = "Some key"
82
+ config.ignore_actions = ["My action"]
83
+ end
114
84
 
115
85
  Appsignal.configure(:my_env2) do |config|
116
86
  expect(config.ignore_actions).to be_empty
@@ -118,6 +88,8 @@ describe Appsignal do
118
88
  config.name = "My app"
119
89
  config.push_api_key = "key"
120
90
  end
91
+ Appsignal.start
92
+
121
93
  expect(Appsignal.config.valid?).to be(true)
122
94
  expect(Appsignal.config.env).to eq("my_env2")
123
95
  expect(Appsignal.config[:active]).to be(true)
@@ -126,13 +98,11 @@ describe Appsignal do
126
98
  end
127
99
 
128
100
  it "loads a new config if the path is not the same" do
129
- Appsignal._config = Appsignal::Config.new(
130
- "/some/path",
131
- :my_env,
132
- :name => "Some name",
133
- :push_api_key => "Some key",
134
- :ignore_actions => ["My action"]
135
- )
101
+ Appsignal.configure(:my_env, :root_path => "/some/path") do |config|
102
+ config.name = "Some name"
103
+ config.push_api_key = "Some key"
104
+ config.ignore_actions = ["My action"]
105
+ end
136
106
 
137
107
  Appsignal.configure(:my_env, :root_path => project_fixture_path) do |config|
138
108
  expect(config.ignore_actions).to be_empty
@@ -140,6 +110,8 @@ describe Appsignal do
140
110
  config.name = "My app"
141
111
  config.push_api_key = "key"
142
112
  end
113
+ Appsignal.start
114
+
143
115
  expect(Appsignal.config.valid?).to be(true)
144
116
  expect(Appsignal.config.env).to eq("my_env")
145
117
  expect(Appsignal.config[:active]).to be(true)
@@ -161,6 +133,8 @@ describe Appsignal do
161
133
  config.name = "My app"
162
134
  config.push_api_key = "key"
163
135
  end
136
+ Appsignal.start
137
+
164
138
  expect(Appsignal.config.valid?).to be(true)
165
139
  expect(Appsignal.config.env).to eq("my_env")
166
140
  expect(Appsignal.config[:active]).to be(true)
@@ -174,23 +148,23 @@ describe Appsignal do
174
148
  Appsignal.configure(:test) do |config|
175
149
  config.push_api_key = "key"
176
150
  end
177
-
178
151
  Appsignal.start
152
+
179
153
  expect(Appsignal.config[:push_api_key]).to eq("key")
180
154
  end
181
155
 
182
156
  it "uses the given env" do
183
157
  ENV["APPSIGNAL_APP_ENV"] = "env_env"
184
158
  Appsignal.configure(:env_arg)
185
-
186
159
  Appsignal.start
160
+
187
161
  expect(Appsignal.config.env).to eq("env_arg")
188
162
  end
189
163
 
190
164
  it "uses the given root path to read the config file" do
191
165
  Appsignal.configure(:test, :root_path => project_fixture_path)
192
-
193
166
  Appsignal.start
167
+
194
168
  expect(Appsignal.config.env).to eq("test")
195
169
  expect(Appsignal.config[:push_api_key]).to eq("abc")
196
170
  # Ensure it loads from the config file in the given path
@@ -201,6 +175,7 @@ describe Appsignal do
201
175
  Dir.chdir project_fixture_path do
202
176
  Appsignal.configure(:test)
203
177
  end
178
+ Appsignal.start
204
179
 
205
180
  expect(Appsignal.config.env).to eq("test")
206
181
  expect(Appsignal.config[:push_api_key]).to eq("abc")
@@ -212,6 +187,7 @@ describe Appsignal do
212
187
  Appsignal.configure(:test) do |config|
213
188
  config.push_api_key = "key"
214
189
  end
190
+ Appsignal.start
215
191
 
216
192
  expect(Appsignal.config.valid?).to be(true)
217
193
  expect(Appsignal.config.env).to eq("test")
@@ -238,6 +214,7 @@ describe Appsignal do
238
214
  Appsignal.configure(:my_env) do |config|
239
215
  config.push_api_key = "key"
240
216
  end
217
+ Appsignal.start
241
218
 
242
219
  expect(Appsignal.config.valid?).to be(true)
243
220
  end
@@ -246,6 +223,7 @@ describe Appsignal do
246
223
  Appsignal.configure(:my_env) do |config|
247
224
  config.push_api_key = ""
248
225
  end
226
+ Appsignal.start
249
227
 
250
228
  expect(Appsignal.config.valid?).to be(false)
251
229
  end
@@ -398,7 +376,7 @@ describe Appsignal do
398
376
  end
399
377
 
400
378
  context "when config is loaded" do
401
- before { Appsignal._config = project_fixture_config }
379
+ before { Appsignal.configure(:production, :root_path => project_fixture_path) }
402
380
 
403
381
  it "should initialize logging" do
404
382
  Appsignal.start
@@ -410,6 +388,27 @@ describe Appsignal do
410
388
  Appsignal.start
411
389
  end
412
390
 
391
+ it "freezes the config" do
392
+ Appsignal.start
393
+
394
+ expect_frozen_error do
395
+ Appsignal.config[:ignore_actions] << "my action"
396
+ end
397
+ expect_frozen_error do
398
+ Appsignal.config.config_hash[:ignore_actions] << "my action"
399
+ end
400
+ expect_frozen_error do
401
+ Appsignal.config.config_hash.merge!(:option => :value)
402
+ end
403
+ expect_frozen_error do
404
+ Appsignal.config[:ignore_actions] = "my action"
405
+ end
406
+ end
407
+
408
+ def expect_frozen_error(&block)
409
+ expect(&block).to raise_error(FrozenError)
410
+ end
411
+
413
412
  context "when allocation tracking has been enabled" do
414
413
  before do
415
414
  Appsignal.config.config_hash[:enable_allocation_tracking] = true
@@ -496,8 +495,21 @@ describe Appsignal do
496
495
  end
497
496
  end
498
497
 
498
+ context "when already started" do
499
+ it "doesn't start again" do
500
+ start_agent
501
+
502
+ expect(Appsignal::Extension).to_not receive(:start)
503
+ logs = capture_logs { Appsignal.start }
504
+ expect(logs).to contains_log(
505
+ :warn,
506
+ "Ignoring call to Appsignal.start after AppSignal has started"
507
+ )
508
+ end
509
+ end
510
+
499
511
  context "with debug logging" do
500
- before { Appsignal._config = project_fixture_config("test") }
512
+ before { Appsignal.configure(:test, :root_path => project_fixture_path) }
501
513
 
502
514
  it "should change the log level" do
503
515
  Appsignal.start
@@ -533,7 +545,8 @@ describe Appsignal do
533
545
 
534
546
  context "when active" do
535
547
  before do
536
- Appsignal._config = project_fixture_config
548
+ Appsignal.configure(:production, :root_path => project_fixture_path)
549
+ Appsignal.start
537
550
  end
538
551
 
539
552
  it "starts the logger and extension" do
@@ -580,9 +593,7 @@ describe Appsignal do
580
593
  end
581
594
 
582
595
  context "when started with inactive config" do
583
- before do
584
- Appsignal._config = project_fixture_config("nonsense")
585
- end
596
+ before { Appsignal.configure(:nonsense, :root_path => project_fixture_path) }
586
597
 
587
598
  it { is_expected.to be_falsy }
588
599
  end
@@ -597,7 +608,8 @@ describe Appsignal do
597
608
 
598
609
  context "with inactive config" do
599
610
  before do
600
- Appsignal._config = project_fixture_config("nonsense")
611
+ Appsignal.configure(:nonsense, :root_path => project_fixture_path)
612
+ Appsignal.start
601
613
  end
602
614
 
603
615
  it { is_expected.to be_falsy }
@@ -605,7 +617,8 @@ describe Appsignal do
605
617
 
606
618
  context "with active config" do
607
619
  before do
608
- Appsignal._config = project_fixture_config
620
+ Appsignal.configure(:production, :root_path => project_fixture_path)
621
+ Appsignal.start
609
622
  end
610
623
 
611
624
  it { is_expected.to be_truthy }
@@ -631,65 +644,9 @@ describe Appsignal do
631
644
  end
632
645
 
633
646
  context "not active" do
634
- before { Appsignal._config = project_fixture_config("not_active") }
635
-
636
- describe ".monitor_transaction" do
637
- it "does not create a transaction" do
638
- object = double(:some_method => 1)
639
-
640
- expect do
641
- Appsignal.monitor_transaction("perform_job.nothing") do
642
- object.some_method
643
- end
644
- end.to_not(change { created_transactions.count })
645
- end
646
-
647
- it "returns the block's return value" do
648
- object = double(:some_method => 1)
649
-
650
- return_value = Appsignal.monitor_transaction("perform_job.nothing") do
651
- object.some_method
652
- end
653
- expect(return_value).to eq 1
654
- end
655
-
656
- context "with an unknown event type" do
657
- it "yields the given block" do
658
- expect do |blk|
659
- Appsignal.monitor_transaction("unknown.sidekiq", &blk)
660
- end.to yield_control
661
- end
662
-
663
- it "logs an error" do
664
- logs =
665
- capture_logs do
666
- Appsignal.monitor_transaction("unknown.sidekiq") {} # rubocop:disable Lint/EmptyBlock
667
- end
668
- expect(logs).to contains_log(
669
- :error,
670
- "Unrecognized name 'unknown.sidekiq': names must start with either 'perform_job' " \
671
- "(for jobs and tasks) or 'process_action' (for HTTP requests)"
672
- )
673
- end
674
- end
675
- end
676
-
677
- describe ".listen_for_error" do
678
- let(:error) { ExampleException.new("specific error") }
679
-
680
- it "reraises the error" do
681
- expect do
682
- Appsignal.listen_for_error { raise error }
683
- end.to raise_error(error)
684
- end
685
-
686
- it "does not create a transaction" do
687
- expect do
688
- expect do
689
- Appsignal.listen_for_error { raise error }
690
- end.to raise_error(error)
691
- end.to_not(change { created_transactions.count })
692
- end
647
+ before do
648
+ Appsignal.configure(:not_active, :root_path => project_fixture_path)
649
+ Appsignal.start
693
650
  end
694
651
 
695
652
  describe ".send_error" do
@@ -852,7 +809,7 @@ describe Appsignal do
852
809
  end
853
810
  end.to_not(change { created_transactions.count })
854
811
 
855
- warning = "An active transaction around this 'Appsignal.monitor' call."
812
+ warning = "A transaction is active around this 'Appsignal.monitor' call."
856
813
  expect(logs).to contains_log(:warn, warning)
857
814
  expect(stderr).to include("appsignal WARNING: #{warning}")
858
815
  end
@@ -897,211 +854,6 @@ describe Appsignal do
897
854
  end
898
855
  end
899
856
 
900
- describe ".monitor_transaction" do
901
- it "prints a deprecation warning" do
902
- err_stream = std_stream
903
- capture_std_streams(std_stream, err_stream) do
904
- Appsignal.monitor_transaction(
905
- "perform_job.something",
906
- :class => "BackgroundJob",
907
- :method => "perform"
908
- ) do
909
- :return_value
910
- end
911
- end
912
-
913
- expect(err_stream.read).to include(
914
- "appsignal WARNING: The `Appsignal.monitor_transaction` helper is deprecated."
915
- )
916
- end
917
-
918
- it "logs a deprecation warning" do
919
- logs =
920
- capture_logs do
921
- silence do
922
- Appsignal.monitor_transaction(
923
- "perform_job.something",
924
- :class => "BackgroundJob",
925
- :method => "perform"
926
- ) do
927
- :return_value
928
- end
929
- end
930
- end
931
-
932
- expect(logs).to contains_log(
933
- :warn,
934
- "The `Appsignal.monitor_transaction` helper is deprecated."
935
- )
936
- end
937
-
938
- context "with a successful call" do
939
- it "instruments and completes for a background job" do
940
- return_value = nil
941
- expect do
942
- return_value =
943
- Appsignal.monitor_transaction(
944
- "perform_job.something",
945
- {
946
- :class => "BackgroundJob",
947
- :method => "perform",
948
- :queue_start => fixed_time.to_i
949
- }
950
- ) do
951
- :return_value
952
- end
953
- end.to(change { created_transactions.count }.by(1))
954
- expect(return_value).to eq(:return_value)
955
-
956
- transaction = last_transaction
957
- expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
958
- expect(transaction).to have_action("BackgroundJob#perform")
959
- expect(transaction).to include_event("name" => "perform_job.something")
960
- expect(transaction).to have_queue_start(1_389_783_600_000)
961
- expect(transaction).to be_completed
962
- end
963
-
964
- it "instruments and completes for a http request" do
965
- return_value = nil
966
- expect do
967
- return_value =
968
- Appsignal.monitor_transaction(
969
- "process_action.something",
970
- {
971
- :controller => "BlogPostsController",
972
- :action => "show",
973
- "HTTP_X_REQUEST_START" => "t=#{fixed_time.to_i * 1000}"
974
- }
975
- ) do
976
- :return_value
977
- end
978
- end.to(change { created_transactions.count }.by(1))
979
- expect(return_value).to eq(:return_value)
980
-
981
- transaction = last_transaction
982
- expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
983
- expect(transaction).to have_action("BlogPostsController#show")
984
- expect(transaction).to include_event("name" => "process_action.something")
985
- expect(transaction).to have_queue_start(1_389_783_600_000)
986
- expect(transaction).to be_completed
987
- end
988
- end
989
-
990
- context "with an erroring call" do
991
- let(:error) { ExampleException.new("error message") }
992
-
993
- it "adds the error to the current transaction and complete" do
994
- expect do
995
- Appsignal.monitor_transaction("perform_job.something") do
996
- raise error
997
- end
998
- end.to raise_error(error)
999
-
1000
- expect(last_transaction).to have_error("ExampleException", "error message")
1001
- expect(last_transaction).to be_completed
1002
- end
1003
- end
1004
-
1005
- context "with an unknown event type" do
1006
- it "yields the given block" do
1007
- expect do |blk|
1008
- Appsignal.monitor_transaction("unknown.sidekiq", &blk)
1009
- end.to yield_control
1010
- end
1011
-
1012
- it "logs an error" do
1013
- logs =
1014
- capture_logs do
1015
- Appsignal.monitor_transaction("unknown.sidekiq") {} # rubocop:disable Lint/EmptyBlock
1016
- end
1017
- expect(logs).to contains_log(
1018
- :error,
1019
- "Unrecognized name 'unknown.sidekiq': names must start with either 'perform_job' " \
1020
- "(for jobs and tasks) or 'process_action' (for HTTP requests)"
1021
- )
1022
- end
1023
- end
1024
- end
1025
-
1026
- describe ".monitor_single_transaction" do
1027
- it "prints a deprecation warning" do
1028
- err_stream = std_stream
1029
- capture_std_streams(std_stream, err_stream) do
1030
- Appsignal.monitor_single_transaction(
1031
- "perform_job.something",
1032
- :class => "BackgroundJob",
1033
- :method => "perform"
1034
- ) do
1035
- :return_value
1036
- end
1037
- end
1038
-
1039
- expect(err_stream.read).to include(
1040
- "appsignal WARNING: The `Appsignal.monitor_single_transaction` helper is deprecated."
1041
- )
1042
- end
1043
-
1044
- it "logs a deprecation warning" do
1045
- logs =
1046
- capture_logs do
1047
- silence do
1048
- Appsignal.monitor_single_transaction(
1049
- "perform_job.something",
1050
- :class => "BackgroundJob",
1051
- :method => "perform"
1052
- ) do
1053
- :return_value
1054
- end
1055
- end
1056
- end
1057
-
1058
- expect(logs).to contains_log(
1059
- :warn,
1060
- "The `Appsignal.monitor_single_transaction` helper is deprecated."
1061
- )
1062
- end
1063
-
1064
- context "with a successful call" do
1065
- it "calls monitor_transaction and Appsignal.stop" do
1066
- expect(Appsignal).to receive(:stop)
1067
-
1068
- Appsignal.monitor_single_transaction(
1069
- "perform_job.something",
1070
- :controller => :my_controller,
1071
- :action => :my_action
1072
- ) do
1073
- # nothing
1074
- end
1075
-
1076
- transaction = last_transaction
1077
- expect(transaction).to have_action("my_controller#my_action")
1078
- expect(transaction).to include_event("name" => "perform_job.something")
1079
- end
1080
- end
1081
-
1082
- context "with an erroring call" do
1083
- let(:error) { ExampleException.new }
1084
-
1085
- it "calls monitor_transaction and stop and re-raises the error" do
1086
- expect(Appsignal).to receive(:stop)
1087
-
1088
- expect do
1089
- Appsignal.monitor_single_transaction(
1090
- "perform_job.something",
1091
- :controller => :my_controller,
1092
- :action => :my_action
1093
- ) do
1094
- raise error
1095
- end
1096
- end.to raise_error(error)
1097
-
1098
- transaction = last_transaction
1099
- expect(transaction).to have_action("my_controller#my_action")
1100
- expect(transaction).to include_event("name" => "perform_job.something")
1101
- end
1102
- end
1103
- end
1104
-
1105
857
  describe ".tag_request" do
1106
858
  before { start_agent }
1107
859
 
@@ -1137,30 +889,37 @@ describe Appsignal do
1137
889
  end
1138
890
  end
1139
891
 
1140
- describe ".set_params" do
892
+ describe ".add_params" do
1141
893
  before { start_agent }
1142
894
 
895
+ it "has a .set_params alias" do
896
+ expect(Appsignal.method(:add_params)).to eq(Appsignal.method(:set_params))
897
+ end
898
+
1143
899
  context "with transaction" do
1144
900
  let(:transaction) { http_request_transaction }
1145
901
  before { set_current_transaction(transaction) }
1146
902
 
1147
- it "sets parameters on the transaction" do
1148
- Appsignal.set_params("param1" => "value1")
903
+ it "adds parameters to the transaction" do
904
+ Appsignal.add_params("param1" => "value1")
1149
905
 
1150
906
  transaction._sample
1151
907
  expect(transaction).to include_params("param1" => "value1")
1152
908
  end
1153
909
 
1154
- it "overwrites the params if called multiple times" do
1155
- Appsignal.set_params("param1" => "value1")
1156
- Appsignal.set_params("param2" => "value2")
910
+ it "merges the params if called multiple times" do
911
+ Appsignal.add_params("param1" => "value1")
912
+ Appsignal.add_params("param2" => "value2")
1157
913
 
1158
914
  transaction._sample
1159
- expect(transaction).to include_params("param2" => "value2")
915
+ expect(transaction).to include_params(
916
+ "param1" => "value1",
917
+ "param2" => "value2"
918
+ )
1160
919
  end
1161
920
 
1162
- it "sets parameters with a block on the transaction" do
1163
- Appsignal.set_params { { "param1" => "value1" } }
921
+ it "adds parameters with a block to the transaction" do
922
+ Appsignal.add_params { { "param1" => "value1" } }
1164
923
 
1165
924
  transaction._sample
1166
925
  expect(transaction).to include_params("param1" => "value1")
@@ -1168,37 +927,61 @@ describe Appsignal do
1168
927
  end
1169
928
 
1170
929
  context "without transaction" do
1171
- it "does not set tags on the transaction" do
1172
- Appsignal.set_params("a" => "b")
930
+ it "does not add tags to any transaction" do
931
+ Appsignal.add_params("a" => "b")
1173
932
 
1174
- expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_params)
933
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:add_params)
1175
934
  end
1176
935
  end
1177
936
  end
1178
937
 
1179
- describe ".set_session_data" do
938
+ describe ".set_empty_params!" do
1180
939
  before { start_agent }
1181
940
 
1182
941
  context "with transaction" do
1183
942
  let(:transaction) { http_request_transaction }
1184
943
  before { set_current_transaction(transaction) }
1185
944
 
1186
- it "sets session data on the transaction" do
1187
- Appsignal.set_session_data("data" => "value1")
945
+ it "marks parameters to be sent as an empty value" do
946
+ Appsignal.add_params("key1" => "value")
947
+ Appsignal.set_empty_params!
948
+
949
+ transaction._sample
950
+ expect(transaction).to_not include_params
951
+ end
952
+ end
953
+ end
954
+
955
+ describe ".add_session_data" do
956
+ before { start_agent }
957
+
958
+ it "has a .set_session_data alias" do
959
+ expect(Appsignal.method(:add_session_data)).to eq(Appsignal.method(:set_session_data))
960
+ end
961
+
962
+ context "with transaction" do
963
+ let(:transaction) { http_request_transaction }
964
+ before { set_current_transaction(transaction) }
965
+
966
+ it "adds session data to the transaction" do
967
+ Appsignal.add_session_data("data" => "value1")
1188
968
 
1189
969
  transaction._sample
1190
970
  expect(transaction).to include_session_data("data" => "value1")
1191
971
  end
1192
972
 
1193
- it "overwrites the session data if called multiple times" do
1194
- Appsignal.set_session_data("data" => "value1")
1195
- Appsignal.set_session_data("data" => "value2")
973
+ it "merges the session data if called multiple times" do
974
+ Appsignal.set_session_data("data1" => "value1")
975
+ Appsignal.set_session_data("data2" => "value2")
1196
976
 
1197
977
  transaction._sample
1198
- expect(transaction).to include_session_data("data" => "value2")
978
+ expect(transaction).to include_session_data(
979
+ "data1" => "value1",
980
+ "data2" => "value2"
981
+ )
1199
982
  end
1200
983
 
1201
- it "sets session data with a block on the transaction" do
984
+ it "adds session data with a block to the transaction" do
1202
985
  Appsignal.set_session_data { { "data" => "value1" } }
1203
986
 
1204
987
  transaction._sample
@@ -1207,38 +990,45 @@ describe Appsignal do
1207
990
  end
1208
991
 
1209
992
  context "without transaction" do
1210
- it "does not set session data on the transaction" do
993
+ it "does not add session data to any transaction" do
1211
994
  Appsignal.set_session_data("a" => "b")
1212
995
 
1213
- expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_session_data)
996
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:add_session_data)
1214
997
  end
1215
998
  end
1216
999
  end
1217
1000
 
1218
- describe ".set_headers" do
1001
+ describe ".add_headers" do
1219
1002
  before { start_agent }
1220
1003
 
1004
+ it "has a .set_headers alias" do
1005
+ expect(Appsignal.method(:add_headers)).to eq(Appsignal.method(:set_headers))
1006
+ end
1007
+
1221
1008
  context "with transaction" do
1222
1009
  let(:transaction) { http_request_transaction }
1223
1010
  before { set_current_transaction(transaction) }
1224
1011
 
1225
- it "sets request headers on the transaction" do
1226
- Appsignal.set_headers("PATH_INFO" => "/some-path")
1012
+ it "adds request headers to the transaction" do
1013
+ Appsignal.add_headers("PATH_INFO" => "/some-path")
1227
1014
 
1228
1015
  transaction._sample
1229
1016
  expect(transaction).to include_environment("PATH_INFO" => "/some-path")
1230
1017
  end
1231
1018
 
1232
- it "overwrites the request headers if called multiple times" do
1233
- Appsignal.set_headers("PATH_INFO" => "/some-path1")
1234
- Appsignal.set_headers("PATH_INFO" => "/some-path2")
1019
+ it "merges the request headers if called multiple times" do
1020
+ Appsignal.add_headers("PATH_INFO" => "/some-path")
1021
+ Appsignal.add_headers("REQUEST_METHOD" => "GET")
1235
1022
 
1236
1023
  transaction._sample
1237
- expect(transaction).to include_environment("PATH_INFO" => "/some-path2")
1024
+ expect(transaction).to include_environment(
1025
+ "PATH_INFO" => "/some-path",
1026
+ "REQUEST_METHOD" => "GET"
1027
+ )
1238
1028
  end
1239
1029
 
1240
- it "sets request headers with a block on the transaction" do
1241
- Appsignal.set_headers { { "PATH_INFO" => "/some-path" } }
1030
+ it "adds request headers with a block to the transaction" do
1031
+ Appsignal.add_headers { { "PATH_INFO" => "/some-path" } }
1242
1032
 
1243
1033
  transaction._sample
1244
1034
  expect(transaction).to include_environment("PATH_INFO" => "/some-path")
@@ -1246,23 +1036,27 @@ describe Appsignal do
1246
1036
  end
1247
1037
 
1248
1038
  context "without transaction" do
1249
- it "does not set request headers on the transaction" do
1250
- Appsignal.set_headers("PATH_INFO" => "/some-path")
1039
+ it "does not add request headers to any transaction" do
1040
+ Appsignal.add_headers("PATH_INFO" => "/some-path")
1251
1041
 
1252
- expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_headers)
1042
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:add_headers)
1253
1043
  end
1254
1044
  end
1255
1045
  end
1256
1046
 
1257
- describe ".set_custom_data" do
1047
+ describe ".add_custom_data" do
1258
1048
  before { start_agent }
1259
1049
 
1050
+ it "has a .set_custom_data alias" do
1051
+ expect(Appsignal.method(:add_custom_data)).to eq(Appsignal.method(:set_custom_data))
1052
+ end
1053
+
1260
1054
  context "with transaction" do
1261
1055
  let(:transaction) { http_request_transaction }
1262
1056
  before { set_current_transaction transaction }
1263
1057
 
1264
- it "sets custom data on the current transaction" do
1265
- Appsignal.set_custom_data(
1058
+ it "adds custom data to the current transaction" do
1059
+ Appsignal.add_custom_data(
1266
1060
  :user => { :id => 123 },
1267
1061
  :organization => { :slug => "appsignal" }
1268
1062
  )
@@ -1273,16 +1067,27 @@ describe Appsignal do
1273
1067
  "organization" => { "slug" => "appsignal" }
1274
1068
  )
1275
1069
  end
1070
+
1071
+ it "merges the custom data if called multiple times" do
1072
+ Appsignal.add_custom_data(:abc => "value")
1073
+ Appsignal.add_custom_data(:def => "value")
1074
+
1075
+ transaction._sample
1076
+ expect(transaction).to include_custom_data(
1077
+ "abc" => "value",
1078
+ "def" => "value"
1079
+ )
1080
+ end
1276
1081
  end
1277
1082
 
1278
1083
  context "without transaction" do
1279
- it "does not set tags on the transaction" do
1280
- Appsignal.set_custom_data(
1084
+ it "does not add tags any the transaction" do
1085
+ Appsignal.add_custom_data(
1281
1086
  :user => { :id => 123 },
1282
1087
  :organization => { :slug => "appsignal" }
1283
1088
  )
1284
1089
 
1285
- expect_any_instance_of(Appsignal::Transaction).to_not receive(:set_custom_data)
1090
+ expect_any_instance_of(Appsignal::Transaction).to_not receive(:add_custom_data)
1286
1091
  end
1287
1092
  end
1288
1093
  end
@@ -1323,7 +1128,7 @@ describe Appsignal do
1323
1128
  end
1324
1129
  end
1325
1130
 
1326
- describe "custom stats" do
1131
+ describe "custom metrics" do
1327
1132
  let(:tags) { { :foo => "bar" } }
1328
1133
 
1329
1134
  describe ".set_gauge" do
@@ -1358,50 +1163,6 @@ describe Appsignal do
1358
1163
  end
1359
1164
  end
1360
1165
 
1361
- describe ".set_host_gauge" do
1362
- let(:err_stream) { std_stream }
1363
- let(:stderr) { err_stream.read }
1364
- let(:log_stream) { StringIO.new }
1365
- let(:logs) { log_contents(log_stream) }
1366
- let(:deprecation_message) do
1367
- "The `set_host_gauge` method has been deprecated. " \
1368
- "Calling this method has no effect. " \
1369
- "Please remove method call in the following file to remove " \
1370
- "this message."
1371
- end
1372
- before do
1373
- Appsignal.internal_logger = test_logger(log_stream)
1374
- capture_std_streams(std_stream, err_stream) { Appsignal.set_host_gauge("key", 0.1) }
1375
- end
1376
-
1377
- it "logs a deprecation warning" do
1378
- expect(stderr).to include("appsignal WARNING: #{deprecation_message}")
1379
- expect(logs).to include(deprecation_message)
1380
- end
1381
- end
1382
-
1383
- describe ".set_process_gauge" do
1384
- let(:err_stream) { std_stream }
1385
- let(:stderr) { err_stream.read }
1386
- let(:log_stream) { StringIO.new }
1387
- let(:logs) { log_contents(log_stream) }
1388
- let(:deprecation_message) do
1389
- "The `set_process_gauge` method has been deprecated. " \
1390
- "Calling this method has no effect. " \
1391
- "Please remove method call in the following file to remove " \
1392
- "this message."
1393
- end
1394
- before do
1395
- Appsignal.internal_logger = test_logger(log_stream)
1396
- capture_std_streams(std_stream, err_stream) { Appsignal.set_process_gauge("key", 0.1) }
1397
- end
1398
-
1399
- it "logs a deprecation warning" do
1400
- expect(stderr).to include("appsignal WARNING: #{deprecation_message}")
1401
- expect(logs).to include(deprecation_message)
1402
- end
1403
- end
1404
-
1405
1166
  describe ".increment_counter" do
1406
1167
  it "should call increment_counter on the extension with a string key" do
1407
1168
  expect(Appsignal::Extension).to receive(:increment_counter)
@@ -1537,138 +1298,52 @@ describe Appsignal do
1537
1298
  end
1538
1299
  end
1539
1300
 
1540
- context "with tags" do
1541
- let(:tags) { { :a => "a", :b => "b" } }
1542
-
1543
- it "prints a deprecation warning and tags the transaction" do
1544
- logs = capture_logs do
1545
- expect do
1546
- capture_std_streams(std_stream, err_stream) do
1547
- Appsignal.send_error(error, tags)
1548
- end
1549
- end.to change { created_transactions.count }.by(1)
1301
+ context "when given a block" do
1302
+ it "yields the transaction and allows additional metadata to be set" do
1303
+ Appsignal.send_error(StandardError.new("my_error")) do |transaction|
1304
+ transaction.set_action("my_action")
1305
+ transaction.set_namespace("my_namespace")
1550
1306
  end
1551
1307
 
1552
- expect(last_transaction).to include_tags("a" => "a", "b" => "b")
1553
-
1554
- message = "The tags argument for `Appsignal.send_error` is deprecated. " \
1555
- "Please use the block method to set tags instead.\n\n" \
1556
- " Appsignal.send_error(error) do |transaction|\n" \
1557
- " transaction.set_tags(#{tags.inspect})\n" \
1558
- " end\n\n" \
1559
- "Appsignal.send_error called on location: #{__FILE__}:"
1560
- expect(stderr).to include("appsignal WARNING: #{message}")
1561
- expect(logs).to include(message)
1308
+ expect(last_transaction).to have_namespace("my_namespace")
1309
+ expect(last_transaction).to have_action("my_action")
1310
+ expect(last_transaction).to have_error("StandardError", "my_error")
1562
1311
  end
1563
- end
1564
1312
 
1565
- context "with namespace" do
1566
- let(:namespace) { "admin" }
1567
-
1568
- it "prints a deprecation warning and sets the namespace on the transaction" do
1569
- logs = capture_logs do
1570
- expect do
1571
- capture_std_streams(std_stream, err_stream) do
1572
- Appsignal.send_error(error, nil, namespace)
1573
- end
1574
- end.to change { created_transactions.count }.by(1)
1313
+ it "yields and allows additional metadata to be set with global helpers" do
1314
+ Appsignal.send_error(StandardError.new("my_error")) do
1315
+ Appsignal.set_action("my_action")
1316
+ Appsignal.set_namespace("my_namespace")
1575
1317
  end
1576
1318
 
1577
- expect(last_transaction).to have_namespace(namespace)
1578
-
1579
- message = "The namespace argument for `Appsignal.send_error` is deprecated. " \
1580
- "Please use the block method to set the namespace instead.\n\n" \
1581
- " Appsignal.send_error(error) do |transaction|\n" \
1582
- " transaction.set_namespace(#{namespace.inspect})\n" \
1583
- " end\n\n" \
1584
- "Appsignal.send_error called on location: #{__FILE__}:"
1585
- expect(stderr).to include("appsignal WARNING: #{message}")
1586
- expect(logs).to include(message)
1587
- end
1588
- end
1589
-
1590
- context "when given a block" do
1591
- it "yields the transaction and allows additional metadata to be set" do
1592
- keep_transactions do
1593
- Appsignal.send_error(StandardError.new("my_error")) do |transaction|
1594
- transaction.set_action("my_action")
1595
- transaction.set_namespace("my_namespace")
1596
- end
1597
- end
1598
1319
  expect(last_transaction).to have_namespace("my_namespace")
1599
1320
  expect(last_transaction).to have_action("my_action")
1600
1321
  expect(last_transaction).to have_error("StandardError", "my_error")
1601
1322
  end
1602
- end
1603
- end
1604
1323
 
1605
- describe ".listen_for_error" do
1606
- around { |example| keep_transactions { example.run } }
1324
+ it "yields to set metadata and doesn't modify the active transaction" do
1325
+ active_transaction = http_request_transaction
1326
+ active_transaction.set_action("active action")
1327
+ active_transaction.set_namespace("active namespace")
1328
+ set_current_transaction(active_transaction)
1329
+ expect(current_transaction).to eq(active_transaction)
1607
1330
 
1608
- it "prints and logs a deprecation warning" do
1609
- err_stream = std_stream
1610
- logs =
1611
- capture_logs do
1612
- capture_std_streams(std_stream, err_stream) do
1613
- Appsignal.listen_for_error do
1614
- # Do nothing
1615
- end
1616
- end
1331
+ Appsignal.send_error(StandardError.new("my_error")) do
1332
+ Appsignal.set_action("my_action")
1333
+ Appsignal.set_namespace("my_namespace")
1617
1334
  end
1618
- expect(err_stream.read)
1619
- .to include("appsignal WARNING: The `Appsignal.listen_for_error` helper is deprecated.")
1620
- expect(logs).to contains_log(
1621
- :warn,
1622
- "The `Appsignal.listen_for_error` helper is deprecated."
1623
- )
1624
- end
1625
1335
 
1626
- it "records the error and re-raise it" do
1627
- expect do
1628
- expect do
1629
- Appsignal.listen_for_error do
1630
- raise ExampleException, "I am an exception"
1631
- end
1632
- end.to raise_error(ExampleException, "I am an exception")
1633
- end.to change { created_transactions.count }.by(1)
1634
-
1635
- # Default namespace
1636
- expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
1637
- expect(last_transaction).to have_error("ExampleException", "I am an exception")
1638
- expect(last_transaction).to_not include_tags
1639
- end
1640
-
1641
- context "with tags" do
1642
- it "adds tags to the transaction" do
1643
- expect do
1644
- expect do
1645
- Appsignal.listen_for_error("foo" => "bar") do
1646
- raise ExampleException, "I am an exception"
1647
- end
1648
- end.to raise_error(ExampleException, "I am an exception")
1649
- end.to change { created_transactions.count }.by(1)
1650
-
1651
- # Default namespace
1652
- expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
1653
- expect(last_transaction).to have_error("ExampleException", "I am an exception")
1654
- expect(last_transaction).to include_tags("foo" => "bar")
1655
- end
1656
- end
1336
+ # Restores the active_transaction as the current transaction
1337
+ expect(current_transaction).to eq(active_transaction)
1657
1338
 
1658
- context "with a custom namespace" do
1659
- it "adds the namespace to the transaction" do
1660
- expect do
1661
- expect do
1662
- Appsignal.listen_for_error(nil, "custom_namespace") do
1663
- raise ExampleException, "I am an exception"
1664
- end
1665
- end.to raise_error(ExampleException, "I am an exception")
1666
- end.to change { created_transactions.count }.by(1)
1339
+ expect(last_transaction).to have_namespace("my_namespace")
1340
+ expect(last_transaction).to have_action("my_action")
1341
+ expect(last_transaction).to have_error("StandardError", "my_error")
1342
+ expect(last_transaction).to be_completed
1667
1343
 
1668
- # Default namespace
1669
- expect(last_transaction).to have_namespace("custom_namespace")
1670
- expect(last_transaction).to have_error("ExampleException", "I am an exception")
1671
- expect(last_transaction).to_not include_tags
1344
+ expect(active_transaction).to have_namespace("active namespace")
1345
+ expect(active_transaction).to have_action("active action")
1346
+ expect(active_transaction).to_not be_completed
1672
1347
  end
1673
1348
  end
1674
1349
  end
@@ -1713,68 +1388,6 @@ describe Appsignal do
1713
1388
  end
1714
1389
  end
1715
1390
 
1716
- context "with tags" do
1717
- let(:tags) { { "foo" => "bar" } }
1718
-
1719
- it "tags the transaction" do
1720
- silence(:allowed => ["set_error", "The tags argument for"]) do
1721
- Appsignal.set_error(error, tags)
1722
- end
1723
-
1724
- transaction._sample
1725
- expect(transaction).to have_error(error)
1726
- expect(transaction).to include_tags(tags)
1727
- end
1728
-
1729
- it "prints a deprecation warning and tags the transaction" do
1730
- logs = capture_logs do
1731
- capture_std_streams(std_stream, err_stream) do
1732
- Appsignal.set_error(error, tags)
1733
- end
1734
- end
1735
-
1736
- message = "The tags argument for `Appsignal.set_error` is deprecated. " \
1737
- "Please use the block method to set tags instead.\n\n" \
1738
- " Appsignal.set_error(error) do |transaction|\n" \
1739
- " transaction.set_tags(#{tags.inspect})\n" \
1740
- " end\n\n" \
1741
- "Appsignal.set_error called on location: #{__FILE__}:"
1742
- expect(stderr).to include("appsignal WARNING: #{message}")
1743
- expect(logs).to include(message)
1744
- end
1745
- end
1746
-
1747
- context "with namespace" do
1748
- let(:namespace) { "admin" }
1749
-
1750
- it "sets the namespace on the transaction" do
1751
- silence(:allowed => ["set_error", "The namespace argument for"]) do
1752
- Appsignal.set_error(error, nil, namespace)
1753
- end
1754
-
1755
- expect(transaction).to have_error("ExampleException", "I am an exception")
1756
- expect(transaction).to have_namespace(namespace)
1757
- expect(transaction).to_not include_tags
1758
- end
1759
-
1760
- it "prints a deprecation warning andsets the namespace on the transaction" do
1761
- logs = capture_logs do
1762
- capture_std_streams(std_stream, err_stream) do
1763
- Appsignal.set_error(error, nil, namespace)
1764
- end
1765
- end
1766
-
1767
- message = "The namespace argument for `Appsignal.set_error` is deprecated. " \
1768
- "Please use the block method to set the namespace instead.\n\n" \
1769
- " Appsignal.set_error(error) do |transaction|\n" \
1770
- " transaction.set_namespace(#{namespace.inspect})\n" \
1771
- " end\n\n" \
1772
- "Appsignal.set_error called on location: #{__FILE__}:"
1773
- expect(stderr).to include("appsignal WARNING: #{message}")
1774
- expect(logs).to include(message)
1775
- end
1776
- end
1777
-
1778
1391
  context "when given a block" do
1779
1392
  it "yields the transaction and allows additional metadata to be set" do
1780
1393
  Appsignal.set_error(StandardError.new("my_error")) do |t|
@@ -1818,7 +1431,7 @@ describe Appsignal do
1818
1431
  logs = capture_logs { Appsignal.report_error(error) }
1819
1432
  expect(logs).to contains_log(
1820
1433
  :error,
1821
- "Appsignal.report_error: Cannot set error. " \
1434
+ "Appsignal.report_error: Cannot add error. " \
1822
1435
  "The given value is not an exception: #{error.inspect}"
1823
1436
  )
1824
1437
  end
@@ -1852,6 +1465,21 @@ describe Appsignal do
1852
1465
  expect(transaction).to include_tags("tag1" => "value1")
1853
1466
  expect(transaction).to be_completed
1854
1467
  end
1468
+
1469
+ it "yields and allows additional metadata to be set with the global helpers" do
1470
+ Appsignal.report_error(error) do
1471
+ Appsignal.set_action("my_action")
1472
+ Appsignal.set_namespace("my_namespace")
1473
+ Appsignal.set_tags(:tag1 => "value1")
1474
+ end
1475
+
1476
+ transaction = last_transaction
1477
+ expect(transaction).to have_namespace("my_namespace")
1478
+ expect(transaction).to have_action("my_action")
1479
+ expect(transaction).to have_error("ExampleException", "error message")
1480
+ expect(transaction).to include_tags("tag1" => "value1")
1481
+ expect(transaction).to be_completed
1482
+ end
1855
1483
  end
1856
1484
  end
1857
1485
 
@@ -1859,7 +1487,7 @@ describe Appsignal do
1859
1487
  let(:transaction) { http_request_transaction }
1860
1488
  before { set_current_transaction(transaction) }
1861
1489
 
1862
- it "adds the error to the active transaction" do
1490
+ it "sets the error in the active transaction" do
1863
1491
  Appsignal.report_error(error)
1864
1492
 
1865
1493
  expect(last_transaction).to eq(transaction)
@@ -1868,6 +1496,41 @@ describe Appsignal do
1868
1496
  expect(transaction).to have_error("ExampleException", "error message")
1869
1497
  end
1870
1498
 
1499
+ context "when the active transaction already has an error" do
1500
+ let(:previous_error) { ExampleException.new("previous error message") }
1501
+
1502
+ before { transaction.set_error(previous_error) }
1503
+
1504
+ it "does not overwrite the existing set error" do
1505
+ Appsignal.report_error(error)
1506
+
1507
+ transaction._sample
1508
+ expect(transaction).to have_error("ExampleException", "previous error message")
1509
+ end
1510
+
1511
+ it "adds the error to the errors" do
1512
+ Appsignal.report_error(error)
1513
+
1514
+ expect(transaction.error_blocks).to eq({ error => [], previous_error => [] })
1515
+ end
1516
+
1517
+ context "when given a block" do
1518
+ it "only applies the block to the transaction for that error" do
1519
+ Appsignal.report_error(error) do |t|
1520
+ t.set_action("my_action")
1521
+ end
1522
+
1523
+ transaction.complete
1524
+ expect(transaction).to have_error("ExampleException", "previous error message")
1525
+ expect(transaction).not_to have_action("my_action")
1526
+
1527
+ expect(last_transaction).to_not be(transaction)
1528
+ expect(last_transaction).to have_error("ExampleException", "error message")
1529
+ expect(last_transaction).to have_action("my_action")
1530
+ end
1531
+ end
1532
+ end
1533
+
1871
1534
  it "does not complete the transaction" do
1872
1535
  Appsignal.report_error(error)
1873
1536
 
@@ -1875,19 +1538,67 @@ describe Appsignal do
1875
1538
  end
1876
1539
 
1877
1540
  context "when given a block" do
1878
- it "yields the transaction and allows additional metadata to be set" do
1541
+ before do
1879
1542
  Appsignal.report_error(error) do |t|
1880
1543
  t.set_action("my_action")
1881
1544
  t.set_namespace("my_namespace")
1882
1545
  t.set_tags(:tag1 => "value1")
1883
1546
  end
1547
+ end
1548
+
1549
+ it "applies the block to the error transaction when completed" do
1550
+ expect(transaction).not_to have_namespace("my_namespace")
1551
+ expect(transaction).not_to have_action("my_action")
1552
+ expect(transaction).not_to include_tags("tag1" => "value1")
1553
+ expect(transaction).to have_error
1554
+ expect(transaction).not_to be_completed
1555
+
1556
+ transaction.complete
1557
+ expect(transaction).to have_namespace("my_namespace")
1558
+ expect(transaction).to have_action("my_action")
1559
+ expect(transaction).to include_tags("tag1" => "value1")
1560
+ expect(transaction).to have_error
1561
+ expect(transaction).to be_completed
1562
+ end
1563
+
1564
+ it "does not apply the block to other error transactions" do
1565
+ Appsignal.report_error(StandardError.new("another error"))
1566
+
1567
+ transaction.complete
1568
+ expect(created_transactions.count).to eq(2)
1884
1569
 
1885
- transaction._sample
1886
1570
  expect(transaction).to have_namespace("my_namespace")
1887
1571
  expect(transaction).to have_action("my_action")
1888
- expect(transaction).to have_error("ExampleException", "error message")
1889
1572
  expect(transaction).to include_tags("tag1" => "value1")
1573
+ expect(transaction).to have_error("ExampleException", "error message")
1574
+ expect(transaction).to be_completed
1575
+
1576
+ expect(last_transaction).not_to be(transaction)
1577
+ expect(last_transaction).not_to have_namespace("my_namespace")
1578
+ expect(last_transaction).not_to have_action("my_action")
1579
+ expect(last_transaction).not_to include_tags("tag1" => "value1")
1580
+ expect(last_transaction).to have_error("StandardError", "another error")
1581
+ expect(last_transaction).to be_completed
1582
+ end
1583
+
1584
+ it "does not create a new transaction" do
1585
+ expect(created_transactions).to eq([transaction])
1586
+ end
1587
+
1588
+ it "yields and allows additional metadata to be set with the global helpers" do
1589
+ Appsignal.report_error(error) do
1590
+ Appsignal.set_action("my_action")
1591
+ Appsignal.set_namespace("my_namespace")
1592
+ Appsignal.set_tags(:tag1 => "value1")
1593
+ end
1594
+
1890
1595
  expect(transaction).to_not be_completed
1596
+
1597
+ transaction.complete
1598
+ expect(transaction).to have_namespace("my_namespace")
1599
+ expect(transaction).to have_action("my_action")
1600
+ expect(transaction).to have_error("ExampleException", "error message")
1601
+ expect(transaction).to include_tags("tag1" => "value1")
1891
1602
  end
1892
1603
  end
1893
1604
  end
@@ -1997,30 +1708,6 @@ describe Appsignal do
1997
1708
  expect(transaction).to include_event("name" => "register.this.event")
1998
1709
  expect(transaction).to_not include_event("name" => "dont.register.this.event")
1999
1710
  end
2000
-
2001
- it "has a without_instrumentation alias that prints a deprecation warning" do
2002
- Appsignal.instrument("register.this.event") { :do_nothing }
2003
- err_stream = std_stream
2004
- logs =
2005
- capture_logs do
2006
- capture_std_streams(std_stream, err_stream) do
2007
- Appsignal.without_instrumentation do
2008
- Appsignal.instrument("dont.register.this.event") { :do_nothing }
2009
- end
2010
- end
2011
- end
2012
-
2013
- expect(transaction).to include_event("name" => "register.this.event")
2014
- expect(transaction).to_not include_event("name" => "dont.register.this.event")
2015
-
2016
- expect(logs).to contains_log(
2017
- :warn,
2018
- "The `Appsignal.without_instrumentation` helper is deprecated."
2019
- )
2020
- expect(err_stream.read).to include(
2021
- "appsignal WARNING: The `Appsignal.without_instrumentation` helper is deprecated."
2022
- )
2023
- end
2024
1711
  end
2025
1712
 
2026
1713
  context "without current transaction" do
@@ -2033,24 +1720,6 @@ describe Appsignal do
2033
1720
  end
2034
1721
  end
2035
1722
 
2036
- describe ".start_logger" do
2037
- let(:stderr_stream) { std_stream }
2038
- let(:stderr) { stderr_stream.read }
2039
- let(:log_stream) { std_stream }
2040
- let(:log) { log_contents(log_stream) }
2041
-
2042
- it "prints and logs a deprecation warning" do
2043
- use_logger_with(log_stream) do
2044
- capture_std_streams(std_stream, stderr_stream) do
2045
- Appsignal.start_logger
2046
- end
2047
- end
2048
- expect(stderr)
2049
- .to include("appsignal WARNING: Calling 'Appsignal.start_logger' is deprecated.")
2050
- expect(log).to contains_log(:warn, "Calling 'Appsignal.start_logger' is deprecated.")
2051
- end
2052
- end
2053
-
2054
1723
  describe "._start_logger" do
2055
1724
  let(:out_stream) { std_stream }
2056
1725
  let(:output) { out_stream.read }
@@ -2069,11 +1738,10 @@ describe Appsignal do
2069
1738
  after { FileUtils.rm_rf(log_path) }
2070
1739
 
2071
1740
  def initialize_config
2072
- Appsignal._config = project_fixture_config(
2073
- "production",
2074
- :log_path => log_path,
2075
- :log_level => log_level
2076
- )
1741
+ Appsignal.configure(:production, :root_path => project_fixture_path) do |config|
1742
+ config.log_path = log_path
1743
+ config.log_level = log_level
1744
+ end
2077
1745
  Appsignal.internal_logger.error("Log in memory line 1")
2078
1746
  Appsignal.internal_logger.debug("Log in memory line 2")
2079
1747
  expect(Appsignal.in_memory_logger.messages).to_not be_empty