appsignal 3.9.2-java → 3.9.3-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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +3135 -0
  3. data/.rubocop.yml +28 -20
  4. data/.rubocop_todo.yml +7 -33
  5. data/CHANGELOG.md +38 -0
  6. data/Rakefile +79 -64
  7. data/appsignal.gemspec +1 -1
  8. data/build_matrix.yml +109 -179
  9. data/ext/base.rb +1 -1
  10. data/gemfiles/hanami-2.1.gemfile +7 -0
  11. data/lib/appsignal/cli/diagnose.rb +1 -1
  12. data/lib/appsignal/config.rb +1 -1
  13. data/lib/appsignal/demo.rb +0 -1
  14. data/lib/appsignal/environment.rb +5 -1
  15. data/lib/appsignal/extension/jruby.rb +1 -1
  16. data/lib/appsignal/helpers/instrumentation.rb +1 -1
  17. data/lib/appsignal/integrations/grape.rb +19 -47
  18. data/lib/appsignal/integrations/hanami.rb +8 -7
  19. data/lib/appsignal/integrations/padrino.rb +46 -43
  20. data/lib/appsignal/integrations/railtie.rb +0 -3
  21. data/lib/appsignal/integrations/sinatra.rb +0 -1
  22. data/lib/appsignal/probes/gvl.rb +24 -2
  23. data/lib/appsignal/probes/sidekiq.rb +1 -1
  24. data/lib/appsignal/probes.rb +1 -1
  25. data/lib/appsignal/rack/abstract_middleware.rb +62 -28
  26. data/lib/appsignal/rack/event_handler.rb +12 -3
  27. data/lib/appsignal/rack/grape_middleware.rb +40 -0
  28. data/lib/appsignal/rack/hanami_middleware.rb +1 -11
  29. data/lib/appsignal/rack/rails_instrumentation.rb +14 -55
  30. data/lib/appsignal/utils/integration_memory_logger.rb +78 -0
  31. data/lib/appsignal/utils.rb +1 -0
  32. data/lib/appsignal/version.rb +1 -1
  33. data/lib/appsignal.rb +34 -33
  34. data/spec/.rubocop.yml +1 -1
  35. data/spec/lib/appsignal/cli/diagnose_spec.rb +1 -1
  36. data/spec/lib/appsignal/cli/install_spec.rb +3 -3
  37. data/spec/lib/appsignal/config_spec.rb +7 -5
  38. data/spec/lib/appsignal/demo_spec.rb +38 -41
  39. data/spec/lib/appsignal/hooks/action_cable_spec.rb +86 -167
  40. data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +8 -20
  41. data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +38 -84
  42. data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +16 -37
  43. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +4 -4
  44. data/spec/lib/appsignal/hooks/activejob_spec.rb +111 -200
  45. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +54 -91
  46. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +14 -32
  47. data/spec/lib/appsignal/hooks/excon_spec.rb +8 -12
  48. data/spec/lib/appsignal/hooks/net_http_spec.rb +7 -42
  49. data/spec/lib/appsignal/hooks/rake_spec.rb +9 -19
  50. data/spec/lib/appsignal/hooks/redis_client_spec.rb +18 -30
  51. data/spec/lib/appsignal/hooks/redis_spec.rb +10 -16
  52. data/spec/lib/appsignal/hooks/resque_spec.rb +42 -62
  53. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +33 -74
  54. data/spec/lib/appsignal/integrations/hanami_spec.rb +79 -21
  55. data/spec/lib/appsignal/integrations/http_spec.rb +12 -20
  56. data/spec/lib/appsignal/integrations/net_http_spec.rb +33 -0
  57. data/spec/lib/appsignal/integrations/object_spec.rb +29 -36
  58. data/spec/lib/appsignal/integrations/padrino_spec.rb +47 -70
  59. data/spec/lib/appsignal/integrations/que_spec.rb +43 -70
  60. data/spec/lib/appsignal/integrations/railtie_spec.rb +26 -67
  61. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +86 -160
  62. data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -1
  63. data/spec/lib/appsignal/integrations/webmachine_spec.rb +28 -39
  64. data/spec/lib/appsignal/probes/gvl_spec.rb +80 -3
  65. data/spec/lib/appsignal/probes_spec.rb +7 -4
  66. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +215 -106
  67. data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -78
  68. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +2 -12
  69. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +234 -0
  70. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +2 -16
  71. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +67 -131
  72. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +36 -44
  73. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +68 -86
  74. data/spec/lib/appsignal/transaction_spec.rb +76 -90
  75. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +163 -0
  76. data/spec/lib/appsignal_spec.rb +363 -342
  77. data/spec/support/helpers/dependency_helper.rb +6 -1
  78. data/spec/support/helpers/std_streams_helper.rb +1 -1
  79. data/spec/support/helpers/transaction_helpers.rb +8 -0
  80. data/spec/support/matchers/transaction.rb +185 -0
  81. data/spec/support/mocks/dummy_app.rb +20 -0
  82. data/spec/support/shared_examples/instrument.rb +17 -12
  83. data/spec/support/testing.rb +18 -9
  84. metadata +15 -10
  85. data/.semaphore/semaphore.yml +0 -2347
  86. data/script/lint_git +0 -22
  87. data/spec/lib/appsignal/integrations/grape_spec.rb +0 -239
  88. data/spec/support/matchers/be_completed.rb +0 -5
  89. /data/gemfiles/{hanami.gemfile → hanami-2.0.gemfile} +0 -0
