appsignal 3.8.1 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,91 +1,38 @@
1
1
  describe Appsignal::Rack::GenericInstrumentation do
2
- before :context do
3
- start_agent
4
- end
5
-
6
2
  let(:app) { double(:call => true) }
7
- let(:env) { { :path => "/", :method => "GET" } }
8
- let(:options) { {} }
9
- let(:middleware) { Appsignal::Rack::GenericInstrumentation.new(app, options) }
10
-
11
- describe "#call" do
12
- before do
13
- allow(middleware).to receive(:raw_payload).and_return({})
14
- end
15
-
16
- context "when appsignal is active" do
17
- before { allow(Appsignal).to receive(:active?).and_return(true) }
18
-
19
- it "should call with monitoring" do
20
- expect(middleware).to receive(:call_with_appsignal_monitoring).with(env)
21
- end
22
- end
23
-
24
- context "when appsignal is not active" do
25
- before { allow(Appsignal).to receive(:active?).and_return(false) }
26
-
27
- it "should not call with monitoring" do
28
- expect(middleware).to_not receive(:call_with_appsignal_monitoring)
29
- end
3
+ let(:env) { Rack::MockRequest.env_for("/some/path") }
4
+ let(:middleware) { Appsignal::Rack::GenericInstrumentation.new(app, {}) }
30
5
 
31
- it "should call the stack" do
32
- expect(app).to receive(:call).with(env)
33
- end
34
- end
6
+ before(:context) { start_agent }
7
+ around { |example| keep_transactions { example.run } }
35
8
 
36
- after { middleware.call(env) }
9
+ def make_request(env)
10
+ middleware.call(env)
37
11
  end
38
12
 
39
- describe "#call_with_appsignal_monitoring", :error => false do
40
- it "should create a transaction" do
41
- expect(Appsignal::Transaction).to receive(:create).with(
42
- kind_of(String),
43
- Appsignal::Transaction::HTTP_REQUEST,
44
- kind_of(Rack::Request)
45
- ).and_return(double(:set_action_if_nil => nil, :set_http_or_background_queue_start => nil,
46
- :set_metadata => nil))
47
- end
48
-
49
- it "should call the app" do
50
- expect(app).to receive(:call).with(env)
13
+ context "without an exception" do
14
+ it "reports a process_action.generic event" do
15
+ make_request(env)
16
+
17
+ expect(last_transaction.to_h).to include(
18
+ "events" => [
19
+ hash_including(
20
+ "body" => "",
21
+ "body_format" => Appsignal::EventFormatter::DEFAULT,
22
+ "count" => 1,
23
+ "name" => "process_action.generic",
24
+ "title" => ""
25
+ )
26
+ ]
27
+ )
51
28
  end
29
+ end
52
30
 
53
- context "with an exception", :error => true do
54
- let(:error) { ExampleException }
55
- let(:app) do
56
- double.tap do |d|
57
- allow(d).to receive(:call).and_raise(error)
58
- end
59
- end
60
-
61
- it "records the exception" do
62
- expect_any_instance_of(Appsignal::Transaction).to receive(:set_error).with(error)
63
- end
64
- end
65
-
66
- it "should set the action to unknown" do
67
- expect_any_instance_of(Appsignal::Transaction).to receive(:set_action_if_nil).with("unknown")
68
- end
69
-
70
- context "with a route specified in the env" do
71
- before do
72
- env["appsignal.route"] = "GET /"
73
- end
74
-
75
- it "should set the action" do
76
- expect_any_instance_of(Appsignal::Transaction).to receive(:set_action_if_nil).with("GET /")
77
- end
78
- end
31
+ context "without action name metadata" do
32
+ it "reports 'unknown' as the action name" do
33
+ make_request(env)
79
34
 
80
- it "should set metadata" do
81
- expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata).twice
35
+ expect(last_transaction.to_h).to include("action" => "unknown")
82
36
  end
83
-
84
- it "should set the queue start" do
85
- expect_any_instance_of(Appsignal::Transaction).to receive(:set_http_or_background_queue_start)
86
- end
87
-
88
- after(:error => false) { middleware.call(env) }
89
- after(:error => true) { expect { middleware.call(env) }.to raise_error(error) }
90
37
  end
91
38
  end
@@ -16,7 +16,9 @@ if DependencyHelper.sinatra_present?
16
16
 
17
17
  let(:settings) { double(:raise_errors => false) }
18
18
  let(:app) { double(:call => true, :settings => settings) }
