appsignal 2.2.1 → 2.3.0.beta.1
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/CHANGELOG.md +15 -0
- data/appsignal.gemspec +1 -2
- data/ext/agent.yml +11 -11
- data/ext/appsignal_extension.c +17 -1
- data/lib/appsignal/config.rb +7 -4
- data/lib/appsignal/hooks.rb +1 -6
- data/lib/appsignal/hooks/action_cable.rb +113 -0
- data/lib/appsignal/hooks/active_support_notifications.rb +12 -4
- data/lib/appsignal/hooks/shoryuken.rb +11 -11
- data/lib/appsignal/hooks/sidekiq.rb +5 -3
- data/lib/appsignal/integrations/delayed_job_plugin.rb +5 -1
- data/lib/appsignal/integrations/resque_active_job.rb +4 -1
- data/lib/appsignal/transaction.rb +40 -13
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/config_spec.rb +8 -1
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +370 -0
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +39 -7
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +179 -34
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +125 -30
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +140 -21
- data/spec/lib/appsignal/hooks_spec.rb +0 -21
- data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +62 -17
- data/spec/lib/appsignal/integrations/resque_spec.rb +24 -12
- data/spec/lib/appsignal/transaction_spec.rb +230 -91
- data/spec/spec_helper.rb +8 -2
- data/spec/support/helpers/dependency_helper.rb +4 -0
- data/spec/support/helpers/env_helpers.rb +1 -1
- data/spec/support/helpers/log_helpers.rb +17 -0
- data/spec/support/matchers/contains_log.rb +7 -0
- data/spec/support/shared_examples/instrument.rb +2 -2
- metadata +13 -20
@@ -25,6 +25,10 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
25
25
|
it { is_expected.to be_truthy }
|
26
26
|
end
|
27
27
|
|
28
|
+
it "adds the plugin" do
|
29
|
+
expect(::Delayed::Worker.plugins).to include Appsignal::Hooks::DelayedJobPlugin
|
30
|
+
end
|
31
|
+
|
28
32
|
# We haven't found a way to test the hooks, we'll have to do that manually
|
29
33
|
|
30
34
|
describe ".invoke_with_instrumentation" do
|
@@ -38,17 +42,16 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
38
42
|
:attempts => 1,
|
39
43
|
:queue => "default",
|
40
44
|
:created_at => time - 60_000,
|
41
|
-
:payload_object => double(:args =>
|
45
|
+
:payload_object => double(:args => args)
|
42
46
|
}
|
43
47
|
end
|
48
|
+
let(:args) { ["argument"] }
|
44
49
|
let(:job) { double(job_data) }
|
45
50
|
let(:invoked_block) { proc {} }
|
46
|
-
let(:error) { StandardError.new }
|
47
51
|
|
48
52
|
context "with a normal call" do
|
49
|
-
|
50
|
-
|
51
|
-
"perform_job.delayed_job",
|
53
|
+
let(:default_params) do
|
54
|
+
{
|
52
55
|
:class => "TestClass",
|
53
56
|
:method => "perform",
|
54
57
|
:metadata => {
|
@@ -57,21 +60,68 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
57
60
|
:queue => "default",
|
58
61
|
:id => "123"
|
59
62
|
},
|
60
|
-
:params => ["argument"],
|
61
63
|
:queue_start => time - 60_000
|
62
|
-
|
63
|
-
|
64
|
+
}
|
65
|
+
end
|
66
|
+
after do
|
64
67
|
Timecop.freeze(time) do
|
65
68
|
plugin.invoke_with_instrumentation(job, invoked_block)
|
66
69
|
end
|
67
70
|
end
|
68
71
|
|
72
|
+
it "wraps it in a transaction with the correct params" do
|
73
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
74
|
+
"perform_job.delayed_job",
|
75
|
+
default_params.merge(:params => ["argument"])
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
context "with more complex params" do
|
80
|
+
let(:args) do
|
81
|
+
{
|
82
|
+
:foo => "Foo",
|
83
|
+
:bar => "Bar"
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
it "adds the more complex arguments" do
|
88
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
89
|
+
"perform_job.delayed_job",
|
90
|
+
default_params.merge(
|
91
|
+
:params => {
|
92
|
+
:foo => "Foo",
|
93
|
+
:bar => "Bar"
|
94
|
+
}
|
95
|
+
)
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
context "with parameter filtering" do
|
100
|
+
before do
|
101
|
+
Appsignal.config = project_fixture_config("production")
|
102
|
+
Appsignal.config[:filter_parameters] = ["foo"]
|
103
|
+
end
|
104
|
+
|
105
|
+
it "filters selected arguments" do
|
106
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
107
|
+
"perform_job.delayed_job",
|
108
|
+
default_params.merge(
|
109
|
+
:params => {
|
110
|
+
:foo => "[FILTERED]",
|
111
|
+
:bar => "Bar"
|
112
|
+
}
|
113
|
+
)
|
114
|
+
)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
69
119
|
context "with custom name call" do
|
70
120
|
let(:job_data) do
|
71
121
|
{
|
72
122
|
:payload_object => double(
|
73
123
|
:appsignal_name => "CustomClass#perform",
|
74
|
-
:args =>
|
124
|
+
:args => args
|
75
125
|
),
|
76
126
|
:id => "123",
|
77
127
|
:name => "TestClass#perform",
|
@@ -81,9 +131,8 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
81
131
|
:created_at => time - 60_000
|
82
132
|
}
|
83
133
|
end
|
84
|
-
|
85
|
-
|
86
|
-
"perform_job.delayed_job",
|
134
|
+
let(:default_params) do
|
135
|
+
{
|
87
136
|
:class => "CustomClass",
|
88
137
|
:method => "perform",
|
89
138
|
:metadata => {
|
@@ -92,12 +141,56 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
92
141
|
:queue => "default",
|
93
142
|
:id => "123"
|
94
143
|
},
|
95
|
-
:params => ["argument"],
|
96
144
|
:queue_start => time - 60_000
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
it "wraps it in a transaction with the correct params" do
|
149
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
150
|
+
"perform_job.delayed_job",
|
151
|
+
default_params.merge(
|
152
|
+
:params => ["argument"]
|
153
|
+
)
|
97
154
|
)
|
155
|
+
end
|
98
156
|
|
99
|
-
|
100
|
-
|
157
|
+
context "with more complex params" do
|
158
|
+
let(:args) do
|
159
|
+
{
|
160
|
+
:foo => "Foo",
|
161
|
+
:bar => "Bar"
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
165
|
+
it "adds the more complex arguments" do
|
166
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
167
|
+
"perform_job.delayed_job",
|
168
|
+
default_params.merge(
|
169
|
+
:params => {
|
170
|
+
:foo => "Foo",
|
171
|
+
:bar => "Bar"
|
172
|
+
}
|
173
|
+
)
|
174
|
+
)
|
175
|
+
end
|
176
|
+
|
177
|
+
context "with parameter filtering" do
|
178
|
+
before do
|
179
|
+
Appsignal.config = project_fixture_config("production")
|
180
|
+
Appsignal.config[:filter_parameters] = ["foo"]
|
181
|
+
end
|
182
|
+
|
183
|
+
it "filters selected arguments" do
|
184
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
185
|
+
"perform_job.delayed_job",
|
186
|
+
default_params.merge(
|
187
|
+
:params => {
|
188
|
+
:foo => "[FILTERED]",
|
189
|
+
:bar => "Bar"
|
190
|
+
}
|
191
|
+
)
|
192
|
+
)
|
193
|
+
end
|
101
194
|
end
|
102
195
|
end
|
103
196
|
end
|
@@ -106,14 +199,9 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
106
199
|
require "active_job"
|
107
200
|
|
108
201
|
context "when wrapped by ActiveJob" do
|
109
|
-
before do
|
110
|
-
job_data[:args] = ["argument"]
|
111
|
-
end
|
112
202
|
let(:job) { ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper.new(job_data) }
|
113
|
-
|
114
|
-
|
115
|
-
expect(Appsignal).to receive(:monitor_transaction).with(
|
116
|
-
"perform_job.delayed_job",
|
203
|
+
let(:default_params) do
|
204
|
+
{
|
117
205
|
:class => "TestClass",
|
118
206
|
:method => "perform",
|
119
207
|
:metadata => {
|
@@ -122,12 +210,55 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
122
210
|
:queue => "default",
|
123
211
|
:id => "123"
|
124
212
|
},
|
125
|
-
:params => ["argument"],
|
126
213
|
:queue_start => time - 60_000
|
214
|
+
}
|
215
|
+
end
|
216
|
+
before { job_data[:args] = args }
|
217
|
+
|
218
|
+
it "wraps it in a transaction with the correct params" do
|
219
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
220
|
+
"perform_job.delayed_job",
|
221
|
+
default_params.merge(:params => ["argument"])
|
127
222
|
)
|
223
|
+
end
|
224
|
+
|
225
|
+
context "with more complex params" do
|
226
|
+
let(:args) do
|
227
|
+
{
|
228
|
+
:foo => "Foo",
|
229
|
+
:bar => "Bar"
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
it "adds the more complex arguments" do
|
234
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
235
|
+
"perform_job.delayed_job",
|
236
|
+
default_params.merge(
|
237
|
+
:params => {
|
238
|
+
:foo => "Foo",
|
239
|
+
:bar => "Bar"
|
240
|
+
}
|
241
|
+
)
|
242
|
+
)
|
243
|
+
end
|
244
|
+
|
245
|
+
context "with parameter filtering" do
|
246
|
+
before do
|
247
|
+
Appsignal.config = project_fixture_config("production")
|
248
|
+
Appsignal.config[:filter_parameters] = ["foo"]
|
249
|
+
end
|
128
250
|
|
129
|
-
|
130
|
-
|
251
|
+
it "filters selected arguments" do
|
252
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
253
|
+
"perform_job.delayed_job",
|
254
|
+
default_params.merge(
|
255
|
+
:params => {
|
256
|
+
:foo => "[FILTERED]",
|
257
|
+
:bar => "Bar"
|
258
|
+
}
|
259
|
+
)
|
260
|
+
)
|
261
|
+
end
|
131
262
|
end
|
132
263
|
end
|
133
264
|
end
|
@@ -135,22 +266,36 @@ describe Appsignal::Hooks::DelayedJobHook do
|
|
135
266
|
end
|
136
267
|
|
137
268
|
context "with an erroring call" do
|
138
|
-
|
139
|
-
|
140
|
-
|
269
|
+
let(:error) { VerySpecificError }
|
270
|
+
let(:transaction) do
|
271
|
+
Appsignal::Transaction.new(
|
272
|
+
SecureRandom.uuid,
|
273
|
+
Appsignal::Transaction::BACKGROUND_JOB,
|
274
|
+
Appsignal::Transaction::GenericRequest.new({})
|
275
|
+
)
|
276
|
+
end
|
277
|
+
before do
|
278
|
+
expect(invoked_block).to receive(:call).and_raise(error)
|
141
279
|
|
142
|
-
allow(
|
280
|
+
allow(Appsignal::Transaction).to receive(:current).and_return(transaction)
|
281
|
+
expect(Appsignal::Transaction).to receive(:create)
|
282
|
+
.with(
|
283
|
+
kind_of(String),
|
284
|
+
Appsignal::Transaction::BACKGROUND_JOB,
|
285
|
+
kind_of(Appsignal::Transaction::GenericRequest)
|
286
|
+
).and_return(transaction)
|
287
|
+
end
|
288
|
+
|
289
|
+
it "adds the error to the transaction" do
|
290
|
+
expect(transaction).to receive(:set_error).with(error)
|
291
|
+
expect(transaction).to receive(:complete)
|
143
292
|
|
144
293
|
expect do
|
145
294
|
plugin.invoke_with_instrumentation(job, invoked_block)
|
146
|
-
end.to raise_error(
|
295
|
+
end.to raise_error(error)
|
147
296
|
end
|
148
297
|
end
|
149
298
|
end
|
150
|
-
|
151
|
-
it "should add the plugin" do
|
152
|
-
expect(::Delayed::Worker.plugins).to include Appsignal::Hooks::DelayedJobPlugin
|
153
|
-
end
|
154
299
|
end
|
155
300
|
|
156
301
|
context "without delayed job" do
|
@@ -1,7 +1,10 @@
|
|
1
1
|
describe Appsignal::Hooks::ShoryukenMiddleware do
|
2
2
|
let(:current_transaction) { background_job_transaction }
|
3
3
|
|
4
|
-
|
4
|
+
class DemoShoryukenWorker
|
5
|
+
end
|
6
|
+
|
7
|
+
let(:worker_instance) { DemoShoryukenWorker.new }
|
5
8
|
let(:queue) { double }
|
6
9
|
let(:sqs_msg) { double(:attributes => {}) }
|
7
10
|
let(:body) { {} }
|
@@ -16,52 +19,144 @@ describe Appsignal::Hooks::ShoryukenMiddleware do
|
|
16
19
|
let(:sqs_msg) do
|
17
20
|
double(:attributes => { "SentTimestamp" => Time.parse("1976-11-18 0:00:00UTC").to_i * 1000 })
|
18
21
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
|
23
|
+
context "with complex argument" do
|
24
|
+
let(:body) do
|
25
|
+
{
|
26
|
+
:foo => "Foo",
|
27
|
+
:bar => "Bar"
|
28
|
+
}
|
29
|
+
end
|
30
|
+
after do
|
31
|
+
Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
|
32
|
+
Appsignal::Hooks::ShoryukenMiddleware.new.call(worker_instance, queue, sqs_msg, body) do
|
33
|
+
# nothing
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "wraps the job in a transaction with the correct params" do
|
39
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
40
|
+
"perform_job.shoryuken",
|
41
|
+
:class => "DemoShoryukenWorker",
|
42
|
+
:method => "perform",
|
43
|
+
:metadata => {
|
44
|
+
:queue => "some-funky-queue-name",
|
45
|
+
"SentTimestamp" => 217_123_200_000
|
46
|
+
},
|
47
|
+
:params => {
|
48
|
+
:foo => "Foo",
|
49
|
+
:bar => "Bar"
|
50
|
+
},
|
51
|
+
:queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with parameter filtering" do
|
56
|
+
before do
|
57
|
+
Appsignal.config = project_fixture_config("production")
|
58
|
+
Appsignal.config[:filter_parameters] = ["foo"]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "filters selected arguments" do
|
62
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
63
|
+
"perform_job.shoryuken",
|
64
|
+
:class => "DemoShoryukenWorker",
|
65
|
+
:method => "perform",
|
66
|
+
:metadata => {
|
67
|
+
:queue => "some-funky-queue-name",
|
68
|
+
"SentTimestamp" => 217_123_200_000
|
69
|
+
},
|
70
|
+
:params => {
|
71
|
+
:foo => "[FILTERED]",
|
72
|
+
:bar => "Bar"
|
73
|
+
},
|
74
|
+
:queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
|
75
|
+
)
|
76
|
+
end
|
77
|
+
end
|
24
78
|
end
|
25
79
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
:
|
31
|
-
|
32
|
-
:
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
80
|
+
context "with a string as an argument" do
|
81
|
+
let(:body) { "foo bar" }
|
82
|
+
|
83
|
+
it "handles string arguments" do
|
84
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
85
|
+
"perform_job.shoryuken",
|
86
|
+
:class => "DemoShoryukenWorker",
|
87
|
+
:method => "perform",
|
88
|
+
:metadata => {
|
89
|
+
:queue => "some-funky-queue-name",
|
90
|
+
"SentTimestamp" => 217_123_200_000
|
91
|
+
},
|
92
|
+
:params => { :params => body },
|
93
|
+
:queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
|
94
|
+
)
|
95
|
+
|
96
|
+
Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
|
97
|
+
Appsignal::Hooks::ShoryukenMiddleware.new.call(worker_instance, queue, sqs_msg, body) do
|
98
|
+
# nothing
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
38
102
|
end
|
39
103
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
104
|
+
context "with primitive type as argument" do
|
105
|
+
let(:body) { 1 }
|
106
|
+
|
107
|
+
it "handles primitive types as arguments" do
|
108
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
109
|
+
"perform_job.shoryuken",
|
110
|
+
:class => "DemoShoryukenWorker",
|
111
|
+
:method => "perform",
|
112
|
+
:metadata => {
|
113
|
+
:queue => "some-funky-queue-name",
|
114
|
+
"SentTimestamp" => 217_123_200_000
|
115
|
+
},
|
116
|
+
:params => { :params => body },
|
117
|
+
:queue_start => Time.parse("1976-11-18 0:00:00UTC").utc
|
118
|
+
)
|
119
|
+
|
120
|
+
Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
|
121
|
+
Appsignal::Hooks::ShoryukenMiddleware.new.call(worker_instance, queue, sqs_msg, body) do
|
122
|
+
# nothing
|
123
|
+
end
|
44
124
|
end
|
45
125
|
end
|
46
126
|
end
|
47
127
|
end
|
48
128
|
|
49
|
-
context "with
|
50
|
-
let(:
|
129
|
+
context "with exception" do
|
130
|
+
let(:transaction) do
|
131
|
+
Appsignal::Transaction.new(
|
132
|
+
SecureRandom.uuid,
|
133
|
+
Appsignal::Transaction::BACKGROUND_JOB,
|
134
|
+
Appsignal::Transaction::GenericRequest.new({})
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
before do
|
139
|
+
allow(Appsignal::Transaction).to receive(:current).and_return(transaction)
|
140
|
+
expect(Appsignal::Transaction).to receive(:create)
|
141
|
+
.with(
|
142
|
+
kind_of(String),
|
143
|
+
Appsignal::Transaction::BACKGROUND_JOB,
|
144
|
+
kind_of(Appsignal::Transaction::GenericRequest)
|
145
|
+
).and_return(transaction)
|
146
|
+
end
|
51
147
|
|
52
|
-
it "
|
53
|
-
|
148
|
+
it "sets the exception on the transaction" do
|
149
|
+
expect(transaction).to receive(:set_error).with(VerySpecificError)
|
54
150
|
end
|
55
151
|
|
56
152
|
after do
|
57
|
-
|
153
|
+
expect do
|
58
154
|
Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
|
59
155
|
Appsignal::Hooks::ShoryukenMiddleware.new.call(worker_instance, queue, sqs_msg, body) do
|
60
|
-
raise
|
156
|
+
raise VerySpecificError
|
61
157
|
end
|
62
158
|
end
|
63
|
-
|
64
|
-
end
|
159
|
+
end.to raise_error(VerySpecificError)
|
65
160
|
end
|
66
161
|
end
|
67
162
|
end
|