@@ -4,6 +4,13 @@ describe Appsignal::Probes::GvlProbe do
4
4
 
5
5
  let(:hostname) { "some-host" }
6
6
 
7
+ around do |example|
8
+ real_program_name = $PROGRAM_NAME
9
+ example.run
10
+ ensure
11
+ $PROGRAM_NAME = real_program_name
12
+ end
13
+
7
14
  def gauges_for(metric)
8
15
  gauges = appsignal_mock.gauges.select do |gauge|
9
16
  gauge[0] == metric
@@ -14,7 +21,7 @@ describe Appsignal::Probes::GvlProbe do
14
21
  end
15
22
  end
16
23
 
17
- after(:each) { FakeGVLTools.reset }
24
+ after { FakeGVLTools.reset }
18
25
 
19
26
  it "gauges the global timer delta" do
20
27
  FakeGVLTools::GlobalTimer.monotonic_time = 100_000_000
@@ -26,6 +33,11 @@ describe Appsignal::Probes::GvlProbe do
26
33
  probe.call
27
34
 
28
35
  expect(gauges_for("gvl_global_timer")).to eq [
36
+ [200, {
37
+ :hostname => hostname,
38
+ :process_name => "rspec",
39
+ :process_id => Process.pid
40
+ }],
29
41
  [200, { :hostname => hostname }]
30
42
  ]
31
43
  end
@@ -58,7 +70,7 @@ describe Appsignal::Probes::GvlProbe do
58
70
  end
59
71
 
60
72
  context "when the waiting threads count is enabled" do
61
- before(:each) do
73
+ before do
62
74
  FakeGVLTools::WaitingThreads.enabled = true
63
75
  end
64
76
 
@@ -67,13 +79,18 @@ describe Appsignal::Probes::GvlProbe do
67
79
  probe.call
68
80
 
69
81
  expect(gauges_for("gvl_waiting_threads")).to eq [
82
+ [3, {
83
+ :hostname => hostname,
84
+ :process_name => "rspec",
85
+ :process_id => Process.pid
86
+ }],
70
87
  [3, { :hostname => hostname }]
71
88
  ]
72
89
  end
73
90
  end
74
91
 
75
92
  context "when the waiting threads count is disabled" do
76
- before(:each) do
93
+ before do
77
94
  FakeGVLTools::WaitingThreads.enabled = false
78
95
  end
79
96
 
@@ -84,4 +101,64 @@ describe Appsignal::Probes::GvlProbe do
84
101
  expect(gauges_for("gvl_waiting_threads")).to be_empty
85
102
  end
86
103
  end