19
- let(:env) { { "sinatra.route" => "GET /", :path => "/", :method => "GET" } }
19
+ let(:env) do
20
+ Rack::MockRequest.env_for("/path", "sinatra.route" => "GET /path", "REQUEST_METHOD" => "GET")
21
+ end
20
22
  let(:middleware) { Appsignal::Rack::SinatraInstrumentation.new(app) }
21
23
 
22
24
  before(:context) { start_agent }
@@ -28,8 +30,7 @@ if DependencyHelper.sinatra_present?
28
30
  before { allow(middleware).to receive(:raw_payload).and_return({}) }
29
31
 
30
32
  it "doesn't instrument requests" do
31
- make_request(env)
32
- expect(created_transactions.count).to eq(0)
33
+ expect { make_request(env) }.to_not(change { created_transactions.count })
33
34
  end
34
35
  end
35
36
 
@@ -47,7 +48,9 @@ if DependencyHelper.sinatra_present?
47
48
 
48
49
  let(:settings) { double(:raise_errors => false) }
49
50
  let(:app) { double(:call => true, :settings => settings) }
50
- let(:env) { { "sinatra.route" => "GET /", :path => "/", :method => "GET" } }
51
+ let(:env) do
52
+ Rack::MockRequest.env_for("/path", "sinatra.route" => "GET /path", "REQUEST_METHOD" => "GET")
53
+ end
51
54
  let(:options) { {} }
52
55
  let(:middleware) { Appsignal::Rack::SinatraBaseInstrumentation.new(app, options) }
53
56
 
@@ -93,216 +96,129 @@ if DependencyHelper.sinatra_present?
93
96
  describe "#call" do
94
97
  before { allow(middleware).to receive(:raw_payload).and_return({}) }
95
98
 
96
- context "when appsignal is active" do
97
- it "instruments requests" do
98
- expect(middleware).to receive(:call_with_appsignal_monitoring).with(env)
99
- end
100
- end
101
-
102
99
  context "when appsignal is not active" do
103
100
  before { allow(Appsignal).to receive(:active?).and_return(false) }
104
101
 
105
102
  it "does not instrument requests" do
106
- expect(created_transactions.count).to eq(0)
103
+ expect { make_request(env) }.to_not(change { created_transactions.count })
107
104
  end
108
105
 
109
106
  it "calls the next middleware in the stack" do
110
- expect(app).to receive(:call).with(env)
111
- end
112
- end
113
-
114
- after { make_request(env) }
115
- end
116
-
117
- describe "#call_with_appsignal_monitoring" do
118
- context "without an error" do
119
- it "creates a transaction" do
120
- expect(app).to receive(:call).with(env)
121
-
122
107
  make_request(env)
123
108
 
124
- expect(created_transactions.count).to eq(1)
125
- expect(last_transaction.to_h).to include(
126
- "namespace" => Appsignal::Transaction::HTTP_REQUEST,
127
- "action" => "GET /",
128
- "error" => nil,
129
- "metadata" => { "path" => "" }
130
- )
131
- end
132
- end
133
-
134
- context "with an error" do
135
- let(:error) { ExampleException }
136
- let(:app) do
137
- double.tap do |d|
138
- allow(d).to receive(:call).and_raise(error)
139
- allow(d).to receive(:settings).and_return(settings)
140
- end
141
- end
142
-
143
- it "records the exception" do
144
- make_request_with_error(env, error)
145
-
146
- expect(created_transactions.count).to eq(1)
147
- expect(last_transaction.to_h).to include(
148
- "namespace" => Appsignal::Transaction::HTTP_REQUEST,
149
- "action" => "GET /",
150
- "error" => hash_including(
151
- "name" => "ExampleException",
152
- "message" => "ExampleException"
153
- )
154
- )
109
+ expect(app).to have_received(:call).with(env)
155
110
  end
156
111
  end
157
112
 
158
- context "with an error in sinatra.error" do
159
- let(:error) { ExampleException.new }
160
- let(:env) { { "sinatra.error" => error } }
161
-
162
- context "when raise_errors is off" do
163
- let(:settings) { double(:raise_errors => false) }
164
-
165
- it "record the error" do
113
+ context "when appsignal is active" do
114
+ context "without an exception" do
115
+ it "reports a process_action.sinatra event" do
166
116
  make_request(env)
167
117
 
