appsignal 3.10.0-java → 3.11.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +88 -0
- data/Gemfile +1 -0
- data/benchmark.rake +99 -42
- data/lib/appsignal/cli/demo.rb +0 -1
- data/lib/appsignal/config.rb +54 -98
- data/lib/appsignal/demo.rb +15 -20
- data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -0
- data/lib/appsignal/event_formatter.rb +3 -2
- data/lib/appsignal/helpers/instrumentation.rb +331 -19
- data/lib/appsignal/hooks/action_cable.rb +21 -16
- data/lib/appsignal/hooks/active_job.rb +14 -8
- data/lib/appsignal/hooks/delayed_job.rb +1 -1
- data/lib/appsignal/hooks/shoryuken.rb +3 -63
- data/lib/appsignal/integrations/action_cable.rb +5 -7
- data/lib/appsignal/integrations/active_support_notifications.rb +1 -0
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +36 -35
- data/lib/appsignal/integrations/data_mapper.rb +1 -0
- data/lib/appsignal/integrations/delayed_job_plugin.rb +27 -33
- data/lib/appsignal/integrations/dry_monitor.rb +1 -0
- data/lib/appsignal/integrations/excon.rb +1 -0
- data/lib/appsignal/integrations/http.rb +1 -0
- data/lib/appsignal/integrations/net_http.rb +1 -0
- data/lib/appsignal/integrations/object.rb +6 -0
- data/lib/appsignal/integrations/que.rb +13 -20
- data/lib/appsignal/integrations/railtie.rb +1 -1
- data/lib/appsignal/integrations/rake.rb +1 -5
- data/lib/appsignal/integrations/redis.rb +1 -0
- data/lib/appsignal/integrations/redis_client.rb +1 -0
- data/lib/appsignal/integrations/resque.rb +2 -5
- data/lib/appsignal/integrations/shoryuken.rb +75 -0
- data/lib/appsignal/integrations/sidekiq.rb +7 -15
- data/lib/appsignal/integrations/unicorn.rb +1 -0
- data/lib/appsignal/integrations/webmachine.rb +2 -5
- data/lib/appsignal/logger.rb +7 -3
- data/lib/appsignal/probes/helpers.rb +1 -0
- data/lib/appsignal/probes/mri.rb +1 -0
- data/lib/appsignal/probes/sidekiq.rb +1 -0
- data/lib/appsignal/probes.rb +3 -0
- data/lib/appsignal/rack/abstract_middleware.rb +18 -12
- data/lib/appsignal/rack/event_handler.rb +39 -8
- data/lib/appsignal/rack/generic_instrumentation.rb +1 -0
- data/lib/appsignal/rack/grape_middleware.rb +2 -1
- data/lib/appsignal/rack/streaming_listener.rb +1 -0
- data/lib/appsignal/rack.rb +29 -0
- data/lib/appsignal/span.rb +1 -0
- data/lib/appsignal/transaction.rb +308 -101
- data/lib/appsignal/utils/data.rb +0 -1
- data/lib/appsignal/utils/hash_sanitizer.rb +0 -1
- data/lib/appsignal/utils/integration_logger.rb +0 -13
- data/lib/appsignal/utils/integration_memory_logger.rb +0 -13
- data/lib/appsignal/utils/json.rb +0 -1
- data/lib/appsignal/utils/query_params_sanitizer.rb +0 -1
- data/lib/appsignal/utils/stdout_and_logger_message.rb +0 -1
- data/lib/appsignal/utils.rb +6 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +6 -5
- data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
- data/spec/lib/appsignal/config_spec.rb +138 -43
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +43 -74
- data/spec/lib/appsignal/hooks/activejob_spec.rb +9 -0
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +2 -443
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -171
- data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
- data/spec/lib/appsignal/integrations/que_spec.rb +3 -4
- data/spec/lib/appsignal/integrations/shoryuken_spec.rb +167 -0
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +4 -4
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +13 -1
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +48 -3
- data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -10
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
- data/spec/lib/appsignal/rack_spec.rb +63 -0
- data/spec/lib/appsignal/transaction_spec.rb +1634 -1071
- data/spec/lib/appsignal/utils/integration_logger_spec.rb +12 -16
- data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -10
- data/spec/lib/appsignal_spec.rb +323 -10
- data/spec/support/helpers/transaction_helpers.rb +44 -20
- data/spec/support/matchers/transaction.rb +15 -1
- data/spec/support/testing.rb +1 -1
- metadata +6 -2
|
@@ -126,6 +126,7 @@ if DependencyHelper.active_job_present?
|
|
|
126
126
|
expect(transaction).to include_params([])
|
|
127
127
|
expect(transaction).to include_tags(
|
|
128
128
|
"active_job_id" => kind_of(String),
|
|
129
|
+
"request_id" => kind_of(String),
|
|
129
130
|
"queue" => queue,
|
|
130
131
|
"executions" => 1
|
|
131
132
|
)
|
|
@@ -196,6 +197,7 @@ if DependencyHelper.active_job_present?
|
|
|
196
197
|
expect(transaction).to include_params([])
|
|
197
198
|
expect(transaction).to include_tags(
|
|
198
199
|
"active_job_id" => kind_of(String),
|
|
200
|
+
"request_id" => kind_of(String),
|
|
199
201
|
"queue" => queue,
|
|
200
202
|
"executions" => 1
|
|
201
203
|
)
|
|
@@ -335,6 +337,7 @@ if DependencyHelper.active_job_present?
|
|
|
335
337
|
expect(transaction).to include_params([])
|
|
336
338
|
expect(transaction).to include_tags(
|
|
337
339
|
"active_job_id" => kind_of(String),
|
|
340
|
+
"request_id" => kind_of(String),
|
|
338
341
|
"queue" => queue,
|
|
339
342
|
"executions" => 1
|
|
340
343
|
)
|
|
@@ -470,6 +473,7 @@ if DependencyHelper.active_job_present?
|
|
|
470
473
|
)
|
|
471
474
|
expect(transaction).to include_tags(
|
|
472
475
|
"active_job_id" => kind_of(String),
|
|
476
|
+
"request_id" => kind_of(String),
|
|
473
477
|
"queue" => "mailers",
|
|
474
478
|
"executions" => 1
|
|
475
479
|
)
|
|
@@ -488,6 +492,7 @@ if DependencyHelper.active_job_present?
|
|
|
488
492
|
)
|
|
489
493
|
expect(transaction).to include_tags(
|
|
490
494
|
"active_job_id" => kind_of(String),
|
|
495
|
+
"request_id" => kind_of(String),
|
|
491
496
|
"queue" => "mailers",
|
|
492
497
|
"executions" => 1
|
|
493
498
|
)
|
|
@@ -510,6 +515,7 @@ if DependencyHelper.active_job_present?
|
|
|
510
515
|
)
|
|
511
516
|
expect(transaction).to include_tags(
|
|
512
517
|
"active_job_id" => kind_of(String),
|
|
518
|
+
"request_id" => kind_of(String),
|
|
513
519
|
"queue" => "mailers",
|
|
514
520
|
"executions" => 1
|
|
515
521
|
)
|
|
@@ -549,6 +555,7 @@ if DependencyHelper.active_job_present?
|
|
|
549
555
|
)
|
|
550
556
|
expect(transaction).to include_tags(
|
|
551
557
|
"active_job_id" => kind_of(String),
|
|
558
|
+
"request_id" => kind_of(String),
|
|
552
559
|
"queue" => "mailers",
|
|
553
560
|
"executions" => 1
|
|
554
561
|
)
|
|
@@ -573,6 +580,7 @@ if DependencyHelper.active_job_present?
|
|
|
573
580
|
)
|
|
574
581
|
expect(transaction).to include_tags(
|
|
575
582
|
"active_job_id" => kind_of(String),
|
|
583
|
+
"request_id" => kind_of(String),
|
|
576
584
|
"queue" => "mailers",
|
|
577
585
|
"executions" => 1
|
|
578
586
|
)
|
|
@@ -599,6 +607,7 @@ if DependencyHelper.active_job_present?
|
|
|
599
607
|
)
|
|
600
608
|
expect(transaction).to include_tags(
|
|
601
609
|
"active_job_id" => kind_of(String),
|
|
610
|
+
"request_id" => kind_of(String),
|
|
602
611
|
"queue" => "mailers",
|
|
603
612
|
"executions" => 1
|
|
604
613
|
)
|
|
@@ -15,9 +15,7 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
after(:context) { Object.send(:remove_const, :Delayed) }
|
|
18
|
-
before
|
|
19
|
-
start_agent
|
|
20
|
-
end
|
|
18
|
+
before { start_agent }
|
|
21
19
|
|
|
22
20
|
describe "#dependencies_present?" do
|
|
23
21
|
subject { described_class.new.dependencies_present? }
|
|
@@ -26,446 +24,7 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
it "adds the plugin" do
|
|
29
|
-
expect(::Delayed::Worker.plugins).to include
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# We haven't found a way to test the hooks, we'll have to do that manually
|
|
33
|
-
|
|
34
|
-
describe ".invoke_with_instrumentation" do
|
|
35
|
-
let(:plugin) { Appsignal::Hooks::DelayedJobPlugin }
|
|
36
|
-
let(:time) { Time.parse("01-01-2001 10:01:00UTC") }
|
|
37
|
-
let(:created_at) { time - 3600 }
|
|
38
|
-
let(:run_at) { time - 3600 }
|
|
39
|
-
let(:payload_object) { double(:args => args) }
|
|
40
|
-
let(:job_data) do
|
|
41
|
-
{
|
|
42
|
-
:id => 123,
|
|
43
|
-
:name => "TestClass#perform",
|
|
44
|
-
:priority => 1,
|
|
45
|
-
:attempts => 1,
|
|
46
|
-
:queue => "default",
|
|
47
|
-
:created_at => created_at,
|
|
48
|
-
:run_at => run_at,
|
|
49
|
-
:payload_object => payload_object
|
|
50
|
-
}
|
|
51
|
-
end
|
|
52
|
-
let(:args) { ["argument"] }
|
|
53
|
-
let(:job) { double(job_data) }
|
|
54
|
-
let(:invoked_block) { proc {} }
|
|
55
|
-
|
|
56
|
-
def perform
|
|
57
|
-
Timecop.freeze(time) do
|
|
58
|
-
keep_transactions do
|
|
59
|
-
plugin.invoke_with_instrumentation(job, invoked_block)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
context "with a normal call" do
|
|
65
|
-
it "wraps it in a transaction" do
|
|
66
|
-
perform
|
|
67
|
-
transaction = last_transaction
|
|
68
|
-
expect(transaction).to have_action("TestClass#perform")
|
|
69
|
-
expect(transaction).to have_namespace("background_job")
|
|
70
|
-
expect(transaction).to_not have_error
|
|
71
|
-
expect(transaction).to include_event(:name => "perform_job.delayed_job")
|
|
72
|
-
expect(transaction).to include_sample_metadata(
|
|
73
|
-
"priority" => 1,
|
|
74
|
-
"attempts" => 1,
|
|
75
|
-
"queue" => "default",
|
|
76
|
-
"id" => "123"
|
|
77
|
-
)
|
|
78
|
-
expect(transaction).to include_params(["argument"])
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
context "with more complex params" do
|
|
82
|
-
let(:args) do
|
|
83
|
-
{
|
|
84
|
-
:foo => "Foo",
|
|
85
|
-
:bar => "Bar"
|
|
86
|
-
}
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it "adds the more complex arguments" do
|
|
90
|
-
perform
|
|
91
|
-
|
|
92
|
-
expect(last_transaction).to include_params("foo" => "Foo", "bar" => "Bar")
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
context "with parameter filtering" do
|
|
96
|
-
before do
|
|
97
|
-
Appsignal.config = project_fixture_config("production")
|
|
98
|
-
Appsignal.config[:filter_parameters] = ["foo"]
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
it "filters selected arguments" do
|
|
102
|
-
perform
|
|
103
|
-
|
|
104
|
-
expect(last_transaction).to include_params("foo" => "[FILTERED]", "bar" => "Bar")
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
context "with run_at in the future" do
|
|
110
|
-
let(:run_at) { Time.parse("2017-01-01 10:01:00UTC") }
|
|
111
|
-
|
|
112
|
-
it "reports queue_start with run_at time" do
|
|
113
|
-
perform
|
|
114
|
-
|
|
115
|
-
expect(last_transaction).to have_queue_start(run_at.to_i * 1000)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
context "with class method job" do
|
|
120
|
-
let(:job_data) do
|
|
121
|
-
{ :name => "CustomClassMethod.perform", :payload_object => payload_object }
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
it "wraps it in a transaction using the class method job name" do
|
|
125
|
-
perform
|
|
126
|
-
expect(last_transaction).to have_action("CustomClassMethod.perform")
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
context "with custom name call" do
|
|
131
|
-
before { perform }
|
|
132
|
-
|
|
133
|
-
context "with appsignal_name defined" do
|
|
134
|
-
context "with payload_object being an object" do
|
|
135
|
-
context "with value" do
|
|
136
|
-
let(:payload_object) { double(:appsignal_name => "CustomClass#perform") }
|
|
137
|
-
|
|
138
|
-
it "wraps it in a transaction using the custom name" do
|
|
139
|
-
expect(last_transaction).to have_action("CustomClass#perform")
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
context "with non-String value" do
|
|
144
|
-
let(:payload_object) { double(:appsignal_name => Object.new) }
|
|
145
|
-
|
|
146
|
-
it "wraps it in a transaction using the original job name" do
|
|
147
|
-
expect(last_transaction).to have_action("TestClass#perform")
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
context "with class method name as job" do
|
|
152
|
-
let(:payload_object) { double(:appsignal_name => "CustomClassMethod.perform") }
|
|
153
|
-
|
|
154
|
-
it "wraps it in a transaction using the custom name" do
|
|
155
|
-
perform
|
|
156
|
-
expect(last_transaction).to have_action("CustomClassMethod.perform")
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
context "with payload_object being a Hash" do
|
|
162
|
-
context "with value" do
|
|
163
|
-
let(:payload_object) { double(:appsignal_name => "CustomClassHash#perform") }
|
|
164
|
-
|
|
165
|
-
it "wraps it in a transaction using the custom name" do
|
|
166
|
-
expect(last_transaction).to have_action("CustomClassHash#perform")
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
context "with non-String value" do
|
|
171
|
-
let(:payload_object) { double(:appsignal_name => Object.new) }
|
|
172
|
-
|
|
173
|
-
it "wraps it in a transaction using the original job name" do
|
|
174
|
-
expect(last_transaction).to have_action("TestClass#perform")
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
context "with class method name as job" do
|
|
179
|
-
let(:payload_object) { { :appsignal_name => "CustomClassMethod.perform" } }
|
|
180
|
-
|
|
181
|
-
it "wraps it in a transaction using the custom name" do
|
|
182
|
-
perform
|
|
183
|
-
expect(last_transaction).to have_action("CustomClassMethod.perform")
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
context "with payload_object acting like a Hash and returning a non-String value" do
|
|
189
|
-
class ClassActingAsHash
|
|
190
|
-
def self.[](_key)
|
|
191
|
-
Object.new
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def self.appsignal_name
|
|
195
|
-
"ClassActingAsHash#perform"
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
let(:payload_object) { ClassActingAsHash }
|
|
199
|
-
|
|
200
|
-
# We check for hash values before object values
|
|
201
|
-
# this means ClassActingAsHash returns `Object.new` instead
|
|
202
|
-
# of `self.appsignal_name`. Since this isn't a valid `String`
|
|
203
|
-
# we return the default job name as action name.
|
|
204
|
-
it "wraps it in a transaction using the original job name" do
|
|
205
|
-
expect(last_transaction).to have_action("TestClass#perform")
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
context "with only job class name" do
|
|
212
|
-
let(:job_data) do
|
|
213
|
-
{ :name => "Banana", :payload_object => payload_object }
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
it "appends #perform to the class name" do
|
|
217
|
-
perform
|
|
218
|
-
expect(last_transaction).to have_action("Banana#perform")
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
if active_job_present?
|
|
223
|
-
require "active_job"
|
|
224
|
-
|
|
225
|
-
context "when wrapped by ActiveJob" do
|
|
226
|
-
let(:payload_object) do
|
|
227
|
-
ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper.new(
|
|
228
|
-
"arguments" => args,
|
|
229
|
-
"job_class" => "TestClass",
|
|
230
|
-
"job_id" => 123,
|
|
231
|
-
"locale" => :en,
|
|
232
|
-
"queue_name" => "default"
|
|
233
|
-
)
|
|
234
|
-
end
|
|
235
|
-
let(:job) do
|
|
236
|
-
double(
|
|
237
|
-
:id => 123,
|
|
238
|
-
:name => "ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper",
|
|
239
|
-
:priority => 1,
|
|
240
|
-
:attempts => 1,
|
|
241
|
-
:queue => "default",
|
|
242
|
-
:created_at => created_at,
|
|
243
|
-
:run_at => run_at,
|
|
244
|
-
:payload_object => payload_object
|
|
245
|
-
)
|
|
246
|
-
end
|
|
247
|
-
let(:args) { ["activejob_argument"] }
|
|
248
|
-
|
|
249
|
-
it "wraps it in a transaction with the correct params" do
|
|
250
|
-
perform
|
|
251
|
-
|
|
252
|
-
transaction = last_transaction
|
|
253
|
-
expect(transaction).to have_namespace("background_job")
|
|
254
|
-
expect(transaction).to have_action("TestClass#perform")
|
|
255
|
-
expect(transaction).to_not have_error
|
|
256
|
-
expect(transaction).to include_event("name" => "perform_job.delayed_job")
|
|
257
|
-
expect(transaction).to include_sample_metadata(
|
|
258
|
-
"priority" => 1,
|
|
259
|
-
"attempts" => 1,
|
|
260
|
-
"queue" => "default",
|
|
261
|
-
"id" => "123"
|
|
262
|
-
)
|
|
263
|
-
expect(transaction).to include_params(["activejob_argument"])
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
context "with more complex params" do
|
|
267
|
-
let(:args) do
|
|
268
|
-
{
|
|
269
|
-
:foo => "Foo",
|
|
270
|
-
:bar => "Bar"
|
|
271
|
-
}
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
it "adds the more complex arguments" do
|
|
275
|
-
perform
|
|
276
|
-
transaction = last_transaction
|
|
277
|
-
expect(transaction).to have_action("TestClass#perform")
|
|
278
|
-
expect(transaction).to include_params(
|
|
279
|
-
"foo" => "Foo",
|
|
280
|
-
"bar" => "Bar"
|
|
281
|
-
)
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
context "with parameter filtering" do
|
|
285
|
-
before do
|
|
286
|
-
Appsignal.config = project_fixture_config("production")
|
|
287
|
-
Appsignal.config[:filter_parameters] = ["foo"]
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
it "filters selected arguments" do
|
|
291
|
-
perform
|
|
292
|
-
transaction = last_transaction
|
|
293
|
-
expect(transaction).to have_action("TestClass#perform")
|
|
294
|
-
expect(transaction).to include_params(
|
|
295
|
-
"foo" => "[FILTERED]",
|
|
296
|
-
"bar" => "Bar"
|
|
297
|
-
)
|
|
298
|
-
end
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
context "with run_at in the future" do
|
|
303
|
-
let(:run_at) { Time.parse("2017-01-01 10:01:00UTC") }
|
|
304
|
-
|
|
305
|
-
it "reports queue_start with run_at time" do
|
|
306
|
-
perform
|
|
307
|
-
|
|
308
|
-
expect(last_transaction).to have_queue_start(run_at.to_i * 1000)
|
|
309
|
-
end
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
context "with an erroring call" do
|
|
316
|
-
let(:error) { ExampleException.new("uh oh") }
|
|
317
|
-
before do
|
|
318
|
-
expect(invoked_block).to receive(:call).and_raise(error)
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
it "adds the error to the transaction" do
|
|
322
|
-
expect do
|
|
323
|
-
perform
|
|
324
|
-
end.to raise_error(error)
|
|
325
|
-
|
|
326
|
-
transaction = last_transaction
|
|
327
|
-
expect(transaction).to have_namespace("background_job")
|
|
328
|
-
expect(transaction).to have_action("TestClass#perform")
|
|
329
|
-
expect(transaction).to have_error("ExampleException", "uh oh")
|
|
330
|
-
end
|
|
331
|
-
end
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
describe ".extract_value" do
|
|
335
|
-
let(:plugin) { Appsignal::Hooks::DelayedJobPlugin }
|
|
336
|
-
|
|
337
|
-
context "for a hash" do
|
|
338
|
-
let(:hash) { { :key => "value", :bool_false => false } }
|
|
339
|
-
|
|
340
|
-
context "when the key exists" do
|
|
341
|
-
subject { plugin.extract_value(hash, :key) }
|
|
342
|
-
|
|
343
|
-
it { is_expected.to eq "value" }
|
|
344
|
-
|
|
345
|
-
context "when the value is false" do
|
|
346
|
-
subject { plugin.extract_value(hash, :bool_false) }
|
|
347
|
-
|
|
348
|
-
it { is_expected.to be false }
|
|
349
|
-
end
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
context "when the key does not exist" do
|
|
353
|
-
subject { plugin.extract_value(hash, :nonexistent_key) }
|
|
354
|
-
|
|
355
|
-
it { is_expected.to be_nil }
|
|
356
|
-
|
|
357
|
-
context "with a default value" do
|
|
358
|
-
subject { plugin.extract_value(hash, :nonexistent_key, 1) }
|
|
359
|
-
|
|
360
|
-
it { is_expected.to eq 1 }
|
|
361
|
-
end
|
|
362
|
-
end
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
context "for a struct" do
|
|
366
|
-
before :context do
|
|
367
|
-
TestStruct = Struct.new(:key)
|
|
368
|
-
end
|
|
369
|
-
let(:struct) { TestStruct.new("value") }
|
|
370
|
-
|
|
371
|
-
context "when the key exists" do
|
|
372
|
-
subject { plugin.extract_value(struct, :key) }
|
|
373
|
-
|
|
374
|
-
it { is_expected.to eq "value" }
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
context "when the key does not exist" do
|
|
378
|
-
subject { plugin.extract_value(struct, :nonexistent_key) }
|
|
379
|
-
|
|
380
|
-
it { is_expected.to be_nil }
|
|
381
|
-
|
|
382
|
-
context "with a default value" do
|
|
383
|
-
subject { plugin.extract_value(struct, :nonexistent_key, 1) }
|
|
384
|
-
|
|
385
|
-
it { is_expected.to eq 1 }
|
|
386
|
-
end
|
|
387
|
-
end
|
|
388
|
-
end
|
|
389
|
-
|
|
390
|
-
context "for a struct with a method" do
|
|
391
|
-
before :context do
|
|
392
|
-
class TestStructClass < Struct.new(:id) # rubocop:disable Style/StructInheritance
|
|
393
|
-
def appsignal_name
|
|
394
|
-
"TestStruct#perform"
|
|
395
|
-
end
|
|
396
|
-
|
|
397
|
-
def bool_false
|
|
398
|
-
false
|
|
399
|
-
end
|
|
400
|
-
end
|
|
401
|
-
end
|
|
402
|
-
let(:struct) { TestStructClass.new("id") }
|
|
403
|
-
|
|
404
|
-
context "when the Struct responds to a method" do
|
|
405
|
-
subject { plugin.extract_value(struct, :appsignal_name) }
|
|
406
|
-
|
|
407
|
-
it "returns the method value" do
|
|
408
|
-
is_expected.to eq "TestStruct#perform"
|
|
409
|
-
end
|
|
410
|
-
|
|
411
|
-
context "when the value is false" do
|
|
412
|
-
subject { plugin.extract_value(struct, :bool_false) }
|
|
413
|
-
|
|
414
|
-
it "returns the method value" do
|
|
415
|
-
is_expected.to be false
|
|
416
|
-
end
|
|
417
|
-
end
|
|
418
|
-
end
|
|
419
|
-
|
|
420
|
-
context "when the key does not exist" do
|
|
421
|
-
subject { plugin.extract_value(struct, :nonexistent_key) }
|
|
422
|
-
|
|
423
|
-
context "without a method with the same name" do
|
|
424
|
-
it "returns nil" do
|
|
425
|
-
is_expected.to be_nil
|
|
426
|
-
end
|
|
427
|
-
end
|
|
428
|
-
|
|
429
|
-
context "with a default value" do
|
|
430
|
-
let(:default_value) { :my_default_value }
|
|
431
|
-
subject { plugin.extract_value(struct, :nonexistent_key, default_value) }
|
|
432
|
-
|
|
433
|
-
it "returns the default value" do
|
|
434
|
-
is_expected.to eq default_value
|
|
435
|
-
end
|
|
436
|
-
end
|
|
437
|
-
end
|
|
438
|
-
end
|
|
439
|
-
|
|
440
|
-
context "for an object" do
|
|
441
|
-
let(:object) { double(:existing_method => "value") }
|
|
442
|
-
|
|
443
|
-
context "when the method exists" do
|
|
444
|
-
subject { plugin.extract_value(object, :existing_method) }
|
|
445
|
-
|
|
446
|
-
it { is_expected.to eq "value" }
|
|
447
|
-
end
|
|
448
|
-
|
|
449
|
-
context "when the method does not exist" do
|
|
450
|
-
subject { plugin.extract_value(object, :nonexistent_method) }
|
|
451
|
-
|
|
452
|
-
it { is_expected.to be_nil }
|
|
453
|
-
|
|
454
|
-
context "and there is a default value" do
|
|
455
|
-
subject { plugin.extract_value(object, :nonexistent_method, 1) }
|
|
456
|
-
|
|
457
|
-
it { is_expected.to eq 1 }
|
|
458
|
-
end
|
|
459
|
-
end
|
|
460
|
-
end
|
|
461
|
-
|
|
462
|
-
context "when we need to call to_s on the value" do
|
|
463
|
-
let(:object) { double(:existing_method => 1) }
|
|
464
|
-
|
|
465
|
-
subject { plugin.extract_value(object, :existing_method, nil, true) }
|
|
466
|
-
|
|
467
|
-
it { is_expected.to eq "1" }
|
|
468
|
-
end
|
|
27
|
+
expect(::Delayed::Worker.plugins).to include(Appsignal::Integrations::DelayedJobPlugin)
|
|
469
28
|
end
|
|
470
29
|
end
|
|
471
30
|
|
|
@@ -1,174 +1,3 @@
|
|
|
1
|
-
describe Appsignal::Hooks::ShoryukenMiddleware do
|
|
2
|
-
class DemoShoryukenWorker
|
|
3
|
-
end
|
|
4
|
-
|
|
5
|
-
let(:time) { "2010-01-01 10:01:00UTC" }
|
|
6
|
-
let(:worker_instance) { DemoShoryukenWorker.new }
|
|
7
|
-
let(:queue) { "some-funky-queue-name" }
|
|
8
|
-
let(:sqs_msg) { double(:message_id => "msg1", :attributes => {}) }
|
|
9
|
-
let(:body) { {} }
|
|
10
|
-
before(:context) { start_agent }
|
|
11
|
-
around { |example| keep_transactions { example.run } }
|
|
12
|
-
|
|
13
|
-
def perform_shoryuken_job(&block)
|
|
14
|
-
block ||= lambda {}
|
|
15
|
-
Timecop.freeze(Time.parse(time)) do
|
|
16
|
-
Appsignal::Hooks::ShoryukenMiddleware.new.call(
|
|
17
|
-
worker_instance,
|
|
18
|
-
queue,
|
|
19
|
-
sqs_msg,
|
|
20
|
-
body,
|
|
21
|
-
&block
|
|
22
|
-
)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
context "with a performance call" do
|
|
27
|
-
let(:sent_timestamp) { Time.parse("1976-11-18 0:00:00UTC").to_i * 1000 }
|
|
28
|
-
let(:sqs_msg) do
|
|
29
|
-
double(:message_id => "msg1", :attributes => { "SentTimestamp" => sent_timestamp })
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
context "with complex argument" do
|
|
33
|
-
let(:body) { { :foo => "Foo", :bar => "Bar" } }
|
|
34
|
-
|
|
35
|
-
it "wraps the job in a transaction with the correct params" do
|
|
36
|
-
allow_any_instance_of(Appsignal::Transaction).to receive(:set_queue_start).and_call_original
|
|
37
|
-
expect { perform_shoryuken_job }.to change { created_transactions.length }.by(1)
|
|
38
|
-
|
|
39
|
-
transaction = last_transaction
|
|
40
|
-
expect(transaction).to have_id
|
|
41
|
-
expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
|
|
42
|
-
expect(transaction).to have_action("DemoShoryukenWorker#perform")
|
|
43
|
-
expect(transaction).to_not have_error
|
|
44
|
-
expect(transaction).to include_event(
|
|
45
|
-
"body" => "",
|
|
46
|
-
"body_format" => Appsignal::EventFormatter::DEFAULT,
|
|
47
|
-
"count" => 1,
|
|
48
|
-
"name" => "perform_job.shoryuken",
|
|
49
|
-
"title" => ""
|
|
50
|
-
)
|
|
51
|
-
expect(transaction).to include_params("foo" => "Foo", "bar" => "Bar")
|
|
52
|
-
expect(transaction).to include_sample_metadata(
|
|
53
|
-
"message_id" => "msg1",
|
|
54
|
-
"queue" => queue,
|
|
55
|
-
"SentTimestamp" => sent_timestamp
|
|
56
|
-
)
|
|
57
|
-
expect(transaction).to have_queue_start(sent_timestamp)
|
|
58
|
-
expect(transaction).to be_completed
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
context "with parameter filtering" do
|
|
62
|
-
before do
|
|
63
|
-
Appsignal.config = project_fixture_config("production")
|
|
64
|
-
Appsignal.config[:filter_parameters] = ["foo"]
|
|
65
|
-
end
|
|
66
|
-
after do
|
|
67
|
-
Appsignal.config[:filter_parameters] = []
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
it "filters selected arguments" do
|
|
71
|
-
perform_shoryuken_job
|
|
72
|
-
|
|
73
|
-
expect(last_transaction).to include_params("foo" => "[FILTERED]", "bar" => "Bar")
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
context "with a string as an argument" do
|
|
79
|
-
let(:body) { "foo bar" }
|
|
80
|
-
|
|
81
|
-
it "handles string arguments" do
|
|
82
|
-
perform_shoryuken_job
|
|
83
|
-
|
|
84
|
-
expect(last_transaction).to include_params("params" => body)
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
context "with primitive type as argument" do
|
|
89
|
-
let(:body) { 1 }
|
|
90
|
-
|
|
91
|
-
it "handles primitive types as arguments" do
|
|
92
|
-
perform_shoryuken_job
|
|
93
|
-
|
|
94
|
-
expect(last_transaction).to include_params("params" => body)
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
context "with exception" do
|
|
100
|
-
it "sets the exception on the transaction" do
|
|
101
|
-
expect do
|
|
102
|
-
expect do
|
|
103
|
-
perform_shoryuken_job { raise ExampleException, "error message" }
|
|
104
|
-
end.to raise_error(ExampleException)
|
|
105
|
-
end.to change { created_transactions.length }.by(1)
|
|
106
|
-
|
|
107
|
-
transaction = last_transaction
|
|
108
|
-
expect(transaction).to have_id
|
|
109
|
-
expect(transaction).to have_action("DemoShoryukenWorker#perform")
|
|
110
|
-
expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
|
|
111
|
-
expect(transaction).to have_error("ExampleException", "error message")
|
|
112
|
-
expect(transaction).to be_completed
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
context "with batched jobs" do
|
|
117
|
-
let(:sqs_msg) do
|
|
118
|
-
[
|
|
119
|
-
double(
|
|
120
|
-
:message_id => "msg2",
|
|
121
|
-
:attributes => {
|
|
122
|
-
"SentTimestamp" => (Time.parse("1976-11-18 01:00:00UTC").to_i * 1000).to_s
|
|
123
|
-
}
|
|
124
|
-
),
|
|
125
|
-
double(
|
|
126
|
-
:message_id => "msg1",
|
|
127
|
-
:attributes => { "SentTimestamp" => sent_timestamp.to_s }
|
|
128
|
-
)
|
|
129
|
-
]
|
|
130
|
-
end
|
|
131
|
-
let(:body) do
|
|
132
|
-
[
|
|
133
|
-
"foo bar",
|
|
134
|
-
{ :id => "123", :foo => "Foo", :bar => "Bar" }
|
|
135
|
-
]
|
|
136
|
-
end
|
|
137
|
-
let(:sent_timestamp) { Time.parse("1976-11-18 01:00:00UTC").to_i * 1000 }
|
|
138
|
-
|
|
139
|
-
it "creates a transaction for the batch" do
|
|
140
|
-
allow_any_instance_of(Appsignal::Transaction).to receive(:set_queue_start).and_call_original
|
|
141
|
-
expect do
|
|
142
|
-
perform_shoryuken_job {} # rubocop:disable Lint/EmptyBlock
|
|
143
|
-
end.to change { created_transactions.length }.by(1)
|
|
144
|
-
|
|
145
|
-
transaction = last_transaction
|
|
146
|
-
expect(transaction).to have_id
|
|
147
|
-
expect(transaction).to have_action("DemoShoryukenWorker#perform")
|
|
148
|
-
expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
|
|
149
|
-
expect(transaction).to_not have_error
|
|
150
|
-
expect(transaction).to include_event(
|
|
151
|
-
"body" => "",
|
|
152
|
-
"body_format" => Appsignal::EventFormatter::DEFAULT,
|
|
153
|
-
"count" => 1,
|
|
154
|
-
"name" => "perform_job.shoryuken",
|
|
155
|
-
"title" => ""
|
|
156
|
-
)
|
|
157
|
-
expect(transaction).to include_params(
|
|
158
|
-
"msg2" => "foo bar",
|
|
159
|
-
"msg1" => { "id" => "123", "foo" => "Foo", "bar" => "Bar" }
|
|
160
|
-
)
|
|
161
|
-
expect(transaction).to include_sample_metadata(
|
|
162
|
-
"batch" => true,
|
|
163
|
-
"queue" => "some-funky-queue-name",
|
|
164
|
-
"SentTimestamp" => sent_timestamp.to_s # Earliest/oldest timestamp from messages
|
|
165
|
-
)
|
|
166
|
-
# Queue time based on earliest/oldest timestamp from messages
|
|
167
|
-
expect(transaction).to have_queue_start(sent_timestamp)
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
1
|
describe Appsignal::Hooks::ShoryukenHook do
|
|
173
2
|
context "with shoryuken" do
|
|
174
3
|
before(:context) do
|