104
+
105
+ context "when the process name is a custom value" do
106
+ before do
107
+ FakeGVLTools::WaitingThreads.enabled = true
108
+ end
109
+
110
+ it "uses only the first word as the process name" do
111
+ $PROGRAM_NAME = "sidekiq 7.1.6 app [0 of 5 busy]"
112
+ probe.call
113
+
114
+ expect(gauges_for("gvl_waiting_threads")).to eq [
115
+ [0, {
116
+ :hostname => hostname,
117
+ :process_name => "sidekiq",
118
+ :process_id => Process.pid
119
+ }],
120
+ [0, { :hostname => hostname }]
121
+ ]
122
+ end
123
+ end
124
+
125
+ context "when the process name is a path" do
126
+ before do
127
+ FakeGVLTools::WaitingThreads.enabled = true
128
+ end
129
+
130
+ it "uses only the binary name as the process name" do
131
+ $PROGRAM_NAME = "/foo/folder with spaces/bin/rails"
132
+ probe.call
133
+
134
+ expect(gauges_for("gvl_waiting_threads")).to eq [
135
+ [0, {
136
+ :hostname => hostname,
137
+ :process_name => "rails",
138
+ :process_id => Process.pid
139
+ }],
140
+ [0, { :hostname => hostname }]
141
+ ]
142
+ end
143
+ end
144
+
145
+ context "when the process name is an empty string" do
146
+ before do
147
+ FakeGVLTools::WaitingThreads.enabled = true
148
+ end
149
+
150
+ it "uses [unknown process] as the process name" do
151
+ $PROGRAM_NAME = ""
152
+ probe.call
153
+
154
+ expect(gauges_for("gvl_waiting_threads")).to eq [
155
+ [0, {
156
+ :hostname => hostname,
157
+ :process_name => "[unknown process]",
158
+ :process_id => Process.pid
159
+ }],
160
+ [0, { :hostname => hostname }]
161
+ ]
162
+ end
163
+ end
87
164
  end
@@ -20,7 +20,7 @@ describe Appsignal::Probes do
20
20
  .to include("appsignal WARNING: The constant Appsignal::Minutely has been deprecated.")
21
21
  end
22
22
 
23
- it "logs a warning to STDERR" do
23
+ it "logs a warning" do
24
24
  logs =
25
25
  capture_logs do
26
26
  silence do
@@ -28,7 +28,10 @@ describe Appsignal::Probes do
28
28
  end
29
29
  end
30
30
 
31
- expect(logs).to include("The constant Appsignal::Minutely has been deprecated.")
31
+ expect(logs).to contains_log(
32
+ :warn,
33
+ "The constant Appsignal::Minutely has been deprecated."
34
+ )
32
35
  end
33
36
  end
34
37
 
@@ -78,7 +81,7 @@ describe Appsignal::Probes do
78
81
  describe ".started?" do
79
82
  it "returns true when the probes thread has been started" do
80
83
  expect(Appsignal::Probes.started?).to be_falsy
81
- Appsignal::Probes.register :my_probe, (lambda {})
84
+ Appsignal::Probes.register :my_probe, lambda {}
82
85
  Appsignal::Probes.start
83
86
  expect(Appsignal::Probes.started?).to be_truthy
84
87
  end
@@ -475,7 +478,7 @@ describe Appsignal::Probes do
475
478
  probe = lambda {}
476
479
  collection.internal_register :my_probe, probe
477
480
  list = []
478
- collection.each do |name, p|
481
+ collection.each do |name, p| # rubocop:disable Style/MapIntoArray
479
482
  list << [name, p]
480
483
  end
481
484
  expect(list).to eql([[:my_probe, probe]])
@@ -1,5 +1,5 @@
1
1
  describe Appsignal::Rack::AbstractMiddleware do
2
- let(:app) { double(:call => true) }
2
+ let(:app) { DummyApp.new }
3
3
  let(:request_path) { "/some/path" }
4
4
  let(:env) do
5
5
  Rack::MockRequest.env_for(
@@ -9,176 +9,235 @@ describe Appsignal::Rack::AbstractMiddleware do
9
9
  )
10
10
  end
11
11
  let(:options) { {} }
12
- let(:middleware) { Appsignal::Rack::AbstractMiddleware.new(app, options) }
12
+ let(:middleware) { described_class.new(app, options) }
13
13
 
14
14
  before(:context) { start_agent }
15
15
  around { |example| keep_transactions { example.run } }
16
16
 
17
- def make_request(env)
17
+ def make_request
18
18
  middleware.call(env)
19
19
  end
20
20
 
21
- def make_request_with_error(env, error)
22
- expect { make_request(env) }.to raise_error(error)
21
+ def make_request_with_error(error_class, error_message)
22
+ expect { make_request }.to raise_error(error_class, error_message)
23
23
  end
24
24
 
25
25
  describe "#call" do
26
- context "when appsignal is not active" do
26
+ context "when not active" do
27
27
  before { allow(Appsignal).to receive(:active?).and_return(false) }
28
28
 
29
- it "does not instrument requests" do
30
- expect { make_request(env) }.to_not(change { created_transactions.count })
29
+ it "does not instrument the request" do
30
+ expect { make_request }.to_not(change { created_transactions.count })
31
31
  end
32
32
 
33
33
  it "calls the next middleware in the stack" do
