appsignal 2.8.4.beta.1 → 2.9.18.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
- data/.github/ISSUE_TEMPLATE/chore.md +14 -0
- data/.gitignore +2 -3
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +7 -16
- data/.travis.yml +28 -27
- data/CHANGELOG.md +657 -533
- data/README.md +31 -3
- data/Rakefile +128 -129
- data/SUPPORT.md +16 -0
- data/appsignal.gemspec +17 -4
- data/build_matrix.yml +21 -9
- data/ext/Rakefile +23 -17
- data/ext/agent.yml +40 -37
- data/ext/base.rb +116 -31
- data/ext/extconf.rb +34 -28
- data/gemfiles/capistrano2.gemfile +5 -0
- data/gemfiles/capistrano3.gemfile +5 -0
- data/gemfiles/grape.gemfile +5 -0
- data/gemfiles/no_dependencies.gemfile +5 -0
- data/gemfiles/padrino.gemfile +5 -0
- data/gemfiles/que.gemfile +5 -0
- data/gemfiles/que_beta.gemfile +10 -0
- data/gemfiles/rails-3.2.gemfile +5 -0
- data/gemfiles/rails-4.0.gemfile +5 -0
- data/gemfiles/rails-4.1.gemfile +5 -0
- data/gemfiles/rails-4.2.gemfile +5 -0
- data/gemfiles/rails-6.0.gemfile +5 -0
- data/gemfiles/resque.gemfile +5 -0
- data/lib/appsignal.rb +14 -492
- data/lib/appsignal/cli/demo.rb +5 -2
- data/lib/appsignal/cli/diagnose.rb +84 -4
- data/lib/appsignal/cli/diagnose/paths.rb +0 -5
- data/lib/appsignal/cli/diagnose/utils.rb +19 -0
- data/lib/appsignal/cli/helpers.rb +6 -0
- data/lib/appsignal/cli/install.rb +45 -15
- data/lib/appsignal/cli/notify_of_deploy.rb +10 -0
- data/lib/appsignal/config.rb +1 -2
- data/lib/appsignal/event_formatter.rb +4 -5
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +10 -8
- data/lib/appsignal/event_formatter/moped/query_formatter.rb +60 -59
- data/lib/appsignal/extension.rb +2 -2
- data/lib/appsignal/helpers/instrumentation.rb +494 -0
- data/lib/appsignal/helpers/metrics.rb +54 -0
- data/lib/appsignal/hooks.rb +11 -8
- data/lib/appsignal/hooks/active_support_notifications.rb +2 -5
- data/lib/appsignal/hooks/puma.rb +74 -11
- data/lib/appsignal/hooks/sequel.rb +1 -1
- data/lib/appsignal/hooks/sidekiq.rb +115 -0
- data/lib/appsignal/integrations/mongo_ruby_driver.rb +7 -0
- data/lib/appsignal/integrations/que.rb +9 -8
- data/lib/appsignal/integrations/railtie.rb +2 -1
- data/lib/appsignal/marker.rb +2 -3
- data/lib/appsignal/minutely.rb +188 -19
- data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -1
- data/lib/appsignal/system.rb +16 -18
- data/lib/appsignal/transaction.rb +8 -0
- data/lib/appsignal/utils/rails_helper.rb +20 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/puma/plugin/appsignal.rb +26 -0
- data/spec/lib/appsignal/cli/diagnose/utils_spec.rb +40 -0
- data/spec/lib/appsignal/cli/diagnose_spec.rb +129 -22
- data/spec/lib/appsignal/cli/install_spec.rb +57 -8
- data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +10 -0
- data/spec/lib/appsignal/config_spec.rb +13 -11
- data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +38 -28
- data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +6 -0
- data/spec/lib/appsignal/event_formatter_spec.rb +168 -69
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +104 -25
- data/spec/lib/appsignal/hooks/puma_spec.rb +251 -34
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +209 -0
- data/spec/lib/appsignal/hooks_spec.rb +4 -0
- data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +24 -1
- data/spec/lib/appsignal/minutely_spec.rb +318 -26
- data/spec/lib/appsignal/system_spec.rb +0 -35
- data/spec/lib/appsignal/transaction_spec.rb +68 -10
- data/spec/lib/appsignal/utils/hash_sanitizer_spec.rb +39 -31
- data/spec/lib/appsignal/utils/json_spec.rb +7 -3
- data/spec/lib/appsignal_spec.rb +98 -22
- data/spec/lib/puma/appsignal_spec.rb +91 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/application.rb +0 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/appsignal.yml +1 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/environments/development.rb +0 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/environments/production.rb +0 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/config/environments/test.rb +0 -0
- data/spec/support/{project_fixture → fixtures/projects/valid}/log/.gitkeep +0 -0
- data/spec/support/helpers/config_helpers.rb +1 -1
- data/spec/support/helpers/log_helpers.rb +6 -0
- data/spec/support/helpers/wait_for_helper.rb +28 -0
- data/spec/support/mocks/mock_probe.rb +11 -0
- data/spec/support/stubs/sidekiq/api.rb +4 -0
- metadata +43 -31
- data/spec/support/fixtures/containers/cgroups/docker +0 -14
- data/spec/support/fixtures/containers/cgroups/docker_systemd +0 -8
- data/spec/support/fixtures/containers/cgroups/lxc +0 -10
- data/spec/support/fixtures/containers/cgroups/no_permission +0 -0
- data/spec/support/fixtures/containers/cgroups/none +0 -1
@@ -19,41 +19,6 @@ describe Appsignal::System do
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
describe ".installed_agent_architecture" do
|
23
|
-
let(:const_name) { "GEM_EXT_PATH".freeze }
|
24
|
-
let(:tmp_ext_dir) { File.join(tmp_dir, "ext") }
|
25
|
-
let(:architecture_file) { File.join(Appsignal::System::GEM_EXT_PATH, "appsignal.architecture") }
|
26
|
-
around do |example|
|
27
|
-
original_gem_ext_path = Appsignal::System.const_get(const_name)
|
28
|
-
Appsignal::System.send(:remove_const, const_name)
|
29
|
-
Appsignal::System.const_set(const_name, tmp_ext_dir)
|
30
|
-
example.run
|
31
|
-
Appsignal::System.send(:remove_const, const_name)
|
32
|
-
Appsignal::System.const_set(const_name, original_gem_ext_path)
|
33
|
-
end
|
34
|
-
after { FileUtils.rm_rf(tmp_ext_dir) }
|
35
|
-
subject { described_class.installed_agent_architecture }
|
36
|
-
|
37
|
-
context "with an ext/appsignal.architecture file" do
|
38
|
-
before do
|
39
|
-
FileUtils.mkdir_p(Appsignal::System::GEM_EXT_PATH)
|
40
|
-
File.open(architecture_file, "w") do |file|
|
41
|
-
file.write "foo"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
it "returns the contents of the file" do
|
46
|
-
expect(subject).to eq("foo")
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context "without an ext/appsignal.architecture file" do
|
51
|
-
it "returns nil" do
|
52
|
-
expect(subject).to be_nil
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
22
|
describe ".agent_platform" do
|
58
23
|
let(:os) { "linux-gnu" }
|
59
24
|
let(:ldd_output) { "" }
|
@@ -214,7 +214,7 @@ describe Appsignal::Transaction do
|
|
214
214
|
|
215
215
|
context "pausing" do
|
216
216
|
describe "#pause!" do
|
217
|
-
it "
|
217
|
+
it "changes the pause flag to true" do
|
218
218
|
expect do
|
219
219
|
transaction.pause!
|
220
220
|
end.to change(transaction, :paused).from(false).to(true)
|
@@ -224,7 +224,7 @@ describe Appsignal::Transaction do
|
|
224
224
|
describe "#resume!" do
|
225
225
|
before { transaction.pause! }
|
226
226
|
|
227
|
-
it "
|
227
|
+
it "changes the pause flag to false" do
|
228
228
|
expect do
|
229
229
|
transaction.resume!
|
230
230
|
end.to change(transaction, :paused).from(true).to(false)
|
@@ -232,14 +232,16 @@ describe Appsignal::Transaction do
|
|
232
232
|
end
|
233
233
|
|
234
234
|
describe "#paused?" do
|
235
|
-
|
236
|
-
|
235
|
+
context "when not paused" do
|
236
|
+
it "return false" do
|
237
|
+
expect(transaction.paused?).to be_falsy
|
238
|
+
end
|
237
239
|
end
|
238
240
|
|
239
241
|
context "when paused" do
|
240
242
|
before { transaction.pause! }
|
241
243
|
|
242
|
-
it "
|
244
|
+
it "returns true" do
|
243
245
|
expect(transaction.paused?).to be_truthy
|
244
246
|
end
|
245
247
|
end
|
@@ -628,7 +630,11 @@ describe Appsignal::Transaction do
|
|
628
630
|
|
629
631
|
describe "#set_error" do
|
630
632
|
let(:env) { http_request_env_with_data }
|
631
|
-
let(:error)
|
633
|
+
let(:error) do
|
634
|
+
e = ExampleStandardError.new("test message")
|
635
|
+
allow(e).to receive(:backtrace).and_return(["line 1"])
|
636
|
+
e
|
637
|
+
end
|
632
638
|
|
633
639
|
it "should also respond to add_exception for backwords compatibility" do
|
634
640
|
expect(transaction).to respond_to(:add_exception)
|
@@ -641,10 +647,24 @@ describe Appsignal::Transaction do
|
|
641
647
|
transaction.set_error(error)
|
642
648
|
end
|
643
649
|
|
650
|
+
context "when error is not an error" do
|
651
|
+
let(:error) { Object.new }
|
652
|
+
|
653
|
+
it "does not add the error" do
|
654
|
+
expect(Appsignal.logger).to receive(:error).with(
|
655
|
+
"Appsignal::Transaction#set_error: Cannot set error. " \
|
656
|
+
"The given value is not an exception: #{error.inspect}"
|
657
|
+
)
|
658
|
+
expect(transaction.ext).to_not receive(:set_error)
|
659
|
+
|
660
|
+
transaction.set_error(error)
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
644
664
|
context "for a http request" do
|
645
665
|
it "should set an error in the extension" do
|
646
666
|
expect(transaction.ext).to receive(:set_error).with(
|
647
|
-
"
|
667
|
+
"ExampleStandardError",
|
648
668
|
"test message",
|
649
669
|
Appsignal::Utils::Data.generate(["line 1"])
|
650
670
|
)
|
@@ -654,7 +674,12 @@ describe Appsignal::Transaction do
|
|
654
674
|
end
|
655
675
|
|
656
676
|
context "when error message is nil" do
|
657
|
-
let(:error)
|
677
|
+
let(:error) do
|
678
|
+
e = ExampleStandardError.new
|
679
|
+
allow(e).to receive(:message).and_return(nil)
|
680
|
+
allow(e).to receive(:backtrace).and_return(["line 1"])
|
681
|
+
e
|
682
|
+
end
|
658
683
|
|
659
684
|
it "should not raise an error" do
|
660
685
|
expect { transaction.set_error(error) }.to_not raise_error
|
@@ -662,7 +687,7 @@ describe Appsignal::Transaction do
|
|
662
687
|
|
663
688
|
it "should set an error in the extension" do
|
664
689
|
expect(transaction.ext).to receive(:set_error).with(
|
665
|
-
"
|
690
|
+
"ExampleStandardError",
|
666
691
|
"",
|
667
692
|
Appsignal::Utils::Data.generate(["line 1"])
|
668
693
|
)
|
@@ -690,11 +715,20 @@ describe Appsignal::Transaction do
|
|
690
715
|
end
|
691
716
|
|
692
717
|
describe "#start_event" do
|
693
|
-
it "
|
718
|
+
it "starts the event in the extension" do
|
694
719
|
expect(transaction.ext).to receive(:start_event).with(0).and_call_original
|
695
720
|
|
696
721
|
transaction.start_event
|
697
722
|
end
|
723
|
+
|
724
|
+
context "when transaction is paused" do
|
725
|
+
it "does not start the event" do
|
726
|
+
transaction.pause!
|
727
|
+
expect(transaction.ext).to_not receive(:start_event)
|
728
|
+
|
729
|
+
transaction.start_event
|
730
|
+
end
|
731
|
+
end
|
698
732
|
end
|
699
733
|
|
700
734
|
describe "#finish_event" do
|
@@ -737,6 +771,15 @@ describe Appsignal::Transaction do
|
|
737
771
|
nil
|
738
772
|
)
|
739
773
|
end
|
774
|
+
|
775
|
+
context "when transaction is paused" do
|
776
|
+
it "does not finish the event" do
|
777
|
+
transaction.pause!
|
778
|
+
expect(transaction.ext).to_not receive(:finish_event)
|
779
|
+
|
780
|
+
transaction.start_event
|
781
|
+
end
|
782
|
+
end
|
740
783
|
end
|
741
784
|
|
742
785
|
describe "#record_event" do
|
@@ -783,6 +826,21 @@ describe Appsignal::Transaction do
|
|
783
826
|
nil
|
784
827
|
)
|
785
828
|
end
|
829
|
+
|
830
|
+
context "when transaction is paused" do
|
831
|
+
it "does not record the event" do
|
832
|
+
transaction.pause!
|
833
|
+
expect(transaction.ext).to_not receive(:record_event)
|
834
|
+
|
835
|
+
transaction.record_event(
|
836
|
+
"name",
|
837
|
+
nil,
|
838
|
+
nil,
|
839
|
+
1000,
|
840
|
+
nil
|
841
|
+
)
|
842
|
+
end
|
843
|
+
end
|
786
844
|
end
|
787
845
|
|
788
846
|
describe "#instrument" do
|
@@ -30,19 +30,20 @@ describe Appsignal::Utils::HashSanitizer do
|
|
30
30
|
let(:sanitized_params) { described_class.sanitize(params) }
|
31
31
|
subject { sanitized_params }
|
32
32
|
|
33
|
-
it
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
it "returns a sanitized Hash" do
|
34
|
+
expect(subject).to_not eq(params)
|
35
|
+
is_expected.to be_instance_of Hash
|
36
|
+
expect(subject[:text]).to eq("string")
|
37
|
+
expect(subject["string"]).to eq("string key value")
|
37
38
|
expect(subject[:file]).to be_instance_of String
|
38
39
|
expect(subject[:file]).to include "::UploadedFile"
|
40
|
+
expect(subject[:float]).to eq(0.0)
|
41
|
+
expect(subject[:bool_true]).to be(true)
|
42
|
+
expect(subject[:bool_false]).to be(false)
|
43
|
+
expect(subject[:nil]).to be_nil
|
44
|
+
expect(subject[:int]).to eq(1)
|
45
|
+
expect(subject[:int64]).to eq(1 << 64)
|
39
46
|
end
|
40
|
-
it { expect(subject[:float]).to eq(0.0) }
|
41
|
-
it { expect(subject[:bool_true]).to be(true) }
|
42
|
-
it { expect(subject[:bool_false]).to be(false) }
|
43
|
-
it { expect(subject[:nil]).to be_nil }
|
44
|
-
it { expect(subject[:int]).to eq(1) }
|
45
|
-
it { expect(subject[:int64]).to eq(1 << 64) }
|
46
47
|
|
47
48
|
it "does not change the original params" do
|
48
49
|
subject
|
@@ -50,29 +51,34 @@ describe Appsignal::Utils::HashSanitizer do
|
|
50
51
|
expect(params[:hash][:nested_array][2]).to eq(file)
|
51
52
|
end
|
52
53
|
|
53
|
-
describe ":hash" do
|
54
|
+
describe ":hash key" do
|
54
55
|
subject { sanitized_params[:hash] }
|
55
56
|
|
56
|
-
it
|
57
|
-
|
57
|
+
it "returns a sanitized Hash" do
|
58
|
+
expect(subject).to_not eq(params[:hash])
|
59
|
+
is_expected.to be_instance_of Hash
|
60
|
+
expect(subject[:nested_text]).to eq("string")
|
61
|
+
end
|
58
62
|
|
59
|
-
describe ":nested_array" do
|
63
|
+
describe ":nested_array key" do
|
60
64
|
subject { sanitized_params[:hash][:nested_array] }
|
61
65
|
|
62
|
-
it
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
+
it "returns a sanitized Array" do
|
67
|
+
expect(subject).to_not eq(params[:hash][:nested_array])
|
68
|
+
is_expected.to be_instance_of Array
|
69
|
+
expect(subject[0]).to eq("something")
|
70
|
+
expect(subject[1]).to eq("else")
|
66
71
|
expect(subject[2]).to be_instance_of String
|
67
72
|
expect(subject[2]).to include "::UploadedFile"
|
68
73
|
end
|
69
74
|
|
70
|
-
describe ":nested_hash" do
|
75
|
+
describe ":nested_hash key" do
|
71
76
|
subject { sanitized_params[:hash][:nested_array][3] }
|
72
77
|
|
73
|
-
it
|
74
|
-
|
75
|
-
|
78
|
+
it "returns a sanitized Hash" do
|
79
|
+
expect(subject).to_not eq(params[:hash][:nested_array][3])
|
80
|
+
is_expected.to be_instance_of Hash
|
81
|
+
expect(subject[:key]).to eq("value")
|
76
82
|
expect(subject[:file]).to be_instance_of String
|
77
83
|
expect(subject[:file]).to include "::UploadedFile"
|
78
84
|
end
|
@@ -86,17 +92,19 @@ describe Appsignal::Utils::HashSanitizer do
|
|
86
92
|
end
|
87
93
|
subject { sanitized_params }
|
88
94
|
|
89
|
-
it
|
90
|
-
|
91
|
-
|
95
|
+
it "returns a sanitized Hash with the given keys filtered out" do
|
96
|
+
expect(subject).to_not eq(params)
|
97
|
+
expect(subject[:text]).to eq(described_class::FILTERED)
|
98
|
+
expect(subject[:hash]).to eq(described_class::FILTERED)
|
99
|
+
|
92
100
|
expect(subject[:file]).to be_instance_of String
|
93
101
|
expect(subject[:file]).to include "::UploadedFile"
|
102
|
+
expect(subject[:float]).to eq(0.0)
|
103
|
+
expect(subject[:bool_true]).to be(true)
|
104
|
+
expect(subject[:bool_false]).to be(false)
|
105
|
+
expect(subject[:nil]).to be_nil
|
106
|
+
expect(subject[:int]).to eq(1)
|
94
107
|
end
|
95
|
-
it { expect(subject[:float]).to eq(0.0) }
|
96
|
-
it { expect(subject[:bool_true]).to be(true) }
|
97
|
-
it { expect(subject[:bool_false]).to be(false) }
|
98
|
-
it { expect(subject[:nil]).to be_nil }
|
99
|
-
it { expect(subject[:int]).to eq(1) }
|
100
108
|
|
101
109
|
context "with strings as key filter values" do
|
102
110
|
let(:sanitized_params) do
|
@@ -108,7 +116,7 @@ describe Appsignal::Utils::HashSanitizer do
|
|
108
116
|
end
|
109
117
|
end
|
110
118
|
|
111
|
-
describe ":hash" do
|
119
|
+
describe ":hash key" do
|
112
120
|
let(:sanitized_params) do
|
113
121
|
described_class.sanitize(params, %w[nested_text])
|
114
122
|
end
|
@@ -16,10 +16,12 @@ describe Appsignal::Utils::JSON do
|
|
16
16
|
}
|
17
17
|
end
|
18
18
|
|
19
|
-
it
|
19
|
+
it "returns a JSON string" do
|
20
|
+
is_expected.to eq %({"the":"payload","1":true,"":"test","foo":[1,2,"three"],"bar":null,"baz":{"foo":"bar"}})
|
21
|
+
end
|
20
22
|
end
|
21
23
|
|
22
|
-
context "with a body that contains strings with invalid
|
24
|
+
context "with a body that contains strings with invalid UTF-8 content" do
|
23
25
|
let(:string_with_invalid_utf8) { [0x61, 0x61, 0x85].pack("c*") }
|
24
26
|
let(:body) do
|
25
27
|
{
|
@@ -34,7 +36,9 @@ describe Appsignal::Utils::JSON do
|
|
34
36
|
}
|
35
37
|
end
|
36
38
|
|
37
|
-
it
|
39
|
+
it "returns a JSON string with invalid UTF-8 content" do
|
40
|
+
is_expected.to eq %({"field_one":"aa","field_two":"aa�","field_three":["one","aa�"],"field_four":{"one":"aa�"}})
|
41
|
+
end
|
38
42
|
end
|
39
43
|
end
|
40
44
|
end
|
data/spec/lib/appsignal_spec.rb
CHANGED
@@ -90,14 +90,10 @@ describe Appsignal do
|
|
90
90
|
unless Appsignal::System.jruby?
|
91
91
|
it "installs the allocation event hook" do
|
92
92
|
expect(Appsignal::Extension).to receive(:install_allocation_event_hook)
|
93
|
+
.and_call_original
|
93
94
|
Appsignal.start
|
94
95
|
end
|
95
96
|
end
|
96
|
-
|
97
|
-
it "should add the gc probe to minutely" do
|
98
|
-
expect(Appsignal::Minutely).to receive(:add_gc_probe)
|
99
|
-
Appsignal.start
|
100
|
-
end
|
101
97
|
end
|
102
98
|
|
103
99
|
context "when allocation tracking and gc instrumentation have been disabled" do
|
@@ -117,7 +113,7 @@ describe Appsignal do
|
|
117
113
|
end
|
118
114
|
|
119
115
|
it "should not add the gc probe to minutely" do
|
120
|
-
expect(Appsignal::Minutely).not_to receive(:
|
116
|
+
expect(Appsignal::Minutely).not_to receive(:register_garbage_collection_probe)
|
121
117
|
Appsignal.start
|
122
118
|
end
|
123
119
|
end
|
@@ -244,6 +240,16 @@ describe Appsignal do
|
|
244
240
|
|
245
241
|
context "not active" do
|
246
242
|
describe ".monitor_transaction" do
|
243
|
+
let(:log_stream) { StringIO.new }
|
244
|
+
let(:log) { log_contents(log_stream) }
|
245
|
+
before do
|
246
|
+
Appsignal.config = project_fixture_config("not_active")
|
247
|
+
Appsignal.start
|
248
|
+
Appsignal.start_logger
|
249
|
+
Appsignal.logger = test_logger(log_stream)
|
250
|
+
end
|
251
|
+
after { Appsignal.logger = nil }
|
252
|
+
|
247
253
|
it "should do nothing but still yield the block" do
|
248
254
|
expect(Appsignal::Transaction).to_not receive(:create)
|
249
255
|
expect(Appsignal).to_not receive(:instrument)
|
@@ -256,6 +262,23 @@ describe Appsignal do
|
|
256
262
|
end).to eq 1
|
257
263
|
end.to_not raise_error
|
258
264
|
end
|
265
|
+
|
266
|
+
context "with an unknown event type" do
|
267
|
+
it "yields the given block" do
|
268
|
+
expect do |blk|
|
269
|
+
Appsignal.monitor_transaction("unknown.sidekiq", &blk)
|
270
|
+
end.to yield_control
|
271
|
+
end
|
272
|
+
|
273
|
+
it "logs an error" do
|
274
|
+
Appsignal.monitor_transaction("unknown.sidekiq") {}
|
275
|
+
expect(log).to contains_log(
|
276
|
+
:error,
|
277
|
+
"Unrecognized name 'unknown.sidekiq': names must start with either 'perform_job' " \
|
278
|
+
"(for jobs and tasks) or 'process_action' (for HTTP requests)"
|
279
|
+
)
|
280
|
+
end
|
281
|
+
end
|
259
282
|
end
|
260
283
|
|
261
284
|
describe ".listen_for_error" do
|
@@ -303,10 +326,15 @@ describe Appsignal do
|
|
303
326
|
end
|
304
327
|
|
305
328
|
context "with config and started" do
|
329
|
+
let(:log_stream) { StringIO.new }
|
330
|
+
let(:log) { log_contents(log_stream) }
|
306
331
|
before do
|
307
332
|
Appsignal.config = project_fixture_config
|
308
333
|
Appsignal.start
|
334
|
+
Appsignal.start_logger
|
335
|
+
Appsignal.logger = test_logger(log_stream)
|
309
336
|
end
|
337
|
+
after { Appsignal.logger = nil }
|
310
338
|
|
311
339
|
describe ".monitor_transaction" do
|
312
340
|
context "with a successful call" do
|
@@ -363,6 +391,23 @@ describe Appsignal do
|
|
363
391
|
end.to raise_error(error)
|
364
392
|
end
|
365
393
|
end
|
394
|
+
|
395
|
+
context "with an unknown event type" do
|
396
|
+
it "yields the given block" do
|
397
|
+
expect do |blk|
|
398
|
+
Appsignal.monitor_transaction("unknown.sidekiq", &blk)
|
399
|
+
end.to yield_control
|
400
|
+
end
|
401
|
+
|
402
|
+
it "logs an error" do
|
403
|
+
Appsignal.monitor_transaction("unknown.sidekiq") {}
|
404
|
+
expect(log).to contains_log(
|
405
|
+
:error,
|
406
|
+
"Unrecognized name 'unknown.sidekiq': names must start with either 'perform_job' " \
|
407
|
+
"(for jobs and tasks) or 'process_action' (for HTTP requests)"
|
408
|
+
)
|
409
|
+
end
|
410
|
+
end
|
366
411
|
end
|
367
412
|
|
368
413
|
describe ".monitor_single_transaction" do
|
@@ -612,8 +657,10 @@ describe Appsignal do
|
|
612
657
|
let(:error) { double }
|
613
658
|
|
614
659
|
it "logs an error message" do
|
615
|
-
expect(Appsignal.logger).to receive(:error)
|
616
|
-
.
|
660
|
+
expect(Appsignal.logger).to receive(:error).with(
|
661
|
+
"Appsignal.send_error: Cannot send error. " \
|
662
|
+
"The given value is not an exception: #{error.inspect}"
|
663
|
+
)
|
617
664
|
end
|
618
665
|
|
619
666
|
it "does not send the error" do
|
@@ -650,6 +697,29 @@ describe Appsignal do
|
|
650
697
|
|
651
698
|
after { Appsignal.send_error(error, nil, namespace) }
|
652
699
|
end
|
700
|
+
|
701
|
+
context "when given a block" do
|
702
|
+
it "yields the transaction and allows additional metadata to be set" do
|
703
|
+
captured_transaction = nil
|
704
|
+
Appsignal.send_error(StandardError.new("my_error")) do |transaction|
|
705
|
+
captured_transaction = transaction
|
706
|
+
transaction.set_action("my_action")
|
707
|
+
transaction.set_namespace("my_namespace")
|
708
|
+
|
709
|
+
# Don't flush the transaction, so we can inspect it
|
710
|
+
expect(transaction).to receive(:complete)
|
711
|
+
end
|
712
|
+
expect(captured_transaction.to_h).to include(
|
713
|
+
"namespace" => "my_namespace",
|
714
|
+
"action" => "my_action",
|
715
|
+
"error" => {
|
716
|
+
"name" => "StandardError",
|
717
|
+
"message" => "my_error",
|
718
|
+
"backtrace" => kind_of(String) # TODO: should be Array
|
719
|
+
}
|
720
|
+
)
|
721
|
+
end
|
722
|
+
end
|
653
723
|
end
|
654
724
|
|
655
725
|
describe ".listen_for_error" do
|
@@ -710,13 +780,19 @@ describe Appsignal do
|
|
710
780
|
Appsignal.set_error(error)
|
711
781
|
end
|
712
782
|
|
713
|
-
context "when the error is
|
714
|
-
|
783
|
+
context "when the error is not an Exception" do
|
784
|
+
let(:error) { Object.new }
|
785
|
+
|
786
|
+
it "logs an error" do
|
787
|
+
expect(Appsignal.logger).to receive(:error).with(
|
788
|
+
"Appsignal.set_error: Cannot set error. " \
|
789
|
+
"The given value is not an exception: #{error.inspect}"
|
790
|
+
)
|
715
791
|
expect(transaction).to_not receive(:set_error)
|
716
792
|
expect(transaction).to_not receive(:set_tags)
|
717
793
|
expect(transaction).to_not receive(:set_namespace)
|
718
794
|
|
719
|
-
Appsignal.set_error(
|
795
|
+
Appsignal.set_error(error)
|
720
796
|
end
|
721
797
|
end
|
722
798
|
|
@@ -831,25 +907,25 @@ describe Appsignal do
|
|
831
907
|
end
|
832
908
|
|
833
909
|
describe ".without_instrumentation" do
|
834
|
-
let(:transaction) {
|
910
|
+
let(:transaction) { http_request_transaction }
|
835
911
|
before { allow(Appsignal::Transaction).to receive(:current).and_return(transaction) }
|
836
912
|
|
837
|
-
it "
|
838
|
-
expect(transaction).to receive(:pause!)
|
839
|
-
expect(transaction).to receive(:resume!)
|
913
|
+
it "does not record events on the transaction" do
|
914
|
+
expect(transaction).to receive(:pause!).and_call_original
|
915
|
+
expect(transaction).to receive(:resume!).and_call_original
|
916
|
+
Appsignal.instrument("register.this.event") { :do_nothing }
|
917
|
+
Appsignal.without_instrumentation do
|
918
|
+
Appsignal.instrument("dont.register.this.event") { :do_nothing }
|
919
|
+
end
|
920
|
+
expect(transaction.to_h["events"].map { |e| e["name"] })
|
921
|
+
.to match_array("register.this.event")
|
840
922
|
end
|
841
923
|
|
842
924
|
context "without transaction" do
|
843
925
|
let(:transaction) { nil }
|
844
926
|
|
845
927
|
it "should not crash" do
|
846
|
-
|
847
|
-
end
|
848
|
-
end
|
849
|
-
|
850
|
-
after do
|
851
|
-
Appsignal.without_instrumentation do
|
852
|
-
# nothing
|
928
|
+
Appsignal.without_instrumentation { :do_nothing }
|
853
929
|
end
|
854
930
|
end
|
855
931
|
end
|