168
- expect(created_transactions.count).to eq(1)
169
118
  expect(last_transaction.to_h).to include(
170
- "error" => hash_including(
171
- "name" => "ExampleException",
172
- "message" => "ExampleException"
173
- )
119
+ "events" => [
120
+ hash_including(
121
+ "body" => "",
122
+ "body_format" => Appsignal::EventFormatter::DEFAULT,
123
+ "count" => 1,
124
+ "name" => "process_action.sinatra",
125
+ "title" => ""
126
+ )
127
+ ]
174
128
  )
175
129
  end
176
130
  end
177
131
 
178
- context "when raise_errors is on" do
179
- let(:settings) { double(:raise_errors => true) }
180
-
181
- it "does not record the error" do
182
- make_request(env)
183
-
184
- expect(created_transactions.count).to eq(1)
185
- expect(last_transaction.to_h).to include("error" => nil)
132
+ context "with an error in sinatra.error" do
133
+ let(:error) { ExampleException.new("error message") }
134
+ before do
135
+ env["sinatra.error"] = error
186
136
  end
187
- end
188
137
 
189
- context "if sinatra.skip_appsignal_error is set" do
190
- let(:env) { { "sinatra.error" => error, "sinatra.skip_appsignal_error" => true } }
138
+ context "when raise_errors is off" do
139
+ let(:settings) { double(:raise_errors => false) }
191
140
 
192
- it "does not record the error" do
193
- make_request(env)
141
+ it "record the error" do
142
+ expect { make_request(env) }
143
+ .to(change { created_transactions.count }.by(1))
194
144
 
195
- expect(created_transactions.count).to eq(1)
196
- expect(last_transaction.to_h).to include("error" => nil)
145
+ expect(last_transaction.to_h).to include(
146
+ "error" => hash_including(
147
+ "name" => "ExampleException",
148
+ "message" => "error message"
149
+ )
150
+ )
151
+ end
197
152
  end
198
- end
199
- end
200
153
 
201
- describe "action name" do
202
- it "sets the action" do
203
- make_request(env)
154
+ context "when raise_errors is on" do
155
+ let(:settings) { double(:raise_errors => true) }
204
156
 
205
- expect(created_transactions.count).to eq(1)
206
- expect(last_transaction.to_h).to include("action" => "GET /")
207
- end
157
+ it "does not record the error" do
158
+ expect { make_request(env) }
159
+ .to(change { created_transactions.count }.by(1))
160
+
161
+ expect(last_transaction.to_h).to include("error" => nil)
162
+ end
163
+ end
208
164
 
209
- context "without 'sinatra.route' env" do
210
- let(:env) { { :path => "/", :method => "GET" } }
165
+ context "if sinatra.skip_appsignal_error is set" do
166
+ before do
167
+ env.merge!(
168
+ "sinatra.error" => error,
169
+ "sinatra.skip_appsignal_error" => true
170
+ )
171
+ end
211
172
 
212
- it "doesn't set an action name" do
213
- make_request(env)
173
+ it "does not record the error" do
174
+ expect { make_request(env) }
175
+ .to(change { created_transactions.count }.by(1))
214
176
 
215
- expect(created_transactions.count).to eq(1)
216
- expect(last_transaction.to_h).to include("action" => nil)
177
+ expect(last_transaction.to_h).to include("error" => nil)
178
+ end
217
179
  end
218
180
  end
219
181
 
220
- context "with mounted modular application" do
221
- before { env["SCRIPT_NAME"] = "/api" }
222
-
223
- it "should call set_action with an application prefix path" do
182
+ describe "action name" do
183
+ it "sets the action to the request method and path" do
224
184
  make_request(env)
225
185
 
226
- expect(created_transactions.count).to eq(1)
227
- expect(last_transaction.to_h).to include("action" => "GET /api/")
186
+ expect(last_transaction.to_h).to include("action" => "GET /path")
228
187
  end
229
188
 
230
189
  context "without 'sinatra.route' env" do
231
- let(:env) { { :path => "/", :method => "GET" } }
190
+ let(:env) do
191
+ Rack::MockRequest.env_for("/path", "REQUEST_METHOD" => "GET")
192
+ end
232
193
 
233
194
  it "doesn't set an action name" do
234
195
  make_request(env)
235
196
 
236
- expect(created_transactions.count).to eq(1)
237
197
  expect(last_transaction.to_h).to include("action" => nil)
238
198
  end
239
199
  end