34
- expect(app).to receive(:call).with(env)
35
- make_request(env)
34
+ make_request
35
+ expect(app).to be_called
36
36
  end
37
37
  end
38
38
 
39
39
  context "when appsignal is active" do
40
40
  before { allow(Appsignal).to receive(:active?).and_return(true) }
41
41
 
42
- it "calls the next middleware in the stack" do
43
- make_request(env)
42
+ it "creates a transaction for the request" do
43
+ expect { make_request }.to(change { created_transactions.count }.by(1))
44
44
 
45
- expect(app).to have_received(:call).with(env)
45
+ expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
46
46
  end
47
47
 
48
- context "without an exception" do
49
- it "create a transaction for the request" do
50
- expect { make_request(env) }.to(change { created_transactions.count }.by(1))
48
+ context "without an error" do
49
+ before { make_request }
51
50
 
52
- expect(last_transaction.to_h).to include(
53
- "namespace" => Appsignal::Transaction::HTTP_REQUEST,
54
- "action" => nil,
55
- "error" => nil
56
- )
51
+ it "calls the next middleware in the stack" do
52
+ expect(app).to be_called
57
53
  end
58
54
 
59
- it "reports a process.abstract event" do
60
- make_request(env)
55
+ it "does not record an error" do
56
+ expect(last_transaction).to_not have_error
57
+ end
61
58
 
62
- expect(last_transaction.to_h).to include(
63
- "events" => [
64
- hash_including(
65
- "body" => "",
66
- "body_format" => Appsignal::EventFormatter::DEFAULT,
67
- "count" => 1,
68
- "name" => "process.abstract",
69
- "title" => ""
70
- )
71
- ]
72
- )
59
+ it "records an instrumentation event" do
60
+ expect(last_transaction).to include_event(:name => "process.abstract")
73
61
  end
74
62
 
75
63
  it "completes the transaction" do
76
- make_request(env)
77
64
  expect(last_transaction).to be_completed
65
+ expect(Appsignal::Transaction.current)
66
+ .to be_kind_of(Appsignal::Transaction::NilTransaction)
67
+ end
68
+
69
+ context "when instrument_span_name option is nil" do
70
+ let(:options) { { :instrument_span_name => nil } }
71
+
72
+ it "does not record an instrumentation event" do
73
+ expect(last_transaction).to_not include_events
74
+ end
78
75
  end
79
76
  end
80
77
 
81
- context "with an exception" do
78
+ context "with an error" do
82
79
  let(:error) { ExampleException.new("error message") }
83
- before do
84
- allow(app).to receive(:call).and_raise(error)
85
- expect { make_request_with_error(env, error) }
80
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
81
+
82
+ it "create a transaction for the request" do
83
+ expect { make_request_with_error(ExampleException, "error message") }
86
84
  .to(change { created_transactions.count }.by(1))
87
- end
88
85
 
89
- it "creates a transaction for the request and records the exception" do
90
- expect(last_transaction.to_h).to include(
91
- "error" => hash_including(
92
- "name" => "ExampleException",
93
- "message" => "error message"
94
- )
95
- )
86
+ expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
96
87
  end
97
88
 
98
- it "completes the transaction" do
99
- expect(last_transaction).to be_completed
89
+ describe "error" do
90
+ before do
91
+ make_request_with_error(ExampleException, "error message")
92
+ end
93
+
94
+ it "records the error" do
95
+ expect(last_transaction).to have_error("ExampleException", "error message")
96
+ end
97
+
98
+ it "completes the transaction" do
99
+ expect(last_transaction).to be_completed
100
+ expect(Appsignal::Transaction.current)
101
+ .to be_kind_of(Appsignal::Transaction::NilTransaction)
102
+ end
103
+
104
+ context "with :report_errors set to false" do
105
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
106
+ let(:options) { { :report_errors => false } }
107
+
108
+ it "does not record the exception on the transaction" do
109
+ expect(last_transaction).to_not have_error
110
+ end
111
+ end
112
+
113
+ context "with :report_errors set to true" do
114
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
115
+ let(:options) { { :report_errors => true } }
116
+
117
+ it "records the exception on the transaction" do
118
+ expect(last_transaction).to have_error("ExampleException", "error message")
119
+ end
120
+ end
121
+
122
+ context "with :report_errors set to a lambda that returns false" do
123
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
124
+ let(:options) { { :report_errors => lambda { |_env| false } } }
125
+
126
+ it "does not record the exception on the transaction" do
127
+ expect(last_transaction).to_not have_error
128
+ end
129
+ end
130
+
131
+ context "with :report_errors set to a lambda that returns true" do
132
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
133
+ let(:options) { { :report_errors => lambda { |_env| true } } }
134
+
135
+ it "records the exception on the transaction" do
136
+ expect(last_transaction).to have_error("ExampleException", "error message")
137
+ end
138
+ end
100
139
  end
