appsignal 2.10.7-java → 2.11.0.alpha.2-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.
- checksums.yaml +4 -4
- data/.semaphore/semaphore.yml +45 -53
- data/CHANGELOG.md +18 -0
- data/build_matrix.yml +13 -6
- data/ext/agent.yml +19 -19
- data/ext/appsignal_extension.c +10 -1
- data/ext/base.rb +15 -4
- data/gemfiles/padrino.gemfile +2 -2
- data/lib/appsignal.rb +21 -1
- data/lib/appsignal/capistrano.rb +2 -0
- data/lib/appsignal/config.rb +6 -2
- data/lib/appsignal/environment.rb +126 -0
- data/lib/appsignal/extension/jruby.rb +10 -0
- data/lib/appsignal/hooks/net_http.rb +2 -0
- data/lib/appsignal/hooks/puma.rb +2 -58
- data/lib/appsignal/hooks/redis.rb +2 -0
- data/lib/appsignal/hooks/sequel.rb +2 -0
- data/lib/appsignal/hooks/sidekiq.rb +2 -99
- data/lib/appsignal/integrations/delayed_job_plugin.rb +16 -3
- data/lib/appsignal/integrations/object.rb +4 -0
- data/lib/appsignal/integrations/resque_active_job.rb +12 -4
- data/lib/appsignal/probes/puma.rb +61 -0
- data/lib/appsignal/probes/sidekiq.rb +102 -0
- data/lib/appsignal/rack/js_exception_catcher.rb +5 -2
- data/lib/appsignal/transaction.rb +22 -7
- data/lib/appsignal/version.rb +1 -1
- data/lib/puma/plugin/appsignal.rb +2 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +2 -1
- data/spec/lib/appsignal/config_spec.rb +6 -1
- data/spec/lib/appsignal/environment_spec.rb +167 -0
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +198 -166
- data/spec/lib/appsignal/hooks/puma_spec.rb +2 -181
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +256 -462
- data/spec/lib/appsignal/integrations/padrino_spec.rb +1 -1
- data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +55 -13
- data/spec/lib/appsignal/probes/puma_spec.rb +180 -0
- data/spec/lib/appsignal/probes/sidekiq_spec.rb +201 -0
- data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +9 -4
- data/spec/lib/appsignal/transaction_spec.rb +30 -13
- data/spec/lib/appsignal_spec.rb +22 -0
- data/spec/lib/puma/appsignal_spec.rb +1 -1
- data/spec/support/helpers/dependency_helper.rb +5 -0
- data/spec/support/helpers/env_helpers.rb +1 -1
- data/spec/support/helpers/environment_metdata_helper.rb +16 -0
- data/spec/support/stubs/sidekiq/api.rb +1 -1
- metadata +19 -8
@@ -36,6 +36,7 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
36
36
|
let(:time) { Time.parse("01-01-2001 10:01:00UTC") }
|
37
37
|
let(:created_at) { time - 3600 }
|
38
38
|
let(:run_at) { time - 3600 }
|
39
|
+
let(:payload_object) { double(:args => args) }
|
39
40
|
let(:job_data) do
|
40
41
|
{
|
41
42
|
:id => 123,
|
@@ -45,38 +46,40 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
45
46
|
:queue => "default",
|
46
47
|
:created_at => created_at,
|
47
48
|
:run_at => run_at,
|
48
|
-
:payload_object =>
|
49
|
+
:payload_object => payload_object
|
49
50
|
}
|
50
51
|
end
|
51
52
|
let(:args) { ["argument"] }
|
52
53
|
let(:job) { double(job_data) }
|
53
54
|
let(:invoked_block) { proc {} }
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
:class => "TestClass",
|
59
|
-
:method => "perform",
|
60
|
-
:metadata => {
|
61
|
-
:priority => 1,
|
62
|
-
:attempts => 1,
|
63
|
-
:queue => "default",
|
64
|
-
:id => "123"
|
65
|
-
},
|
66
|
-
:params => args,
|
67
|
-
:queue_start => run_at
|
68
|
-
}
|
69
|
-
end
|
70
|
-
after do
|
71
|
-
Timecop.freeze(time) do
|
56
|
+
def perform
|
57
|
+
Timecop.freeze(time) do
|
58
|
+
keep_transactions do
|
72
59
|
plugin.invoke_with_instrumentation(job, invoked_block)
|
73
60
|
end
|
74
61
|
end
|
62
|
+
end
|
75
63
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
64
|
+
context "with a normal call" do
|
65
|
+
it "wraps it in a transaction" do
|
66
|
+
perform
|
67
|
+
transaction_data = last_transaction.to_h
|
68
|
+
expect(transaction_data).to include(
|
69
|
+
"action" => "TestClass#perform",
|
70
|
+
"namespace" => "background_job",
|
71
|
+
"error" => nil
|
72
|
+
)
|
73
|
+
expect(transaction_data["events"].map { |e| e["name"] })
|
74
|
+
.to eql(["perform_job.delayed_job"])
|
75
|
+
expect(transaction_data["sample_data"]).to include(
|
76
|
+
"metadata" => {
|
77
|
+
"priority" => 1,
|
78
|
+
"attempts" => 1,
|
79
|
+
"queue" => "default",
|
80
|
+
"id" => "123"
|
81
|
+
},
|
82
|
+
"params" => ["argument"]
|
80
83
|
)
|
81
84
|
end
|
82
85
|
|
@@ -89,14 +92,13 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
89
92
|
end
|
90
93
|
|
91
94
|
it "adds the more complex arguments" do
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
)
|
95
|
+
perform
|
96
|
+
transaction_data = last_transaction.to_h
|
97
|
+
expect(transaction_data["sample_data"]).to include(
|
98
|
+
"params" => {
|
99
|
+
"foo" => "Foo",
|
100
|
+
"bar" => "Bar"
|
101
|
+
}
|
100
102
|
)
|
101
103
|
end
|
102
104
|
|
@@ -107,14 +109,13 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
107
109
|
end
|
108
110
|
|
109
111
|
it "filters selected arguments" do
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
)
|
112
|
+
perform
|
113
|
+
transaction_data = last_transaction.to_h
|
114
|
+
expect(transaction_data["sample_data"]).to include(
|
115
|
+
"params" => {
|
116
|
+
"foo" => "[FILTERED]",
|
117
|
+
"bar" => "Bar"
|
118
|
+
}
|
118
119
|
)
|
119
120
|
end
|
120
121
|
end
|
@@ -124,98 +125,135 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
124
125
|
let(:run_at) { Time.parse("2017-01-01 10:01:00UTC") }
|
125
126
|
|
126
127
|
it "reports queue_start with run_at time" do
|
128
|
+
# TODO: Not available in transaction.to_h yet.
|
129
|
+
# https://github.com/appsignal/appsignal-agent/issues/293
|
127
130
|
expect(Appsignal).to receive(:monitor_transaction).with(
|
128
131
|
"perform_job.delayed_job",
|
129
|
-
|
130
|
-
)
|
132
|
+
a_hash_including(:queue_start => run_at)
|
133
|
+
).and_call_original
|
134
|
+
perform
|
131
135
|
end
|
132
136
|
end
|
133
137
|
|
134
|
-
context "with
|
138
|
+
context "with class method job" do
|
135
139
|
let(:job_data) do
|
136
|
-
{
|
137
|
-
:payload_object => double(
|
138
|
-
:appsignal_name => "CustomClass#perform",
|
139
|
-
:args => args
|
140
|
-
),
|
141
|
-
:id => "123",
|
142
|
-
:name => "TestClass#perform",
|
143
|
-
:priority => 1,
|
144
|
-
:attempts => 1,
|
145
|
-
:queue => "default",
|
146
|
-
:created_at => created_at,
|
147
|
-
:run_at => run_at
|
148
|
-
}
|
149
|
-
end
|
150
|
-
let(:default_params) do
|
151
|
-
{
|
152
|
-
:class => "CustomClass",
|
153
|
-
:method => "perform",
|
154
|
-
:metadata => {
|
155
|
-
:priority => 1,
|
156
|
-
:attempts => 1,
|
157
|
-
:queue => "default",
|
158
|
-
:id => "123"
|
159
|
-
},
|
160
|
-
:queue_start => run_at
|
161
|
-
}
|
140
|
+
{ :name => "CustomClassMethod.perform", :payload_object => payload_object }
|
162
141
|
end
|
163
142
|
|
164
|
-
it "wraps it in a transaction
|
165
|
-
|
166
|
-
|
167
|
-
default_params.merge(
|
168
|
-
:params => ["argument"]
|
169
|
-
)
|
170
|
-
)
|
143
|
+
it "wraps it in a transaction using the class method job name" do
|
144
|
+
perform
|
145
|
+
expect(last_transaction.to_h["action"]).to eql("CustomClassMethod.perform")
|
171
146
|
end
|
147
|
+
end
|
172
148
|
|
173
|
-
|
174
|
-
|
175
|
-
{
|
176
|
-
:foo => "Foo",
|
177
|
-
:bar => "Bar"
|
178
|
-
}
|
179
|
-
end
|
149
|
+
context "with custom name call" do
|
150
|
+
before { perform }
|
180
151
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
152
|
+
context "with appsignal_name defined" do
|
153
|
+
context "with payload_object being an object" do
|
154
|
+
context "with value" do
|
155
|
+
let(:payload_object) { double(:appsignal_name => "CustomClass#perform") }
|
156
|
+
|
157
|
+
it "wraps it in a transaction using the custom name" do
|
158
|
+
expect(last_transaction.to_h["action"]).to eql("CustomClass#perform")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "with non-String value" do
|
163
|
+
let(:payload_object) { double(:appsignal_name => Object.new) }
|
164
|
+
|
165
|
+
it "wraps it in a transaction using the original job name" do
|
166
|
+
expect(last_transaction.to_h["action"]).to eql("TestClass#perform")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "with class method name as job" do
|
171
|
+
let(:payload_object) { double(:appsignal_name => "CustomClassMethod.perform") }
|
172
|
+
|
173
|
+
it "wraps it in a transaction using the custom name" do
|
174
|
+
perform
|
175
|
+
expect(last_transaction.to_h["action"]).to eql("CustomClassMethod.perform")
|
176
|
+
end
|
177
|
+
end
|
191
178
|
end
|
192
179
|
|
193
|
-
context "with
|
194
|
-
|
195
|
-
|
196
|
-
|
180
|
+
context "with payload_object being a Hash" do
|
181
|
+
context "with value" do
|
182
|
+
let(:payload_object) { double(:appsignal_name => "CustomClassHash#perform") }
|
183
|
+
|
184
|
+
it "wraps it in a transaction using the custom name" do
|
185
|
+
expect(last_transaction.to_h["action"]).to eql("CustomClassHash#perform")
|
186
|
+
end
|
197
187
|
end
|
198
188
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
)
|
189
|
+
context "with non-String value" do
|
190
|
+
let(:payload_object) { double(:appsignal_name => Object.new) }
|
191
|
+
|
192
|
+
it "wraps it in a transaction using the original job name" do
|
193
|
+
expect(last_transaction.to_h["action"]).to eql("TestClass#perform")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context "with class method name as job" do
|
198
|
+
let(:payload_object) { { :appsignal_name => "CustomClassMethod.perform" } }
|
199
|
+
|
200
|
+
it "wraps it in a transaction using the custom name" do
|
201
|
+
perform
|
202
|
+
expect(last_transaction.to_h["action"]).to eql("CustomClassMethod.perform")
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "with payload_object being acting like a Hash and returning a non-String value" do
|
208
|
+
class ClassActingAsHash
|
209
|
+
def self.[](_key)
|
210
|
+
Object.new
|
211
|
+
end
|
212
|
+
|
213
|
+
def self.appsignal_name
|
214
|
+
"ClassActingAsHash#perform"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
let(:payload_object) { ClassActingAsHash }
|
218
|
+
|
219
|
+
# We check for hash values before object values
|
220
|
+
# this means ClassActingAsHash returns `Object.new` instead
|
221
|
+
# of `self.appsignal_name`. Since this isn't a valid `String`
|
222
|
+
# we return the default job name as action name.
|
223
|
+
it "wraps it in a transaction using the original job name" do
|
224
|
+
expect(last_transaction.to_h["action"]).to eql("TestClass#perform")
|
209
225
|
end
|
210
226
|
end
|
211
227
|
end
|
212
228
|
end
|
213
229
|
|
230
|
+
context "without job name" do
|
231
|
+
let(:job_data) do
|
232
|
+
{ :name => "", :payload_object => payload_object }
|
233
|
+
end
|
234
|
+
|
235
|
+
it "wraps it in a transaction using the class method job name" do
|
236
|
+
perform
|
237
|
+
expect(last_transaction.to_h["action"]).to eql("unknown")
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context "with invalid job name" do
|
242
|
+
let(:job_data) do
|
243
|
+
{ :name => "Banana", :payload_object => payload_object }
|
244
|
+
end
|
245
|
+
|
246
|
+
it "wraps it in a transaction using the class method job name" do
|
247
|
+
perform
|
248
|
+
expect(last_transaction.to_h["action"]).to eql("unknown")
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
214
252
|
if active_job_present?
|
215
253
|
require "active_job"
|
216
254
|
|
217
255
|
context "when wrapped by ActiveJob" do
|
218
|
-
let(:
|
256
|
+
let(:payload_object) do
|
219
257
|
ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper.new(
|
220
258
|
"arguments" => args,
|
221
259
|
"job_class" => "TestClass",
|
@@ -233,32 +271,30 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
233
271
|
:queue => "default",
|
234
272
|
:created_at => created_at,
|
235
273
|
:run_at => run_at,
|
236
|
-
:payload_object =>
|
274
|
+
:payload_object => payload_object
|
237
275
|
)
|
238
276
|
end
|
239
|
-
let(:default_params) do
|
240
|
-
{
|
241
|
-
:class => "TestClass",
|
242
|
-
:method => "perform",
|
243
|
-
:metadata => {
|
244
|
-
:priority => 1,
|
245
|
-
:attempts => 1,
|
246
|
-
:queue => "default",
|
247
|
-
:id => "123"
|
248
|
-
},
|
249
|
-
:queue_start => run_at,
|
250
|
-
:params => args
|
251
|
-
}
|
252
|
-
end
|
253
277
|
let(:args) { ["activejob_argument"] }
|
254
278
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
279
|
+
it "wraps it in a transaction with the correct params" do
|
280
|
+
perform
|
281
|
+
transaction_data = last_transaction.to_h
|
282
|
+
expect(transaction_data).to include(
|
283
|
+
"action" => "TestClass#perform",
|
284
|
+
"namespace" => "background_job",
|
285
|
+
"error" => nil
|
286
|
+
)
|
287
|
+
expect(transaction_data["events"].map { |e| e["name"] })
|
288
|
+
.to eql(["perform_job.delayed_job"])
|
289
|
+
expect(transaction_data["sample_data"]).to include(
|
290
|
+
"metadata" => {
|
291
|
+
"priority" => 1,
|
292
|
+
"attempts" => 1,
|
293
|
+
"queue" => "default",
|
294
|
+
"id" => "123"
|
295
|
+
},
|
296
|
+
"params" => ["activejob_argument"]
|
297
|
+
)
|
262
298
|
end
|
263
299
|
|
264
300
|
context "with more complex params" do
|
@@ -270,14 +306,14 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
270
306
|
end
|
271
307
|
|
272
308
|
it "adds the more complex arguments" do
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
309
|
+
perform
|
310
|
+
transaction_data = last_transaction.to_h
|
311
|
+
expect(transaction_data).to include("action" => "TestClass#perform")
|
312
|
+
expect(transaction_data["sample_data"]).to include(
|
313
|
+
"params" => {
|
314
|
+
"foo" => "Foo",
|
315
|
+
"bar" => "Bar"
|
316
|
+
}
|
281
317
|
)
|
282
318
|
end
|
283
319
|
|
@@ -288,14 +324,14 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
288
324
|
end
|
289
325
|
|
290
326
|
it "filters selected arguments" do
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
327
|
+
perform
|
328
|
+
transaction_data = last_transaction.to_h
|
329
|
+
expect(transaction_data).to include("action" => "TestClass#perform")
|
330
|
+
expect(transaction_data["sample_data"]).to include(
|
331
|
+
"params" => {
|
332
|
+
"foo" => "[FILTERED]",
|
333
|
+
"bar" => "Bar"
|
334
|
+
}
|
299
335
|
)
|
300
336
|
end
|
301
337
|
end
|
@@ -307,8 +343,9 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
307
343
|
it "reports queue_start with run_at time" do
|
308
344
|
expect(Appsignal).to receive(:monitor_transaction).with(
|
309
345
|
"perform_job.delayed_job",
|
310
|
-
|
311
|
-
)
|
346
|
+
a_hash_including(:queue_start => run_at)
|
347
|
+
).and_call_original
|
348
|
+
perform
|
312
349
|
end
|
313
350
|
end
|
314
351
|
end
|
@@ -316,33 +353,28 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
316
353
|
end
|
317
354
|
|
318
355
|
context "with an erroring call" do
|
319
|
-
let(:error) { ExampleException }
|
320
|
-
let(:transaction) do
|
321
|
-
Appsignal::Transaction.new(
|
322
|
-
SecureRandom.uuid,
|
323
|
-
Appsignal::Transaction::BACKGROUND_JOB,
|
324
|
-
Appsignal::Transaction::GenericRequest.new({})
|
325
|
-
)
|
326
|
-
end
|
356
|
+
let(:error) { ExampleException.new("uh oh") }
|
327
357
|
before do
|
328
358
|
expect(invoked_block).to receive(:call).and_raise(error)
|
329
|
-
|
330
|
-
allow(Appsignal::Transaction).to receive(:current).and_return(transaction)
|
331
|
-
expect(Appsignal::Transaction).to receive(:create)
|
332
|
-
.with(
|
333
|
-
kind_of(String),
|
334
|
-
Appsignal::Transaction::BACKGROUND_JOB,
|
335
|
-
kind_of(Appsignal::Transaction::GenericRequest)
|
336
|
-
).and_return(transaction)
|
337
359
|
end
|
338
360
|
|
339
361
|
it "adds the error to the transaction" do
|
340
|
-
expect(transaction).to receive(:set_error).with(error)
|
341
|
-
expect(transaction).to receive(:complete)
|
342
|
-
|
343
362
|
expect do
|
344
|
-
|
363
|
+
perform
|
345
364
|
end.to raise_error(error)
|
365
|
+
|
366
|
+
transaction_data = last_transaction.to_h
|
367
|
+
expect(transaction_data).to include(
|
368
|
+
"action" => "TestClass#perform",
|
369
|
+
"namespace" => "background_job",
|
370
|
+
"error" => {
|
371
|
+
"name" => "ExampleException",
|
372
|
+
"message" => "uh oh",
|
373
|
+
# TODO: backtrace should be an Array of Strings
|
374
|
+
# https://github.com/appsignal/appsignal-agent/issues/294
|
375
|
+
"backtrace" => kind_of(String)
|
376
|
+
}
|
377
|
+
)
|
346
378
|
end
|
347
379
|
end
|
348
380
|
end
|