240
- end
241
- end
242
-
243
- context "metadata" do
244
- let(:env) { { "PATH_INFO" => "/some/path", "REQUEST_METHOD" => "GET" } }
245
-
246
- it "sets metadata from the environment" do
247
- make_request(env)
248
-
249
- expect(created_transactions.count).to eq(1)
250
- expect(last_transaction.to_h).to include(
251
- "metadata" => {
252
- "method" => "GET",
253
- "path" => "/some/path"
254
- },
255
- "sample_data" => hash_including(
256
- "environment" => hash_including(
257
- "REQUEST_METHOD" => "GET",
258
- "PATH_INFO" => "/some/path"
259
- )
260
- )
261
- )
262
- end
263
- end
264
200
 
265
- context "with queue start" do
266
- let(:queue_start_time) { fixed_time * 1_000 }
267
- let(:env) do
268
- { "HTTP_X_REQUEST_START" => "t=#{queue_start_time.to_i}" } # in milliseconds
269
- end
270
-
271
- it "sets the queue start" do
272
- make_request(env)
273
- expect(last_transaction.ext.queue_start).to eq(queue_start_time)
274
- end
275
- end
276
-
277
- class FilteredRequest
278
- def initialize(_args) # rubocop:disable Style/RedundantInitialize
279
- end
280
-
281
- def path
282
- "/static/path"
283
- end
201
+ context "with mounted modular application" do
202
+ before { env["SCRIPT_NAME"] = "/api" }
284
203
 
285
- def request_method
286
- "GET"
287
- end
204
+ it "sets the action name with an application prefix path" do
205
+ make_request(env)
288
206
 
289
- def filtered_params
290
- { "abc" => "123" }
291
- end
292
- end
207
+ expect(last_transaction.to_h).to include("action" => "GET /api/path")
208
+ end
293
209
 
294
- context "with overridden request class and params method" do
295
- let(:options) { { :request_class => FilteredRequest, :params_method => :filtered_params } }
210
+ context "without 'sinatra.route' env" do
211
+ let(:env) do
212
+ Rack::MockRequest.env_for("/path", "REQUEST_METHOD" => "GET")
213
+ end
296
214
 
297
- it "uses the overridden request class and params method to fetch params" do
298
- make_request(env)
215
+ it "doesn't set an action name" do
216
+ make_request(env)
299
217
 
300
- expect(created_transactions.count).to eq(1)
301
- expect(last_transaction.to_h).to include(
302
- "sample_data" => hash_including(
303
- "params" => { "abc" => "123" }
304
- )
305
- )
218
+ expect(last_transaction.to_h).to include("action" => nil)
219
+ end
220
+ end
221
+ end
306
222
  end
307
223
  end
308
224
  end
data/support/install_deps CHANGED
@@ -4,6 +4,12 @@ set -eu
4
4
 
5
5
  gem_args="--no-verbose --no-document"
6
6
 
7
+ # Workaround for https://github.com/jruby/jruby/issues/7059
8
+ if [[ "${RUBY_VERSION}" == *"jruby"* ]]; then
9
+ echo "Skipping rubygems and bundler update for JRuby"
10
+ exit 0
11
+ fi
12
+
7
13
  case "${_RUBYGEMS_VERSION-"latest"}" in
8
14
  "latest")
9
15
  echo "Updating rubygems"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appsignal
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.1
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Beekman
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-06-17 00:00:00.000000000 Z
13
+ date: 2024-06-21 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -271,6 +271,7 @@ files:
271
271
  - lib/appsignal/probes/helpers.rb
272
272
  - lib/appsignal/probes/mri.rb
273
273
  - lib/appsignal/probes/sidekiq.rb
274
+ - lib/appsignal/rack/abstract_middleware.rb
274
275
  - lib/appsignal/rack/event_handler.rb
275
276
  - lib/appsignal/rack/generic_instrumentation.rb
276
277
  - lib/appsignal/rack/rails_instrumentation.rb
@@ -372,6 +373,7 @@ files:
372
373
  - spec/lib/appsignal/probes/mri_spec.rb
373
374
  - spec/lib/appsignal/probes/sidekiq_spec.rb
374
375
  - spec/lib/appsignal/probes_spec.rb
376
+ - spec/lib/appsignal/rack/abstract_middleware_spec.rb
375
377
  - spec/lib/appsignal/rack/event_handler_spec.rb
376
378
  - spec/lib/appsignal/rack/generic_instrumentation_spec.rb
377
379
  - spec/lib/appsignal/rack/rails_instrumentation_spec.rb