101
140
  end
102
141
 
103
142
  context "without action name metadata" do
104
143
  it "reports no action name" do
105
- make_request(env)
144
+ make_request
106
145
 
107
- expect(last_transaction.to_h).to include("action" => nil)
146
+ expect(last_transaction).to_not have_action
108
147
  end
109
148
  end
110
149
 
111
150
  context "with appsignal.route env" do
112
- before do
113
- env["appsignal.route"] = "POST /my-route"
114
- end
115
-
116
151
  it "reports the appsignal.route value as the action name" do
117
- make_request(env)
152
+ env["appsignal.route"] = "POST /my-route"
153
+ make_request
118
154
 
119
- expect(last_transaction.to_h).to include("action" => "POST /my-route")
155
+ expect(last_transaction).to have_action("POST /my-route")
120
156
  end
121
157
  end
122
158
 
123
159
  context "with appsignal.action env" do
124
- before do
125
- env["appsignal.action"] = "POST /my-action"
126
- end
127
-
128
160
  it "reports the appsignal.route value as the action name" do
129
- make_request(env)
161
+ env["appsignal.action"] = "POST /my-action"
162
+ make_request
130
163
 
131
- expect(last_transaction.to_h).to include("action" => "POST /my-action")
164
+ expect(last_transaction).to have_action("POST /my-action")
132
165
  end
133
166
  end
134
167
 
135
168
  describe "request metadata" do
136
- before do
137
- env.merge("PATH_INFO" => "/some/path", "REQUEST_METHOD" => "GET")
138
- end
139
-
140
169
  it "sets request metadata" do
