appsignal 2.4.0.alpha.1 → 2.4.0
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/.travis.yml +0 -7
- data/CHANGELOG.md +5 -1
- data/README.md +3 -2
- data/Rakefile +0 -1
- data/lib/appsignal.rb +29 -2
- data/lib/appsignal/hooks/sidekiq.rb +20 -67
- data/lib/appsignal/integrations/capistrano/appsignal.cap +1 -1
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +1 -1
- data/lib/appsignal/transaction.rb +0 -7
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/capistrano2_spec.rb +14 -0
- data/spec/lib/appsignal/capistrano3_spec.rb +14 -0
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +192 -224
- data/spec/lib/appsignal_spec.rb +39 -5
- data/spec/support/helpers/dependency_helper.rb +0 -4
- data/spec/support/helpers/transaction_helpers.rb +0 -6
- metadata +4 -5
- data/gemfiles/sidekiq.gemfile +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73a704494489e09f2d92ffc41f9628aef70e9974
|
4
|
+
data.tar.gz: 267fe55728850ffe4802ea0761a748c809235de5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd3aa5683ed5c745a828caa4b4971cc1795056c91d990d114cd8e95737ce9bc02419b5255c91761cb3b5bec4aa1fdee9c59b47c6588f52a3f27679342ca2a14e
|
7
|
+
data.tar.gz: d2f42c59c32fc1dcfe7be0e64466d0afafc81e4d355b26c5b9618436ed9946b67e8988a960d689ada112798551833c4cc81fe6038a0de9c80487164f00ac3fc5
|
data/.travis.yml
CHANGED
@@ -30,7 +30,6 @@ gemfile:
|
|
30
30
|
- "gemfiles/resque.gemfile"
|
31
31
|
- "gemfiles/sequel.gemfile"
|
32
32
|
- "gemfiles/sequel-435.gemfile"
|
33
|
-
- "gemfiles/sidekiq.gemfile"
|
34
33
|
- "gemfiles/sinatra.gemfile"
|
35
34
|
- "gemfiles/grape.gemfile"
|
36
35
|
- "gemfiles/webmachine.gemfile"
|
@@ -46,12 +45,6 @@ matrix:
|
|
46
45
|
- rvm: "jruby-19mode"
|
47
46
|
|
48
47
|
# Rails 5 doesn't support Ruby < 2.2
|
49
|
-
- rvm: "2.0.0"
|
50
|
-
gemfile: "gemfiles/sidekiq.gemfile"
|
51
|
-
- rvm: "2.1.8"
|
52
|
-
gemfile: "gemfiles/sidekiq.gemfile"
|
53
|
-
- rvm: "jruby-19mode"
|
54
|
-
gemfile: "gemfiles/sidekiq.gemfile"
|
55
48
|
- rvm: "2.0.0"
|
56
49
|
gemfile: "gemfiles/rails-5.0.gemfile"
|
57
50
|
- rvm: "2.1.8"
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# 2.4.0
|
1
|
+
# 2.4.0
|
2
2
|
- Add separate GNU linux build. PR #351 and
|
3
3
|
Commit d1763f4dcb685608468a73f3192226f60f66b217
|
4
4
|
- Add separate FreeBSD build
|
@@ -8,7 +8,11 @@
|
|
8
8
|
Commit d1763f4dcb685608468a73f3192226f60f66b217
|
9
9
|
- Auto restart agent when none is running
|
10
10
|
Commit d1763f4dcb685608468a73f3192226f60f66b217
|
11
|
+
- Add `appsignal_user` Capistrano config option. PR #355
|
11
12
|
- Track Exception-level exceptions. PR #356
|
13
|
+
- Add tags and namespace arguments to `Appsignal.listen_for_error`. PR #357
|
14
|
+
- Revert Sidekiq delayed extension job action names fix.
|
15
|
+
Commit 9b84a098604de5ef5e52645ba7fcb09d84f66eaa
|
12
16
|
|
13
17
|
# 2.3.7
|
14
18
|
* Support Sidekiq delayed extension job action names better. Now action names
|
data/README.md
CHANGED
@@ -72,7 +72,8 @@ instrumentation anywhere in your code.
|
|
72
72
|
```ruby
|
73
73
|
# Simple instrumentation
|
74
74
|
Appsignal.instrument("array_to_hash.expensive_logic", "Complex calculations") do
|
75
|
-
|
75
|
+
array = [["a", 1], ["b", 2], ["c", 3]]
|
76
|
+
Hash[array]
|
76
77
|
end
|
77
78
|
|
78
79
|
# Add the query that you're monitoring
|
@@ -150,7 +151,7 @@ currently. Be sure to check it out!
|
|
150
151
|
## Supported systems
|
151
152
|
|
152
153
|
Currently the AppSignal agent works on most Unix-like operating systems, such
|
153
|
-
as most Linux distributions
|
154
|
+
as most Linux distributions, FreeBSD, macOS, excluding Microsoft Windows.
|
154
155
|
|
155
156
|
For more detailed information please visit our [Supported
|
156
157
|
systems][supported-systems] page.
|
data/Rakefile
CHANGED
data/lib/appsignal.rb
CHANGED
@@ -217,10 +217,37 @@ module Appsignal
|
|
217
217
|
stop("monitor_single_transaction")
|
218
218
|
end
|
219
219
|
|
220
|
-
|
220
|
+
# Listen for an error to occur and send it to AppSignal.
|
221
|
+
#
|
222
|
+
# Uses {.send_error} to directly send the error in a separate transaction.
|
223
|
+
# Does not add the error to the current transaction.
|
224
|
+
#
|
225
|
+
# Make sure that AppSignal is integrated in your application beforehand.
|
226
|
+
# AppSignal won't record errors unless {Config#active?} is `true`.
|
227
|
+
#
|
228
|
+
# @example
|
229
|
+
# # my_app.rb
|
230
|
+
# # setup AppSignal beforehand
|
231
|
+
#
|
232
|
+
# Appsignal.listen_for_error do
|
233
|
+
# # my code
|
234
|
+
# raise "foo"
|
235
|
+
# end
|
236
|
+
#
|
237
|
+
# @see Transaction.set_tags
|
238
|
+
# @see Transaction.set_namespace
|
239
|
+
# @see .send_error
|
240
|
+
# @see https://docs.appsignal.com/ruby/instrumentation/integrating-appsignal.html
|
241
|
+
# AppSignal integration guide
|
242
|
+
#
|
243
|
+
# @param tags [Hash, nil]
|
244
|
+
# @param namespace [String] the namespace for this error.
|
245
|
+
# @yield yields the given block.
|
246
|
+
# @return [Object] returns the return value of the given block.
|
247
|
+
def listen_for_error(tags = nil, namespace = Appsignal::Transaction::HTTP_REQUEST)
|
221
248
|
yield
|
222
249
|
rescue Exception => error # rubocop:disable Lint/RescueException
|
223
|
-
send_error(error)
|
250
|
+
send_error(error, tags, namespace)
|
224
251
|
raise error
|
225
252
|
end
|
226
253
|
alias :listen_for_exception :listen_for_error
|
@@ -14,78 +14,32 @@ module Appsignal
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def call(_worker, item, _queue)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
call_and_log_on_error(job, &:display_args),
|
23
|
-
:filter_parameters => Appsignal.config[:filter_parameters]
|
24
|
-
)
|
25
|
-
|
26
|
-
transaction = Appsignal::Transaction.create(
|
27
|
-
SecureRandom.uuid,
|
28
|
-
Appsignal::Transaction::BACKGROUND_JOB,
|
29
|
-
Appsignal::Transaction::GenericRequest.new(
|
30
|
-
:queue_start => call_and_log_on_error(job, &:enqueued_at),
|
31
|
-
:queue_time => call_and_log_on_error(job) { |j| j.latency.to_f * 1000 }
|
32
|
-
)
|
33
|
-
)
|
34
|
-
|
35
|
-
Appsignal.instrument "perform_job.sidekiq" do
|
36
|
-
begin
|
37
|
-
yield
|
38
|
-
rescue Exception => exception # rubocop:disable Lint/RescueException
|
39
|
-
transaction.set_error(exception)
|
40
|
-
raise exception
|
17
|
+
args =
|
18
|
+
if item["class"] == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
19
|
+
item["args"].first["arguments"]
|
20
|
+
else
|
21
|
+
item["args"]
|
41
22
|
end
|
42
|
-
|
43
|
-
|
44
|
-
if transaction
|
45
|
-
transaction.set_action_if_nil(job_action_name)
|
46
|
-
transaction.params = params
|
47
|
-
formatted_metadata(job_metadata).each do |key, value|
|
48
|
-
transaction.set_metadata key, value
|
49
|
-
end
|
50
|
-
transaction.set_http_or_background_queue_start
|
51
|
-
Appsignal::Transaction.complete_current!
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def fetch_sidekiq_job
|
58
|
-
yield
|
59
|
-
rescue NameError => e
|
60
|
-
Appsignal.logger.error("Problem parsing the Sidekiq job data: #{e.inspect}")
|
61
|
-
nil
|
62
|
-
end
|
63
|
-
|
64
|
-
def call_and_log_on_error(job)
|
65
|
-
yield job if job
|
66
|
-
rescue NameError => e
|
67
|
-
Appsignal.logger.error("Problem parsing the Sidekiq job data: #{e.inspect}")
|
68
|
-
nil
|
69
|
-
end
|
23
|
+
params = Appsignal::Utils::ParamsSanitizer.sanitize args,
|
24
|
+
:filter_parameters => Appsignal.config[:filter_parameters]
|
70
25
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
26
|
+
Appsignal.monitor_transaction(
|
27
|
+
"perform_job.sidekiq",
|
28
|
+
:class => item["wrapped"] || item["class"],
|
29
|
+
:method => "perform",
|
30
|
+
:metadata => formatted_metadata(item),
|
31
|
+
:params => params,
|
32
|
+
:queue_start => item["enqueued_at"],
|
33
|
+
:queue_time => (Time.now.to_f - item["enqueued_at"].to_f) * 1000
|
34
|
+
) do
|
35
|
+
yield
|
81
36
|
end
|
82
37
|
end
|
83
38
|
|
84
39
|
def formatted_metadata(item)
|
85
|
-
{}.tap do |
|
86
|
-
|
87
|
-
|
88
|
-
hash[key] = truncate(string_or_inspect(value))
|
40
|
+
{}.tap do |hsh|
|
41
|
+
item.each do |key, val|
|
42
|
+
hsh[key] = truncate(string_or_inspect(val)) unless job_keys.include?(key)
|
89
43
|
end
|
90
44
|
end
|
91
45
|
end
|
@@ -99,7 +53,6 @@ module Appsignal
|
|
99
53
|
end
|
100
54
|
|
101
55
|
def install
|
102
|
-
require "sidekiq/api"
|
103
56
|
::Sidekiq.configure_server do |config|
|
104
57
|
config.server_middleware do |chain|
|
105
58
|
chain.add Appsignal::Hooks::SidekiqPlugin
|
@@ -1,7 +1,7 @@
|
|
1
1
|
namespace :appsignal do
|
2
2
|
task :deploy do
|
3
3
|
appsignal_env = fetch(:appsignal_env, fetch(:stage, fetch(:rails_env, fetch(:rack_env, "production"))))
|
4
|
-
user = ENV["USER"] || ENV["USERNAME"]
|
4
|
+
user = fetch(:appsignal_user, ENV["USER"] || ENV["USERNAME"])
|
5
5
|
revision = fetch(:appsignal_revision, fetch(:current_revision))
|
6
6
|
|
7
7
|
appsignal_config = Appsignal::Config.new(
|
@@ -10,7 +10,7 @@ module Appsignal
|
|
10
10
|
namespace :appsignal do
|
11
11
|
task :deploy do
|
12
12
|
env = fetch(:appsignal_env, fetch(:stage, fetch(:rails_env, fetch(:rack_env, "production"))))
|
13
|
-
user = ENV["USER"] || ENV["USERNAME"]
|
13
|
+
user = fetch(:appsignal_user, ENV["USER"] || ENV["USERNAME"])
|
14
14
|
revision = fetch(:appsignal_revision, fetch(:current_revision))
|
15
15
|
|
16
16
|
appsignal_config = Appsignal::Config.new(
|
@@ -54,12 +54,6 @@ module Appsignal
|
|
54
54
|
rescue => e
|
55
55
|
Appsignal.logger.error("Failed to complete transaction ##{current.transaction_id}. #{e.message}")
|
56
56
|
ensure
|
57
|
-
clear_current_transaction!
|
58
|
-
end
|
59
|
-
|
60
|
-
# Remove current transaction from current Thread.
|
61
|
-
# @api private
|
62
|
-
def clear_current_transaction!
|
63
57
|
Thread.current[:appsignal_transaction] = nil
|
64
58
|
end
|
65
59
|
|
@@ -318,7 +312,6 @@ module Appsignal
|
|
318
312
|
finish_event(name, title, body, body_format)
|
319
313
|
end
|
320
314
|
|
321
|
-
# @api private
|
322
315
|
def to_h
|
323
316
|
JSON.parse(@ext.to_json)
|
324
317
|
end
|
data/lib/appsignal/version.rb
CHANGED
@@ -152,6 +152,20 @@ if DependencyHelper.capistrano2_present?
|
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
155
|
+
context "with overridden deploy user" do
|
156
|
+
before do
|
157
|
+
capistrano_config.set(:appsignal_user, "robin")
|
158
|
+
stub_marker_request(:user => "robin").to_return(:status => 200)
|
159
|
+
run
|
160
|
+
end
|
161
|
+
|
162
|
+
it "transmits the overriden deploy user" do
|
163
|
+
expect(output).to include \
|
164
|
+
"Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: robin",
|
165
|
+
"AppSignal has been notified of this deploy!"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
155
169
|
context "with failed request" do
|
156
170
|
before do
|
157
171
|
stub_marker_request.to_return(:status => 500)
|
@@ -152,6 +152,20 @@ if DependencyHelper.capistrano3_present?
|
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
155
|
+
context "with overridden deploy user" do
|
156
|
+
before do
|
157
|
+
capistrano_config.set(:appsignal_user, "robin")
|
158
|
+
stub_marker_request(:user => "robin").to_return(:status => 200)
|
159
|
+
run
|
160
|
+
end
|
161
|
+
|
162
|
+
it "transmits the overriden deploy user" do
|
163
|
+
expect(output).to include \
|
164
|
+
"Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: robin",
|
165
|
+
"AppSignal has been notified of this deploy!"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
155
169
|
if Gem::Version.new(Capistrano::VERSION) >= Gem::Version.new("3.5.0")
|
156
170
|
context "when dry run" do
|
157
171
|
before do
|
@@ -1,101 +1,145 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
let(:plugin) { Appsignal::Hooks::SidekiqPlugin.new }
|
19
|
-
let(:test_store) { {} }
|
1
|
+
describe Appsignal::Hooks::SidekiqPlugin do
|
2
|
+
let(:worker) { double }
|
3
|
+
let(:queue) { double }
|
4
|
+
let(:current_transaction) { background_job_transaction }
|
5
|
+
let(:args) { ["Model", 1] }
|
6
|
+
let(:item) do
|
7
|
+
{
|
8
|
+
"class" => "TestClass",
|
9
|
+
"retry_count" => 0,
|
10
|
+
"queue" => "default",
|
11
|
+
"enqueued_at" => Time.parse("01-01-2001 10:00:00UTC"),
|
12
|
+
"args" => args,
|
13
|
+
"extra" => "data"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
let(:plugin) { Appsignal::Hooks::SidekiqPlugin.new }
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
allow_any_instance_of(Appsignal::Extension::Transaction).to receive(:complete)
|
18
|
+
before do
|
19
|
+
allow(Appsignal::Transaction).to receive(:current).and_return(current_transaction)
|
20
|
+
start_agent
|
21
|
+
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
context "with a performance call" do
|
24
|
+
after do
|
25
|
+
Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
|
26
|
+
Appsignal::Hooks::SidekiqPlugin.new.call(worker, item, queue) do
|
27
|
+
# nothing
|
28
|
+
end
|
32
29
|
end
|
33
30
|
end
|
34
|
-
|
35
|
-
|
31
|
+
|
32
|
+
it "wraps it in a transaction with the correct params" do
|
33
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
34
|
+
"perform_job.sidekiq",
|
35
|
+
:class => "TestClass",
|
36
|
+
:method => "perform",
|
37
|
+
:metadata => {
|
38
|
+
"retry_count" => "0",
|
39
|
+
"queue" => "default",
|
40
|
+
"extra" => "data"
|
41
|
+
},
|
42
|
+
:params => ["Model", 1],
|
43
|
+
:queue_start => Time.parse("01-01-2001 10:00:00UTC"),
|
44
|
+
:queue_time => 60_000.to_f
|
45
|
+
)
|
36
46
|
end
|
37
|
-
after { clear_current_transaction! }
|
38
47
|
|
39
|
-
context "
|
40
|
-
let(:
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
48
|
+
context "with more complex arguments" do
|
49
|
+
let(:default_params) do
|
50
|
+
{
|
51
|
+
:class => "TestClass",
|
52
|
+
:method => "perform",
|
53
|
+
:metadata => {
|
54
|
+
"retry_count" => "0",
|
55
|
+
"queue" => "default",
|
56
|
+
"extra" => "data"
|
57
|
+
},
|
58
|
+
:params => {
|
59
|
+
:foo => "Foo",
|
60
|
+
:bar => "Bar"
|
61
|
+
},
|
62
|
+
:queue_start => Time.parse("01-01-2001 10:00:00UTC"),
|
63
|
+
:queue_time => 60_000.to_f
|
64
|
+
}
|
65
|
+
end
|
66
|
+
let(:args) do
|
67
|
+
{
|
68
|
+
:foo => "Foo",
|
69
|
+
:bar => "Bar"
|
70
|
+
}
|
45
71
|
end
|
46
72
|
|
47
|
-
it "
|
48
|
-
expect(
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
73
|
+
it "adds the more complex arguments" do
|
74
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
75
|
+
"perform_job.sidekiq",
|
76
|
+
default_params.merge(
|
77
|
+
:params => {
|
78
|
+
:foo => "Foo",
|
79
|
+
:bar => "Bar"
|
80
|
+
}
|
81
|
+
)
|
53
82
|
)
|
54
83
|
end
|
55
|
-
end
|
56
84
|
|
57
|
-
|
58
|
-
|
59
|
-
|
85
|
+
context "with parameter filtering" do
|
86
|
+
before do
|
87
|
+
Appsignal.config = project_fixture_config("production")
|
88
|
+
Appsignal.config[:filter_parameters] = ["foo"]
|
89
|
+
end
|
60
90
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
"sample_data" => {
|
73
|
-
"environment" => {},
|
74
|
-
"params" => args,
|
75
|
-
"tags" => {}
|
76
|
-
}
|
77
|
-
)
|
78
|
-
# TODO: Not available in transaction.to_h yet.
|
79
|
-
# https://github.com/appsignal/appsignal-agent/issues/293
|
80
|
-
expect(transaction.request.env).to eq(
|
81
|
-
:queue_start => Time.parse("01-01-2001 10:00:00UTC"),
|
82
|
-
:queue_time => 60_000.0
|
83
|
-
)
|
84
|
-
expect_transaction_to_have_sidekiq_event(transaction_hash)
|
91
|
+
it "filters selected arguments" do
|
92
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
93
|
+
"perform_job.sidekiq",
|
94
|
+
default_params.merge(
|
95
|
+
:params => {
|
96
|
+
:foo => "[FILTERED]",
|
97
|
+
:bar => "Bar"
|
98
|
+
}
|
99
|
+
)
|
100
|
+
)
|
101
|
+
end
|
85
102
|
end
|
103
|
+
end
|
86
104
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
105
|
+
context "when wrapped by ActiveJob" do
|
106
|
+
let(:item) do
|
107
|
+
{
|
108
|
+
"class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
|
109
|
+
"wrapped" => "TestClass",
|
110
|
+
"queue" => "default",
|
111
|
+
"args" => [{
|
112
|
+
"job_class" => "TestJob",
|
113
|
+
"job_id" => "23e79d48-6966-40d0-b2d4-f7938463a263",
|
114
|
+
"queue_name" => "default",
|
115
|
+
"arguments" => args
|
116
|
+
}],
|
117
|
+
"retry" => true,
|
118
|
+
"jid" => "efb140489485999d32b5504c",
|
119
|
+
"created_at" => Time.parse("01-01-2001 10:00:00UTC").to_f,
|
120
|
+
"enqueued_at" => Time.parse("01-01-2001 10:00:00UTC").to_f
|
121
|
+
}
|
122
|
+
end
|
123
|
+
let(:default_params) do
|
124
|
+
{
|
125
|
+
:class => "TestClass",
|
126
|
+
:method => "perform",
|
127
|
+
:metadata => {
|
128
|
+
"queue" => "default"
|
129
|
+
},
|
130
|
+
:queue_start => Time.parse("01-01-2001 10:00:00UTC").to_f,
|
131
|
+
:queue_time => 60_000.to_f
|
132
|
+
}
|
133
|
+
end
|
92
134
|
|
93
|
-
|
94
|
-
|
95
|
-
|
135
|
+
it "wraps it in a transaction with the correct params" do
|
136
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
137
|
+
"perform_job.sidekiq",
|
138
|
+
default_params.merge(:params => ["Model", 1])
|
139
|
+
)
|
96
140
|
end
|
97
141
|
|
98
|
-
context "with more complex
|
142
|
+
context "with more complex arguments" do
|
99
143
|
let(:args) do
|
100
144
|
{
|
101
145
|
:foo => "Foo",
|
@@ -104,14 +148,14 @@ if DependencyHelper.sidekiq_present?
|
|
104
148
|
end
|
105
149
|
|
106
150
|
it "adds the more complex arguments" do
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
151
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
152
|
+
"perform_job.sidekiq",
|
153
|
+
default_params.merge(
|
154
|
+
:params => {
|
155
|
+
:foo => "Foo",
|
156
|
+
:bar => "Bar"
|
157
|
+
}
|
158
|
+
)
|
115
159
|
)
|
116
160
|
end
|
117
161
|
|
@@ -122,166 +166,90 @@ if DependencyHelper.sidekiq_present?
|
|
122
166
|
end
|
123
167
|
|
124
168
|
it "filters selected arguments" do
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
"bar" => "Bar"
|
132
|
-
}
|
133
|
-
)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
context "when job is wrapped by ActiveJob" do
|
139
|
-
let(:item) do
|
140
|
-
{
|
141
|
-
"class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
|
142
|
-
"wrapped" => "TestClass",
|
143
|
-
"queue" => "default",
|
144
|
-
"args" => [{
|
145
|
-
"job_class" => "TestJob",
|
146
|
-
"job_id" => "23e79d48-6966-40d0-b2d4-f7938463a263",
|
147
|
-
"queue_name" => "default",
|
148
|
-
"arguments" => args
|
149
|
-
}],
|
150
|
-
"retry" => true,
|
151
|
-
"jid" => "efb140489485999d32b5504c",
|
152
|
-
"created_at" => Time.parse("01-01-2001 10:00:00UTC"),
|
153
|
-
"enqueued_at" => Time.parse("01-01-2001 10:00:00UTC").to_f
|
154
|
-
}
|
155
|
-
end
|
156
|
-
|
157
|
-
it "creates a transaction with performance events" do
|
158
|
-
perform_job
|
159
|
-
|
160
|
-
transaction_hash = transaction.to_h
|
161
|
-
expect(transaction_hash).to include(
|
162
|
-
"id" => kind_of(String),
|
163
|
-
"action" => "TestClass#perform",
|
164
|
-
"error" => nil,
|
165
|
-
"namespace" => namespace,
|
166
|
-
"metadata" => {
|
167
|
-
"queue" => "default"
|
168
|
-
},
|
169
|
-
"sample_data" => {
|
170
|
-
"environment" => {},
|
171
|
-
"params" => args,
|
172
|
-
"tags" => {}
|
173
|
-
}
|
174
|
-
)
|
175
|
-
# TODO: Not available in transaction.to_h yet.
|
176
|
-
# https://github.com/appsignal/appsignal-agent/issues/293
|
177
|
-
expect(transaction.request.env).to eq(
|
178
|
-
:queue_start => Time.parse("01-01-2001 10:00:00UTC"),
|
179
|
-
:queue_time => 60_000.0
|
180
|
-
)
|
181
|
-
expect_transaction_to_have_sidekiq_event(transaction_hash)
|
182
|
-
end
|
183
|
-
|
184
|
-
context "with more complex arguments" do
|
185
|
-
let(:args) do
|
186
|
-
{
|
187
|
-
:foo => "Foo",
|
188
|
-
:bar => "Bar"
|
189
|
-
}
|
190
|
-
end
|
191
|
-
|
192
|
-
it "adds the more complex arguments" do
|
193
|
-
perform_job
|
194
|
-
|
195
|
-
transaction_hash = transaction.to_h
|
196
|
-
expect(transaction_hash["sample_data"]).to include(
|
197
|
-
"params" => {
|
198
|
-
"foo" => "Foo",
|
199
|
-
"bar" => "Bar"
|
200
|
-
}
|
201
|
-
)
|
202
|
-
end
|
203
|
-
|
204
|
-
context "with parameter filtering" do
|
205
|
-
before do
|
206
|
-
Appsignal.config = project_fixture_config("production")
|
207
|
-
Appsignal.config[:filter_parameters] = ["foo"]
|
208
|
-
end
|
209
|
-
|
210
|
-
it "filters selected arguments" do
|
211
|
-
perform_job
|
212
|
-
|
213
|
-
transaction_hash = transaction.to_h
|
214
|
-
expect(transaction_hash["sample_data"]).to include(
|
215
|
-
"params" => {
|
216
|
-
"foo" => "[FILTERED]",
|
217
|
-
"bar" => "Bar"
|
169
|
+
expect(Appsignal).to receive(:monitor_transaction).with(
|
170
|
+
"perform_job.sidekiq",
|
171
|
+
default_params.merge(
|
172
|
+
:params => {
|
173
|
+
:foo => "[FILTERED]",
|
174
|
+
:bar => "Bar"
|
218
175
|
}
|
219
176
|
)
|
220
|
-
|
177
|
+
)
|
221
178
|
end
|
222
179
|
end
|
223
180
|
end
|
224
181
|
end
|
182
|
+
end
|
225
183
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
184
|
+
context "with an erroring call" do
|
185
|
+
let(:error) { ExampleException }
|
186
|
+
let(:transaction) do
|
187
|
+
Appsignal::Transaction.new(
|
188
|
+
SecureRandom.uuid,
|
189
|
+
Appsignal::Transaction::BACKGROUND_JOB,
|
190
|
+
Appsignal::Transaction::GenericRequest.new({})
|
191
|
+
)
|
192
|
+
end
|
193
|
+
before do
|
194
|
+
allow(Appsignal::Transaction).to receive(:current).and_return(transaction)
|
195
|
+
expect(Appsignal::Transaction).to receive(:create)
|
196
|
+
.with(
|
197
|
+
kind_of(String),
|
198
|
+
Appsignal::Transaction::BACKGROUND_JOB,
|
199
|
+
kind_of(Appsignal::Transaction::GenericRequest)
|
200
|
+
).and_return(transaction)
|
201
|
+
end
|
237
202
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
# https://github.com/appsignal/appsignal-agent/issues/294
|
242
|
-
expect(transaction_hash["error"]).to include(
|
243
|
-
"name" => "ExampleException",
|
244
|
-
"message" => "uh oh",
|
245
|
-
"backtrace" => kind_of(String)
|
246
|
-
)
|
247
|
-
expect_transaction_to_have_sidekiq_event(transaction_hash)
|
248
|
-
end
|
203
|
+
it "adds the error to the transaction" do
|
204
|
+
expect(transaction).to receive(:set_error).with(error)
|
205
|
+
expect(transaction).to receive(:complete)
|
249
206
|
end
|
250
207
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
208
|
+
after do
|
209
|
+
expect do
|
210
|
+
Timecop.freeze(Time.parse("01-01-2001 10:01:00UTC")) do
|
211
|
+
Appsignal::Hooks::SidekiqPlugin.new.call(worker, item, queue) do
|
212
|
+
raise error
|
213
|
+
end
|
255
214
|
end
|
256
|
-
end
|
215
|
+
end.to raise_error(error)
|
257
216
|
end
|
217
|
+
end
|
258
218
|
|
259
|
-
|
260
|
-
|
219
|
+
# TODO: Don't test (what are basically) private methods
|
220
|
+
describe "#formatted_data" do
|
221
|
+
let(:item) do
|
222
|
+
{
|
223
|
+
"foo" => "bar",
|
224
|
+
"class" => "TestClass"
|
225
|
+
}
|
261
226
|
end
|
262
227
|
|
263
|
-
|
264
|
-
|
265
|
-
expect(events.count).to eq(1)
|
266
|
-
expect(events.first).to include(
|
267
|
-
"name" => "perform_job.sidekiq",
|
268
|
-
"title" => "",
|
269
|
-
"count" => 1,
|
270
|
-
"body" => "",
|
271
|
-
"body_format" => Appsignal::EventFormatter::DEFAULT
|
272
|
-
)
|
228
|
+
it "only adds items to the hash that do not appear in JOB_KEYS" do
|
229
|
+
expect(plugin.formatted_metadata(item)).to eq("foo" => "bar")
|
273
230
|
end
|
274
231
|
end
|
275
232
|
end
|
276
233
|
|
277
234
|
describe Appsignal::Hooks::SidekiqHook do
|
278
|
-
|
235
|
+
context "with sidekiq" do
|
236
|
+
before :context do
|
237
|
+
module Sidekiq
|
238
|
+
def self.configure_server
|
239
|
+
end
|
240
|
+
end
|
241
|
+
Appsignal::Hooks::SidekiqHook.new.install
|
242
|
+
end
|
243
|
+
after(:context) { Object.send(:remove_const, :Sidekiq) }
|
244
|
+
|
279
245
|
describe "#dependencies_present?" do
|
280
246
|
subject { described_class.new.dependencies_present? }
|
281
247
|
|
282
248
|
it { is_expected.to be_truthy }
|
283
249
|
end
|
284
|
-
|
250
|
+
end
|
251
|
+
|
252
|
+
context "without sidekiq" do
|
285
253
|
describe "#dependencies_present?" do
|
286
254
|
subject { described_class.new.dependencies_present? }
|
287
255
|
|
data/spec/lib/appsignal_spec.rb
CHANGED
@@ -257,7 +257,7 @@ describe Appsignal do
|
|
257
257
|
end
|
258
258
|
|
259
259
|
describe ".listen_for_error" do
|
260
|
-
it "
|
260
|
+
it "does not record anyhing" do
|
261
261
|
error = RuntimeError.new("specific error")
|
262
262
|
expect do
|
263
263
|
Appsignal.listen_for_error do
|
@@ -779,13 +779,47 @@ describe Appsignal do
|
|
779
779
|
end
|
780
780
|
|
781
781
|
describe ".listen_for_error" do
|
782
|
-
it "
|
783
|
-
expect(Appsignal).to receive(:send_error).with(
|
782
|
+
it "records the error and re-raise it" do
|
783
|
+
expect(Appsignal).to receive(:send_error).with(
|
784
|
+
kind_of(ExampleException),
|
785
|
+
nil,
|
786
|
+
Appsignal::Transaction::HTTP_REQUEST
|
787
|
+
)
|
784
788
|
expect do
|
785
789
|
Appsignal.listen_for_error do
|
786
|
-
raise "I am an exception"
|
790
|
+
raise ExampleException, "I am an exception"
|
787
791
|
end
|
788
|
-
end.to raise_error(
|
792
|
+
end.to raise_error(ExampleException, "I am an exception")
|
793
|
+
end
|
794
|
+
|
795
|
+
context "with tags" do
|
796
|
+
it "adds tags to the transaction" do
|
797
|
+
expect(Appsignal).to receive(:send_error).with(
|
798
|
+
kind_of(ExampleException),
|
799
|
+
{ "foo" => "bar" },
|
800
|
+
Appsignal::Transaction::HTTP_REQUEST
|
801
|
+
)
|
802
|
+
expect do
|
803
|
+
Appsignal.listen_for_error("foo" => "bar") do
|
804
|
+
raise ExampleException, "I am an exception"
|
805
|
+
end
|
806
|
+
end.to raise_error(ExampleException, "I am an exception")
|
807
|
+
end
|
808
|
+
end
|
809
|
+
|
810
|
+
context "with a custom namespace" do
|
811
|
+
it "adds the namespace to the transaction" do
|
812
|
+
expect(Appsignal).to receive(:send_error).with(
|
813
|
+
kind_of(ExampleException),
|
814
|
+
nil,
|
815
|
+
"custom_namespace"
|
816
|
+
)
|
817
|
+
expect do
|
818
|
+
Appsignal.listen_for_error(nil, "custom_namespace") do
|
819
|
+
raise ExampleException, "I am an exception"
|
820
|
+
end
|
821
|
+
end.to raise_error(ExampleException, "I am an exception")
|
822
|
+
end
|
789
823
|
end
|
790
824
|
end
|
791
825
|
|
@@ -63,10 +63,6 @@ module DependencyHelper
|
|
63
63
|
Gem.loaded_specs["capistrano"].version >= Gem::Version.new("3.0")
|
64
64
|
end
|
65
65
|
|
66
|
-
def sidekiq_present?
|
67
|
-
dependency_present? "sidekiq"
|
68
|
-
end
|
69
|
-
|
70
66
|
def dependency_present?(dependency_file)
|
71
67
|
Gem.loaded_specs.key? dependency_file
|
72
68
|
end
|
@@ -28,10 +28,4 @@ module TransactionHelpers
|
|
28
28
|
}.merge(args))
|
29
29
|
)
|
30
30
|
end
|
31
|
-
|
32
|
-
# Use when {Appsignal::Transaction.clear_current_transaction!} is stubbed to
|
33
|
-
# clear the current transaction on the current thread.
|
34
|
-
def clear_current_transaction!
|
35
|
-
Thread.current[:appsignal_transaction] = nil
|
36
|
-
end
|
37
31
|
end
|
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: 2.4.0
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Beekman
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-10-
|
12
|
+
date: 2017-10-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -163,7 +163,6 @@ files:
|
|
163
163
|
- gemfiles/resque.gemfile
|
164
164
|
- gemfiles/sequel-435.gemfile
|
165
165
|
- gemfiles/sequel.gemfile
|
166
|
-
- gemfiles/sidekiq.gemfile
|
167
166
|
- gemfiles/sinatra.gemfile
|
168
167
|
- gemfiles/webmachine.gemfile
|
169
168
|
- lib/appsignal.rb
|
@@ -349,9 +348,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
349
348
|
version: '1.9'
|
350
349
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
351
350
|
requirements:
|
352
|
-
- - "
|
351
|
+
- - ">="
|
353
352
|
- !ruby/object:Gem::Version
|
354
|
-
version:
|
353
|
+
version: '0'
|
355
354
|
requirements: []
|
356
355
|
rubyforge_project:
|
357
356
|
rubygems_version: 2.5.2.1
|