appsignal 3.9.2-java → 3.9.3-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/.github/workflows/ci.yml +3135 -0
- data/.rubocop.yml +28 -20
- data/.rubocop_todo.yml +7 -33
- data/CHANGELOG.md +38 -0
- data/Rakefile +79 -64
- data/appsignal.gemspec +1 -1
- data/build_matrix.yml +109 -179
- data/ext/base.rb +1 -1
- data/gemfiles/hanami-2.1.gemfile +7 -0
- data/lib/appsignal/cli/diagnose.rb +1 -1
- data/lib/appsignal/config.rb +1 -1
- data/lib/appsignal/demo.rb +0 -1
- data/lib/appsignal/environment.rb +5 -1
- data/lib/appsignal/extension/jruby.rb +1 -1
- data/lib/appsignal/helpers/instrumentation.rb +1 -1
- data/lib/appsignal/integrations/grape.rb +19 -47
- data/lib/appsignal/integrations/hanami.rb +8 -7
- data/lib/appsignal/integrations/padrino.rb +46 -43
- data/lib/appsignal/integrations/railtie.rb +0 -3
- data/lib/appsignal/integrations/sinatra.rb +0 -1
- data/lib/appsignal/probes/gvl.rb +24 -2
- data/lib/appsignal/probes/sidekiq.rb +1 -1
- data/lib/appsignal/probes.rb +1 -1
- data/lib/appsignal/rack/abstract_middleware.rb +62 -28
- data/lib/appsignal/rack/event_handler.rb +12 -3
- data/lib/appsignal/rack/grape_middleware.rb +40 -0
- data/lib/appsignal/rack/hanami_middleware.rb +1 -11
- data/lib/appsignal/rack/rails_instrumentation.rb +14 -55
- data/lib/appsignal/utils/integration_memory_logger.rb +78 -0
- data/lib/appsignal/utils.rb +1 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +34 -33
- data/spec/.rubocop.yml +1 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +1 -1
- data/spec/lib/appsignal/cli/install_spec.rb +3 -3
- data/spec/lib/appsignal/config_spec.rb +7 -5
- data/spec/lib/appsignal/demo_spec.rb +38 -41
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +86 -167
- data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +8 -20
- data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +38 -84
- data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +16 -37
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +4 -4
- data/spec/lib/appsignal/hooks/activejob_spec.rb +111 -200
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +54 -91
- data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +14 -32
- data/spec/lib/appsignal/hooks/excon_spec.rb +8 -12
- data/spec/lib/appsignal/hooks/net_http_spec.rb +7 -42
- data/spec/lib/appsignal/hooks/rake_spec.rb +9 -19
- data/spec/lib/appsignal/hooks/redis_client_spec.rb +18 -30
- data/spec/lib/appsignal/hooks/redis_spec.rb +10 -16
- data/spec/lib/appsignal/hooks/resque_spec.rb +42 -62
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +33 -74
- data/spec/lib/appsignal/integrations/hanami_spec.rb +79 -21
- data/spec/lib/appsignal/integrations/http_spec.rb +12 -20
- data/spec/lib/appsignal/integrations/net_http_spec.rb +33 -0
- data/spec/lib/appsignal/integrations/object_spec.rb +29 -36
- data/spec/lib/appsignal/integrations/padrino_spec.rb +47 -70
- data/spec/lib/appsignal/integrations/que_spec.rb +43 -70
- data/spec/lib/appsignal/integrations/railtie_spec.rb +26 -67
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +86 -160
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -1
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +28 -39
- data/spec/lib/appsignal/probes/gvl_spec.rb +80 -3
- data/spec/lib/appsignal/probes_spec.rb +7 -4
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +215 -106
- data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -78
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +2 -12
- data/spec/lib/appsignal/rack/grape_middleware_spec.rb +234 -0
- data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +2 -16
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +67 -131
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +36 -44
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +68 -86
- data/spec/lib/appsignal/transaction_spec.rb +76 -90
- data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +163 -0
- data/spec/lib/appsignal_spec.rb +363 -342
- data/spec/support/helpers/dependency_helper.rb +6 -1
- data/spec/support/helpers/std_streams_helper.rb +1 -1
- data/spec/support/helpers/transaction_helpers.rb +8 -0
- data/spec/support/matchers/transaction.rb +185 -0
- data/spec/support/mocks/dummy_app.rb +20 -0
- data/spec/support/shared_examples/instrument.rb +17 -12
- data/spec/support/testing.rb +18 -9
- metadata +15 -10
- data/.semaphore/semaphore.yml +0 -2347
- data/script/lint_git +0 -22
- data/spec/lib/appsignal/integrations/grape_spec.rb +0 -239
- data/spec/support/matchers/be_completed.rb +0 -5
- /data/gemfiles/{hanami.gemfile → hanami-2.0.gemfile} +0 -0
|
@@ -3,11 +3,6 @@ if DependencyHelper.rails_present?
|
|
|
3
3
|
class MockController; end
|
|
4
4
|
|
|
5
5
|
let(:log) { StringIO.new }
|
|
6
|
-
before do
|
|
7
|
-
start_agent
|
|
8
|
-
Appsignal.internal_logger = test_logger(log)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
6
|
let(:transaction) do
|
|
12
7
|
Appsignal::Transaction.new(
|
|
13
8
|
"transaction_id",
|
|
@@ -15,7 +10,7 @@ if DependencyHelper.rails_present?
|
|
|
15
10
|
Rack::Request.new(env)
|
|
16
11
|
)
|
|
17
12
|
end
|
|
18
|
-
let(:app) {
|
|
13
|
+
let(:app) { DummyApp.new }
|
|
19
14
|
let(:params) do
|
|
20
15
|
{
|
|
21
16
|
"controller" => "blog_posts",
|
|
@@ -25,9 +20,8 @@ if DependencyHelper.rails_present?
|
|
|
25
20
|
"password" => "super secret"
|
|
26
21
|
}
|
|
27
22
|
end
|
|
28
|
-
let(:env_extra) { {} }
|
|
29
23
|
let(:env) do
|
|
30
|
-
http_request_env_with_data(
|
|
24
|
+
http_request_env_with_data(
|
|
31
25
|
:params => params,
|
|
32
26
|
:with_queue_start => true,
|
|
33
27
|
"action_dispatch.request_id" => "request_id123",
|
|
@@ -36,160 +30,102 @@ if DependencyHelper.rails_present?
|
|
|
36
30
|
:class => MockController,
|
|
37
31
|
:action_name => "index"
|
|
38
32
|
)
|
|
39
|
-
|
|
33
|
+
)
|
|
40
34
|
end
|
|
41
35
|
let(:middleware) { Appsignal::Rack::RailsInstrumentation.new(app, {}) }
|
|
42
36
|
around { |example| keep_transactions { example.run } }
|
|
43
37
|
before do
|
|
38
|
+
start_agent
|
|
39
|
+
Appsignal.internal_logger = test_logger(log)
|
|
44
40
|
env[Appsignal::Rack::APPSIGNAL_TRANSACTION] = transaction
|
|
45
41
|
end
|
|
46
42
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
context "when appsignal is active" do
|
|
53
|
-
before { allow(Appsignal).to receive(:active?).and_return(true) }
|
|
54
|
-
|
|
55
|
-
it "calls with monitoring" do
|
|
56
|
-
expect(middleware).to receive(:call_with_appsignal_monitoring).with(env)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
43
|
+
def make_request
|
|
44
|
+
middleware.call(env)
|
|
45
|
+
last_transaction&._sample
|
|
46
|
+
end
|
|
59
47
|
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
def make_request_with_error(error_class, error_message)
|
|
49
|
+
expect { make_request }.to raise_error(error_class, error_message)
|
|
50
|
+
end
|
|
62
51
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
end
|
|
52
|
+
context "with a request that doesn't raise an error" do
|
|
53
|
+
before { make_request }
|
|
66
54
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
end
|
|
55
|
+
it "calls the next middleware in the stack" do
|
|
56
|
+
expect(app).to be_called
|
|
70
57
|
end
|
|
71
58
|
|
|
72
|
-
|
|
59
|
+
it "does not instrument an event" do
|
|
60
|
+
expect(last_transaction).to_not include_events
|
|
61
|
+
end
|
|
73
62
|
end
|
|
74
63
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
context "with a request that raises an error" do
|
|
65
|
+
let(:app) do
|
|
66
|
+
DummyApp.new { |_env| raise ExampleException, "error message" }
|
|
67
|
+
end
|
|
68
|
+
before do
|
|
69
|
+
make_request_with_error(ExampleException, "error message")
|
|
79
70
|
end
|
|
80
71
|
|
|
81
|
-
it "calls the
|
|
82
|
-
expect
|
|
83
|
-
expect(app).to have_received(:call).with(env)
|
|
72
|
+
it "calls the next middleware in the stack" do
|
|
73
|
+
expect(app).to be_called
|
|
84
74
|
end
|
|
85
75
|
|
|
86
|
-
it "
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
expect(last_transaction.to_h).to include(
|
|
90
|
-
"namespace" => Appsignal::Transaction::HTTP_REQUEST,
|
|
91
|
-
"action" => "MockController#index",
|
|
92
|
-
"metadata" => hash_including(
|
|
93
|
-
"method" => "GET",
|
|
94
|
-
"path" => "/blog"
|
|
95
|
-
),
|
|
96
|
-
"sample_data" => hash_including(
|
|
97
|
-
"tags" => { "request_id" => "request_id123" }
|
|
98
|
-
)
|
|
99
|
-
)
|
|
76
|
+
it "reports the error on the transaction" do
|
|
77
|
+
expect(last_transaction).to have_error("ExampleException", "error message")
|
|
100
78
|
end
|
|
79
|
+
end
|
|
101
80
|
|
|
102
|
-
|
|
103
|
-
|
|
81
|
+
it "sets the controller action as the action name" do
|
|
82
|
+
make_request
|
|
104
83
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
"my_custom_param" => "[FILTERED]",
|
|
109
|
-
"password" => "[FILTERED]"
|
|
110
|
-
)
|
|
111
|
-
)
|
|
112
|
-
)
|
|
113
|
-
end
|
|
84
|
+
expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
85
|
+
expect(last_transaction).to have_action("MockController#index")
|
|
86
|
+
end
|
|
114
87
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
lambda do |env|
|
|
118
|
-
env[Appsignal::Rack::APPSIGNAL_TRANSACTION].set_params("custom_param" => "yes")
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
it "allows custom params to be set" do
|
|
123
|
-
run
|
|
124
|
-
|
|
125
|
-
expect(last_transaction.to_h).to include(
|
|
126
|
-
"sample_data" => hash_including(
|
|
127
|
-
"params" => {
|
|
128
|
-
"custom_param" => "yes"
|
|
129
|
-
}
|
|
130
|
-
)
|
|
131
|
-
)
|
|
132
|
-
end
|
|
133
|
-
end
|
|
88
|
+
it "sets request metadata on the transaction" do
|
|
89
|
+
make_request
|
|
134
90
|
|
|
135
|
-
|
|
136
|
-
|
|
91
|
+
expect(last_transaction).to include_metadata(
|
|
92
|
+
"method" => "GET",
|
|
93
|
+
"path" => "/blog"
|
|
94
|
+
)
|
|
95
|
+
expect(last_transaction).to include_tags("request_id" => "request_id123")
|
|
96
|
+
end
|
|
137
97
|
|
|
138
|
-
|
|
139
|
-
|
|
98
|
+
it "reports Rails filter parameters" do
|
|
99
|
+
make_request
|
|
140
100
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
101
|
+
expect(last_transaction).to include_params(
|
|
102
|
+
"controller" => "blog_posts",
|
|
103
|
+
"action" => "show",
|
|
104
|
+
"id" => "1",
|
|
105
|
+
"my_custom_param" => "[FILTERED]",
|
|
106
|
+
"password" => "[FILTERED]"
|
|
107
|
+
)
|
|
108
|
+
end
|
|
147
109
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
it "records the exception" do
|
|
157
|
-
expect { run }.to raise_error(error)
|
|
158
|
-
|
|
159
|
-
transaction_hash = last_transaction.to_h
|
|
160
|
-
expect(transaction_hash["error"]).to include(
|
|
161
|
-
"name" => "ExampleException",
|
|
162
|
-
"message" => "ExampleException message",
|
|
163
|
-
"backtrace" => kind_of(String)
|
|
164
|
-
)
|
|
165
|
-
end
|
|
166
|
-
end
|
|
110
|
+
context "with an invalid HTTP request method" do
|
|
111
|
+
it "does not store the invalid HTTP request method" do
|
|
112
|
+
env[:request_method] = "FOO"
|
|
113
|
+
env["REQUEST_METHOD"] = "FOO"
|
|
114
|
+
make_request
|
|
167
115
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
:path => "/unknown-route",
|
|
172
|
-
"action_controller.instance" => nil
|
|
173
|
-
}
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
it "doesn't set an action name" do
|
|
177
|
-
run
|
|
178
|
-
|
|
179
|
-
expect(last_transaction.to_h).to include(
|
|
180
|
-
"action" => nil
|
|
181
|
-
)
|
|
182
|
-
end
|
|
116
|
+
expect(last_transaction).to_not include_metadata("method" => anything)
|
|
117
|
+
expect(log_contents(log))
|
|
118
|
+
.to contains_log(:error, "Unable to report HTTP request method: '")
|
|
183
119
|
end
|
|
184
120
|
end
|
|
185
121
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
122
|
+
context "with a request path that's not a route" do
|
|
123
|
+
it "doesn't set an action name" do
|
|
124
|
+
env[:path] = "/unknown-route"
|
|
125
|
+
env["action_controller.instance"] = nil
|
|
126
|
+
make_request
|
|
190
127
|
|
|
191
|
-
|
|
192
|
-
is_expected.to eq "id"
|
|
128
|
+
expect(last_transaction).to_not have_action
|
|
193
129
|
end
|
|
194
130
|
end
|
|
195
131
|
end
|
|
@@ -2,11 +2,11 @@ if DependencyHelper.sinatra_present?
|
|
|
2
2
|
require "appsignal/integrations/sinatra"
|
|
3
3
|
|
|
4
4
|
module SinatraRequestHelpers
|
|
5
|
-
def make_request
|
|
5
|
+
def make_request
|
|
6
6
|
middleware.call(env)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def make_request_with_error(
|
|
9
|
+
def make_request_with_error(error)
|
|
10
10
|
expect { middleware.call(env) }.to raise_error(error)
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -30,7 +30,7 @@ if DependencyHelper.sinatra_present?
|
|
|
30
30
|
before { allow(middleware).to receive(:raw_payload).and_return({}) }
|
|
31
31
|
|
|
32
32
|
it "doesn't instrument requests" do
|
|
33
|
-
expect { make_request
|
|
33
|
+
expect { make_request }.to_not(change { created_transactions.count })
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -100,54 +100,48 @@ if DependencyHelper.sinatra_present?
|
|
|
100
100
|
before { allow(Appsignal).to receive(:active?).and_return(false) }
|
|
101
101
|
|
|
102
102
|
it "does not instrument requests" do
|
|
103
|
-
expect { make_request
|
|
103
|
+
expect { make_request }.to_not(change { created_transactions.count })
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
it "calls the next middleware in the stack" do
|
|
107
|
-
make_request
|
|
107
|
+
make_request
|
|
108
108
|
|
|
109
109
|
expect(app).to have_received(:call).with(env)
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
context "when appsignal is active" do
|
|
114
|
-
context "without an
|
|
114
|
+
context "without an error" do
|
|
115
|
+
it "creates a transaction for the request" do
|
|
116
|
+
expect { make_request }.to(change { created_transactions.count }.by(1))
|
|
117
|
+
|
|
118
|
+
expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
119
|
+
end
|
|
120
|
+
|
|
115
121
|
it "reports a process_action.sinatra event" do
|
|
116
|
-
make_request
|
|
117
|
-
|
|
118
|
-
expect(last_transaction
|
|
119
|
-
"events" => [
|
|
120
|
-
hash_including(
|
|
121
|
-
"body" => "",
|
|
122
|
-
"body_format" => Appsignal::EventFormatter::DEFAULT,
|
|
123
|
-
"count" => 1,
|
|
124
|
-
"name" => "process_action.sinatra",
|
|
125
|
-
"title" => ""
|
|
126
|
-
)
|
|
127
|
-
]
|
|
128
|
-
)
|
|
122
|
+
make_request
|
|
123
|
+
|
|
124
|
+
expect(last_transaction).to include_event("name" => "process_action.sinatra")
|
|
129
125
|
end
|
|
130
126
|
end
|
|
131
127
|
|
|
132
128
|
context "with an error in sinatra.error" do
|
|
133
129
|
let(:error) { ExampleException.new("error message") }
|
|
134
|
-
before
|
|
135
|
-
|
|
130
|
+
before { env["sinatra.error"] = error }
|
|
131
|
+
|
|
132
|
+
it "creates a transaction for the request" do
|
|
133
|
+
expect { make_request }.to(change { created_transactions.count }.by(1))
|
|
134
|
+
|
|
135
|
+
expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
136
136
|
end
|
|
137
137
|
|
|
138
138
|
context "when raise_errors is off" do
|
|
139
139
|
let(:settings) { double(:raise_errors => false) }
|
|
140
140
|
|
|
141
|
-
it "
|
|
142
|
-
|
|
143
|
-
.to(change { created_transactions.count }.by(1))
|
|
141
|
+
it "records the error" do
|
|
142
|
+
make_request
|
|
144
143
|
|
|
145
|
-
expect(last_transaction
|
|
146
|
-
"error" => hash_including(
|
|
147
|
-
"name" => "ExampleException",
|
|
148
|
-
"message" => "error message"
|
|
149
|
-
)
|
|
150
|
-
)
|
|
144
|
+
expect(last_transaction).to have_error("ExampleException", "error message")
|
|
151
145
|
end
|
|
152
146
|
end
|
|
153
147
|
|
|
@@ -155,10 +149,9 @@ if DependencyHelper.sinatra_present?
|
|
|
155
149
|
let(:settings) { double(:raise_errors => true) }
|
|
156
150
|
|
|
157
151
|
it "does not record the error" do
|
|
158
|
-
|
|
159
|
-
.to(change { created_transactions.count }.by(1))
|
|
152
|
+
make_request
|
|
160
153
|
|
|
161
|
-
expect(last_transaction
|
|
154
|
+
expect(last_transaction).to_not have_error
|
|
162
155
|
end
|
|
163
156
|
end
|
|
164
157
|
|
|
@@ -171,19 +164,18 @@ if DependencyHelper.sinatra_present?
|
|
|
171
164
|
end
|
|
172
165
|
|
|
173
166
|
it "does not record the error" do
|
|
174
|
-
|
|
175
|
-
.to(change { created_transactions.count }.by(1))
|
|
167
|
+
make_request
|
|
176
168
|
|
|
177
|
-
expect(last_transaction
|
|
169
|
+
expect(last_transaction).to_not have_error
|
|
178
170
|
end
|
|
179
171
|
end
|
|
180
172
|
end
|
|
181
173
|
|
|
182
174
|
describe "action name" do
|
|
183
175
|
it "sets the action to the request method and path" do
|
|
184
|
-
make_request
|
|
176
|
+
make_request
|
|
185
177
|
|
|
186
|
-
expect(last_transaction
|
|
178
|
+
expect(last_transaction).to have_action("GET /path")
|
|
187
179
|
end
|
|
188
180
|
|
|
189
181
|
context "without 'sinatra.route' env" do
|
|
@@ -192,9 +184,9 @@ if DependencyHelper.sinatra_present?
|
|
|
192
184
|
end
|
|
193
185
|
|
|
194
186
|
it "doesn't set an action name" do
|
|
195
|
-
make_request
|
|
187
|
+
make_request
|
|
196
188
|
|
|
197
|
-
expect(last_transaction
|
|
189
|
+
expect(last_transaction).to_not have_action
|
|
198
190
|
end
|
|
199
191
|
end
|
|
200
192
|
|
|
@@ -202,9 +194,9 @@ if DependencyHelper.sinatra_present?
|
|
|
202
194
|
before { env["SCRIPT_NAME"] = "/api" }
|
|
203
195
|
|
|
204
196
|
it "sets the action name with an application prefix path" do
|
|
205
|
-
make_request
|
|
197
|
+
make_request
|
|
206
198
|
|
|
207
|
-
expect(last_transaction
|
|
199
|
+
expect(last_transaction).to have_action("GET /api/path")
|
|
208
200
|
end
|
|
209
201
|
|
|
210
202
|
context "without 'sinatra.route' env" do
|
|
@@ -213,9 +205,9 @@ if DependencyHelper.sinatra_present?
|
|
|
213
205
|
end
|
|
214
206
|
|
|
215
207
|
it "doesn't set an action name" do
|
|
216
|
-
make_request
|
|
208
|
+
make_request
|
|
217
209
|
|
|
218
|
-
expect(last_transaction
|
|
210
|
+
expect(last_transaction).to_not have_action
|
|
219
211
|
end
|
|
220
212
|
end
|
|
221
213
|
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
require "appsignal/rack/streaming_listener"
|
|
2
2
|
|
|
3
3
|
describe Appsignal::Rack::StreamingListener do
|
|
4
|
-
before(:context) { start_agent }
|
|
5
|
-
let(:headers) { {} }
|
|
6
4
|
let(:env) do
|
|
7
5
|
{
|
|
8
6
|
"rack.input" => StringIO.new,
|
|
@@ -11,114 +9,96 @@ describe Appsignal::Rack::StreamingListener do
|
|
|
11
9
|
"QUERY_STRING" => "param=something"
|
|
12
10
|
}
|
|
13
11
|
end
|
|
14
|
-
let(:app)
|
|
12
|
+
let(:app) { DummyApp.new }
|
|
15
13
|
let(:listener) { Appsignal::Rack::StreamingListener.new(app, {}) }
|
|
14
|
+
before(:context) { start_agent }
|
|
15
|
+
around { |example| keep_transactions { example.run } }
|
|
16
16
|
|
|
17
17
|
describe "#call" do
|
|
18
|
-
context "when Appsignal is active" do
|
|
19
|
-
before { allow(Appsignal).to receive(:active?).and_return(true) }
|
|
20
|
-
|
|
21
|
-
it "should call `call_with_appsignal_monitoring`" do
|
|
22
|
-
expect(listener).to receive(:call_with_appsignal_monitoring)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
18
|
context "when Appsignal is not active" do
|
|
27
19
|
before { allow(Appsignal).to receive(:active?).and_return(false) }
|
|
28
20
|
|
|
29
|
-
it "
|
|
30
|
-
expect
|
|
21
|
+
it "does not create a transaction" do
|
|
22
|
+
expect do
|
|
23
|
+
listener.call(env)
|
|
24
|
+
end.to_not(change { created_transactions.count })
|
|
31
25
|
end
|
|
32
|
-
end
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
describe "#call_with_appsignal_monitoring" do
|
|
38
|
-
let!(:transaction) do
|
|
39
|
-
Appsignal::Transaction.create(
|
|
40
|
-
SecureRandom.uuid,
|
|
41
|
-
Appsignal::Transaction::HTTP_REQUEST,
|
|
42
|
-
::Rack::Request.new(env)
|
|
43
|
-
)
|
|
44
|
-
end
|
|
45
|
-
let(:wrapper) { Appsignal::StreamWrapper.new("body", transaction) }
|
|
46
|
-
let(:raw_payload) { { :foo => :bar } }
|
|
47
|
-
|
|
48
|
-
before do
|
|
49
|
-
allow(SecureRandom).to receive(:uuid).and_return("123")
|
|
50
|
-
allow(listener).to receive(:raw_payload).and_return(raw_payload)
|
|
51
|
-
allow(Appsignal::Transaction).to receive(:create).and_return(transaction)
|
|
52
|
-
end
|
|
27
|
+
it "calls the app" do
|
|
28
|
+
listener.call(env)
|
|
53
29
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
.with("123", Appsignal::Transaction::HTTP_REQUEST, instance_of(Rack::Request))
|
|
57
|
-
.and_return(transaction)
|
|
58
|
-
|
|
59
|
-
listener.call_with_appsignal_monitoring(env)
|
|
30
|
+
expect(app).to be_called
|
|
31
|
+
end
|
|
60
32
|
end
|
|
61
33
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.with("process_action.rack")
|
|
65
|
-
.and_yield
|
|
34
|
+
context "when Appsignal is active" do
|
|
35
|
+
before { allow(Appsignal).to receive(:active?).and_return(true) }
|
|
66
36
|
|
|
67
|
-
|
|
68
|
-
|
|
37
|
+
let(:wrapper) { Appsignal::StreamWrapper.new("body", transaction) }
|
|
38
|
+
let(:raw_payload) { { :foo => :bar } }
|
|
39
|
+
before { allow(listener).to receive(:raw_payload).and_return(raw_payload) }
|
|
69
40
|
|
|
70
|
-
|
|
71
|
-
|
|
41
|
+
it "creates a transaction" do
|
|
42
|
+
expect do
|
|
43
|
+
listener.call(env)
|
|
44
|
+
end.to(change { created_transactions.count }.by(1))
|
|
45
|
+
end
|
|
72
46
|
|
|
73
|
-
|
|
47
|
+
it "instruments the call" do
|
|
48
|
+
listener.call(env)
|
|
74
49
|
|
|
75
|
-
|
|
50
|
+
expect(last_transaction).to include_event("name" => "process_action.rack")
|
|
51
|
+
end
|
|
76
52
|
|
|
77
|
-
|
|
78
|
-
|
|
53
|
+
it "set `appsignal.action` to the action name" do
|
|
54
|
+
env["appsignal.action"] = "Action"
|
|
79
55
|
|
|
80
|
-
|
|
81
|
-
allow(Appsignal).to receive(:instrument).and_yield
|
|
56
|
+
listener.call(env)
|
|
82
57
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
expect(transaction).to receive(:set_http_or_background_queue_start)
|
|
58
|
+
expect(last_transaction).to have_action("Action")
|
|
59
|
+
end
|
|
86
60
|
|
|
87
|
-
|
|
88
|
-
|
|
61
|
+
it "adds the path, method and queue start to the transaction" do
|
|
62
|
+
listener.call(env)
|
|
89
63
|
|
|
90
|
-
|
|
91
|
-
|
|
64
|
+
expect(last_transaction).to include_metadata(
|
|
65
|
+
"path" => "/homepage",
|
|
66
|
+
"method" => "GET"
|
|
67
|
+
)
|
|
68
|
+
expect(last_transaction).to have_queue_start
|
|
69
|
+
end
|
|
92
70
|
|
|
93
|
-
|
|
94
|
-
|
|
71
|
+
context "with an exception in the instrumentation call" do
|
|
72
|
+
let(:error) { ExampleException.new("error message") }
|
|
73
|
+
let(:app) { DummyApp.new { raise error } }
|
|
95
74
|
|
|
96
|
-
|
|
75
|
+
it "adds the exception to the transaction" do
|
|
76
|
+
expect do
|
|
77
|
+
listener.call(env)
|
|
78
|
+
end.to raise_error(error)
|
|
97
79
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
end.to raise_error(error)
|
|
80
|
+
expect(last_transaction).to have_error("ExampleException", "error message")
|
|
81
|
+
end
|
|
101
82
|
end
|
|
102
|
-
end
|
|
103
83
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
.with("body", transaction)
|
|
107
|
-
.and_return(wrapper)
|
|
84
|
+
it "wraps the body in a wrapper" do
|
|
85
|
+
_, _, body = listener.call(env)
|
|
108
86
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
expect(body).to be_a(Appsignal::StreamWrapper)
|
|
87
|
+
expect(body).to be_a(Appsignal::StreamWrapper)
|
|
88
|
+
end
|
|
112
89
|
end
|
|
113
90
|
end
|
|
114
91
|
end
|
|
115
92
|
|
|
116
93
|
describe Appsignal::StreamWrapper do
|
|
117
|
-
let(:stream)
|
|
118
|
-
let(:transaction)
|
|
119
|
-
Appsignal::Transaction.create(SecureRandom.uuid, Appsignal::Transaction::HTTP_REQUEST, {})
|
|
120
|
-
end
|
|
94
|
+
let(:stream) { double }
|
|
95
|
+
let(:transaction) { http_request_transaction }
|
|
121
96
|
let(:wrapper) { Appsignal::StreamWrapper.new(stream, transaction) }
|
|
97
|
+
before do
|
|
98
|
+
start_agent
|
|
99
|
+
set_current_transaction(transaction)
|
|
100
|
+
end
|
|
101
|
+
around { |example| keep_transactions { example.run } }
|
|
122
102
|
|
|
123
103
|
describe "#each" do
|
|
124
104
|
it "calls the original stream" do
|
|
@@ -128,14 +108,14 @@ describe Appsignal::StreamWrapper do
|
|
|
128
108
|
end
|
|
129
109
|
|
|
130
110
|
context "when #each raises an error" do
|
|
131
|
-
let(:error) { ExampleException }
|
|
111
|
+
let(:error) { ExampleException.new("error message") }
|
|
132
112
|
|
|
133
113
|
it "records the exception" do
|
|
134
114
|
allow(stream).to receive(:each).and_raise(error)
|
|
135
115
|
|
|
136
|
-
expect(transaction).to receive(:set_error).with(error)
|
|
137
|
-
|
|
138
116
|
expect { wrapper.send(:each) }.to raise_error(error)
|
|
117
|
+
|
|
118
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
|
139
119
|
end
|
|
140
120
|
end
|
|
141
121
|
end
|
|
@@ -143,21 +123,23 @@ describe Appsignal::StreamWrapper do
|
|
|
143
123
|
describe "#close" do
|
|
144
124
|
it "closes the original stream and completes the transaction" do
|
|
145
125
|
expect(stream).to receive(:close)
|
|
146
|
-
expect(Appsignal::Transaction).to receive(:complete_current!)
|
|
147
126
|
|
|
148
127
|
wrapper.close
|
|
128
|
+
|
|
129
|
+
expect(current_transaction?).to be_falsy
|
|
130
|
+
expect(transaction).to be_completed
|
|
149
131
|
end
|
|
150
132
|
|
|
151
133
|
context "when #close raises an error" do
|
|
152
|
-
let(:error) { ExampleException }
|
|
134
|
+
let(:error) { ExampleException.new("error message") }
|
|
153
135
|
|
|
154
136
|
it "records the exception and completes the transaction" do
|
|
155
137
|
allow(stream).to receive(:close).and_raise(error)
|
|
156
138
|
|
|
157
|
-
expect(transaction).to receive(:set_error).with(error)
|
|
158
|
-
expect(transaction).to receive(:complete)
|
|
159
|
-
|
|
160
139
|
expect { wrapper.send(:close) }.to raise_error(error)
|
|
140
|
+
|
|
141
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
|
142
|
+
expect(transaction).to be_completed
|
|
161
143
|
end
|
|
162
144
|
end
|
|
163
145
|
end
|