141
- make_request(env)
142
-
143
- expect(last_transaction.to_h).to include(
144
- "metadata" => {
145
- "method" => "GET",
146
- "path" => "/some/path"
147
- },
148
- "sample_data" => hash_including(
149
- "environment" => hash_including(
150
- "REQUEST_METHOD" => "GET",
151
- "PATH_INFO" => "/some/path"
152
- # and more, but we don't need to test Rack mock defaults
153
- )
154
- )
170
+ env.merge!("PATH_INFO" => "/some/path", "REQUEST_METHOD" => "GET")
171
+ make_request
172
+
173
+ expect(last_transaction).to include_metadata(
174
+ "method" => "GET",
175
+ "path" => "/some/path"
176
+ )
177
+ expect(last_transaction).to include_environment(
178
+ "REQUEST_METHOD" => "GET",
179
+ "PATH_INFO" => "/some/path"
180
+ # and more, but we don't need to test Rack mock defaults
155
181
  )
156
182
  end
157
183
 
184
+ context "with an invalid HTTP request method" do
185
+ it "stores the invalid HTTP request method" do
186
+ env["REQUEST_METHOD"] = "FOO"
187
+ make_request
188
+
189
+ expect(last_transaction).to include_metadata("method" => "FOO")
190
+ end
191
+ end
192
+
193
+ context "with fetching the request method raises an error" do
194
+ class BrokenRequestMethodRequest < Rack::Request
195
+ def request_method
196
+ raise "uh oh!"
197
+ end
198
+ end
199
+
200
+ let(:options) { { :request_class => BrokenRequestMethodRequest } }
201
+ it "does not store the invalid HTTP request method" do
202
+ env["REQUEST_METHOD"] = "FOO"
203
+ make_request
204
+
205
+ expect(last_transaction).to_not include_metadata("method" => anything)
206
+ end
207
+ end
208
+
158
209
  it "sets request parameters" do
159
- make_request(env)
160
-
161
- expect(last_transaction.to_h).to include(
162
- "sample_data" => hash_including(
163
- "params" => hash_including(
164
- "page" => "2",
165
- "query" => "lorem"
166
- )
167
- )
210
+ make_request
211
+
212
+ expect(last_transaction).to include_params(
213
+ "page" => "2",
214
+ "query" => "lorem"
168
215
  )
169
216
  end
217
+
218
+ context "when setting custom params" do
219
+ let(:app) do
220
+ DummyApp.new do |_env|
221
+ Appsignal::Transaction.current.set_params("custom" => "param")
222
+ end
223
+ end
224
+
225
+ it "allow custom request parameters to be set" do
226
+ make_request
227
+
228
+ expect(last_transaction).to include_params("custom" => "param")
229
+ end
230
+ end
170
231
  end
171
232
 
172
233
  context "with queue start header" do
173
234
  let(:queue_start_time) { fixed_time * 1_000 }
174
- before do
175
- env["HTTP_X_REQUEST_START"] = "t=#{queue_start_time.to_i}" # in milliseconds
176
- end
177
235
 
178
236
  it "sets the queue start" do
179
- make_request(env)
237
+ env["HTTP_X_REQUEST_START"] = "t=#{queue_start_time.to_i}" # in milliseconds
238
+ make_request
180
239
 
181
- expect(last_transaction.ext.queue_start).to eq(queue_start_time)
240
+ expect(last_transaction).to have_queue_start(queue_start_time)
182
241
  end
183
242
  end
184
243
 
@@ -208,13 +267,9 @@ describe Appsignal::Rack::AbstractMiddleware do
208
267
  end
209
268
 
210
269
  it "uses the overridden request class and params method to fetch params" do
211
- make_request(env)
270
+ make_request
212
271
 
213
- expect(last_transaction.to_h).to include(
214
- "sample_data" => hash_including(
215
- "params" => { "abc" => "123" }
216
- )
217
- )
272
+ expect(last_transaction).to include_params("abc" => "123")
218
273
  end
219
274
  end
220
275
 
@@ -224,13 +279,23 @@ describe Appsignal::Rack::AbstractMiddleware do
224
279
  end
225
280
 
226
281
  it "uses the existing transaction" do
227
- make_request(env)
282
+ make_request
228
283
 
229
- expect { make_request(env) }.to_not(change { created_transactions.count })
284
+ expect { make_request }.to_not(change { created_transactions.count })
285
+ end
286
+
287
+ context "with error" do
288
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
289
+
290
+ it "doesn't record the error on the transaction" do
291
+ make_request_with_error(ExampleException, "error message")
292
+
293
+ expect(last_transaction).to_not have_error
294
+ end
230
295
  end
231
296
 
232
297
  it "doesn't complete the existing transaction" do
233
- make_request(env)
298
+ make_request
234
299
 
235
300
  expect(env[Appsignal::Rack::APPSIGNAL_TRANSACTION]).to_not be_completed
236
301
  end
@@ -239,9 +304,53 @@ describe Appsignal::Rack::AbstractMiddleware do
239
304
  it "does not overwrite the action name" do
240
305
  env[Appsignal::Rack::APPSIGNAL_TRANSACTION].set_action("My custom action")
241
306
  env["appsignal.action"] = "POST /my-action"
242
- make_request(env)
307
+ make_request
308
+
309
+ expect(last_transaction).to have_action("My custom action")
310
+ end
311
+ end
312
+
313
+ context "with :report_errors set to false" do
314
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
315
+ let(:options) { { :report_errors => false } }
316
+
317
+ it "does not record the error on the transaction" do
318
+ make_request_with_error(ExampleException, "error message")
319
+
320
+ expect(last_transaction).to_not have_error
321
+ end
322
+ end
323
+
324
+ context "with :report_errors set to true" do
325
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
326
+ let(:options) { { :report_errors => true } }
327
+
328
+ it "records the error on the transaction" do
329
+ make_request_with_error(ExampleException, "error message")
330
+
331
+ expect(last_transaction).to have_error("ExampleException", "error message")
332
+ end
333
+ end
334
+
335
+ context "with :report_errors set to a lambda that returns false" do
336
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
337
+ let(:options) { { :report_errors => lambda { |_env| false } } }
338
+
339
+ it "does not record the exception on the transaction" do
340
+ make_request_with_error(ExampleException, "error message")
341
+
342
+ expect(last_transaction).to_not have_error
343
+ end
344
+ end
345
+
346
+ context "with :report_errors set to a lambda that returns true" do
347
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
348
+ let(:options) { { :report_errors => lambda { |_env| true } } }
349
+
350
+ it "records the error on the transaction" do
351
+ make_request_with_error(ExampleException, "error message")
243
352
 
244
- expect(last_transaction.to_h).to include("action" => "My custom action")
353
+ expect(last_transaction).to have_error("ExampleException", "error message")
245
354
  end
246
355
  end
247
356
  end