appsignal 3.9.1 → 3.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/lib/appsignal/helpers/instrumentation.rb +2 -2
- data/lib/appsignal/hooks/active_job.rb +2 -1
- data/lib/appsignal/integrations/action_cable.rb +1 -1
- data/lib/appsignal/integrations/hanami.rb +19 -34
- data/lib/appsignal/integrations/railtie.rb +1 -1
- data/lib/appsignal/integrations/resque.rb +1 -1
- data/lib/appsignal/integrations/sidekiq.rb +2 -4
- data/lib/appsignal/integrations/sinatra.rb +7 -1
- data/lib/appsignal/rack/event_handler.rb +28 -26
- data/lib/appsignal/rack/hanami_middleware.rb +30 -0
- data/lib/appsignal/rack/rails_instrumentation.rb +1 -2
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/integrations/hanami_spec.rb +66 -62
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +8 -2
- data/spec/lib/appsignal/rack/event_handler_spec.rb +83 -4
- data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +50 -0
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +1 -1
- data/spec/lib/appsignal/transaction_spec.rb +3 -3
- data/spec/support/hanami/hanami_app.rb +1 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f8a64513e6bab13284c0032189a16d58cbd6188fc2cd1a43e583bf91744f428
|
4
|
+
data.tar.gz: e604b5e5acd710f2978579db85b3e274461d4c2c3b68065c9e4541b2a7f4b133
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7afd7fe460f8d86355d5f3b143bb8c81967cc172d46f1cba801041c64773510b3d6a30c4c106f438c982c291b44720a3760859c978d47958331be67712a974c8
|
7
|
+
data.tar.gz: ce4f0c6fdd313528c2b91ad3b0c4c50f3e05bb93b56d2f2a983da830ff4a0dfa8a1184ce6b8cad0c20091b7e1d07dedea4f259f8e528ecc86295b8ea3a375e0b
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# AppSignal for Ruby gem Changelog
|
2
2
|
|
3
|
+
## 3.9.2
|
4
|
+
|
5
|
+
_Published on 2024-06-26._
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- Improve instrumentation of Hanami requests by making sure the transaction is always closed.
|
10
|
+
It will also report a `response_status` tag and metric for Hanami requests.
|
11
|
+
|
12
|
+
(patch [e79d4277](https://github.com/appsignal/appsignal-ruby/commit/e79d4277046bf4ec0d32263d06d4975ca8c426ee))
|
13
|
+
|
14
|
+
### Changed
|
15
|
+
|
16
|
+
- Instrument the entire Sinatra request. Instrumenting Sinatra apps using `require "appsignal/integrations/sinatra"` will now report more of the request, if previously other middleware were not instrumented. It will also report the response status with the `response_status` tag and metric. (patch [15b3390b](https://github.com/appsignal/appsignal-ruby/commit/15b3390b5b54cdc7378d69c92d91ec51dab1b0e4))
|
17
|
+
|
18
|
+
### Fixed
|
19
|
+
|
20
|
+
- Fix deprecation warnings about `Transacation.params=` usage by updating how we record parameters in our instrumentations. (patch [b65d6674](https://github.com/appsignal/appsignal-ruby/commit/b65d6674c93afbc95e9cecee8c032e6949229aab))
|
21
|
+
- Fix error reporting for requests with an error that use the AppSignal EventHandler. (patch [0e48f19b](https://github.com/appsignal/appsignal-ruby/commit/0e48f19bb9f5c3ead96d21fbacdd5d7f221e2063))
|
22
|
+
|
3
23
|
## 3.9.1
|
4
24
|
|
5
25
|
_Published on 2024-06-24._
|
@@ -176,7 +176,7 @@ module Appsignal
|
|
176
176
|
#
|
177
177
|
# @example Add more metadata to transaction
|
178
178
|
# Appsignal.send_error(e) do |transaction|
|
179
|
-
# transaction.
|
179
|
+
# transaction.set_params(:search_query => params[:search_query])
|
180
180
|
# transaction.set_action("my_action_name")
|
181
181
|
# transaction.set_tags(:key => "value")
|
182
182
|
# transaction.set_namespace("my_namespace")
|
@@ -273,7 +273,7 @@ module Appsignal
|
|
273
273
|
#
|
274
274
|
# @example Add more metadata to transaction
|
275
275
|
# Appsignal.set_error(e) do |transaction|
|
276
|
-
# transaction.
|
276
|
+
# transaction.set_params(:search_query => params[:search_query])
|
277
277
|
# transaction.set_action("my_action_name")
|
278
278
|
# transaction.set_tags(:key => "value")
|
279
279
|
# transaction.set_namespace("my_namespace")
|
@@ -62,11 +62,12 @@ module Appsignal
|
|
62
62
|
end
|
63
63
|
|
64
64
|
if transaction
|
65
|
-
transaction.
|
65
|
+
transaction.set_params_if_nil(
|
66
66
|
Appsignal::Utils::HashSanitizer.sanitize(
|
67
67
|
job["arguments"],
|
68
68
|
Appsignal.config[:filter_parameters]
|
69
69
|
)
|
70
|
+
)
|
70
71
|
|
71
72
|
transaction_tags = ActiveJobHelpers.transaction_tags_for(job)
|
72
73
|
transaction_tags["active_job_id"] = job["job_id"]
|
@@ -22,7 +22,7 @@ module Appsignal
|
|
22
22
|
transaction.set_error(exception)
|
23
23
|
raise exception
|
24
24
|
ensure
|
25
|
-
transaction.
|
25
|
+
transaction.set_params_if_nil(args.first)
|
26
26
|
transaction.set_action_if_nil("#{self.class}##{args.first["action"]}")
|
27
27
|
transaction.set_metadata("path", request.path)
|
28
28
|
transaction.set_metadata("method", "websocket")
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "appsignal"
|
4
|
+
require "appsignal/rack/hanami_middleware"
|
4
5
|
|
5
6
|
module Appsignal
|
6
7
|
module Integrations
|
8
|
+
# @api private
|
7
9
|
module HanamiPlugin
|
8
10
|
def self.init
|
9
11
|
Appsignal.internal_logger.debug("Loading Hanami integration")
|
@@ -17,44 +19,27 @@ module Appsignal
|
|
17
19
|
Appsignal.start_logger
|
18
20
|
Appsignal.start
|
19
21
|
|
20
|
-
|
22
|
+
return unless Appsignal.active?
|
23
|
+
|
24
|
+
hanami_app_config.middleware.use(
|
25
|
+
::Rack::Events,
|
26
|
+
[Appsignal::Rack::EventHandler.new]
|
27
|
+
)
|
28
|
+
hanami_app_config.middleware.use(Appsignal::Rack::HanamiMiddleware)
|
29
|
+
|
30
|
+
::Hanami::Action.prepend Appsignal::Integrations::HanamiIntegration
|
21
31
|
end
|
22
32
|
end
|
23
|
-
end
|
24
|
-
end
|
25
33
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
transaction = Appsignal::Transaction.create(
|
36
|
-
SecureRandom.uuid,
|
37
|
-
Appsignal::Transaction::HTTP_REQUEST,
|
38
|
-
request
|
39
|
-
)
|
40
|
-
|
41
|
-
begin
|
42
|
-
Appsignal.instrument("process_action.hanami") do
|
43
|
-
super.tap do |response|
|
44
|
-
transaction.set_metadata("status", response.status.to_s)
|
45
|
-
end
|
34
|
+
# @api private
|
35
|
+
module HanamiIntegration
|
36
|
+
def call(env)
|
37
|
+
super
|
38
|
+
ensure
|
39
|
+
transaction = env[::Appsignal::Rack::APPSIGNAL_TRANSACTION]
|
40
|
+
|
41
|
+
transaction&.set_action_if_nil(self.class.name)
|
46
42
|
end
|
47
|
-
rescue Exception => error # rubocop:disable Lint/RescueException
|
48
|
-
transaction.set_error(error)
|
49
|
-
transaction.set_metadata("status", "500")
|
50
|
-
raise error
|
51
|
-
ensure
|
52
|
-
transaction.params = request.params.to_h
|
53
|
-
transaction.set_action_if_nil(self.class.name)
|
54
|
-
transaction.set_metadata("path", request.path)
|
55
|
-
transaction.set_metadata("method", request.request_method)
|
56
|
-
transaction.set_http_or_background_queue_start
|
57
|
-
Appsignal::Transaction.complete_current!
|
58
43
|
end
|
59
44
|
end
|
60
45
|
end
|
@@ -71,7 +71,7 @@ module Appsignal
|
|
71
71
|
transaction.set_action(action_name) if action_name
|
72
72
|
transaction.set_metadata("path", path)
|
73
73
|
transaction.set_metadata("method", method)
|
74
|
-
transaction.params
|
74
|
+
transaction.set_params_if_nil(params)
|
75
75
|
transaction.set_sample_data("custom_data", custom_data) if custom_data
|
76
76
|
|
77
77
|
tags[:severity] = severity
|
@@ -25,7 +25,7 @@ module Appsignal
|
|
25
25
|
ResqueHelpers.arguments(payload),
|
26
26
|
Appsignal.config[:filter_parameters]
|
27
27
|
)
|
28
|
-
transaction.
|
28
|
+
transaction.set_params_if_nil(args)
|
29
29
|
transaction.set_tags("queue" => queue)
|
30
30
|
|
31
31
|
Appsignal::Transaction.complete_current!
|
@@ -45,7 +45,7 @@ module Appsignal
|
|
45
45
|
)
|
46
46
|
transaction.set_action_if_nil("SidekiqInternal")
|
47
47
|
transaction.set_metadata("sidekiq_error", sidekiq_context[:context])
|
48
|
-
transaction.
|
48
|
+
transaction.set_params_if_nil(:jobstr => sidekiq_context[:jobstr])
|
49
49
|
transaction.set_error(exception)
|
50
50
|
end
|
51
51
|
|
@@ -83,9 +83,7 @@ module Appsignal
|
|
83
83
|
raise exception
|
84
84
|
ensure
|
85
85
|
if transaction
|
86
|
-
|
87
|
-
transaction.params = params if params
|
88
|
-
|
86
|
+
transaction.set_params_if_nil(filtered_arguments(item))
|
89
87
|
transaction.set_http_or_background_queue_start
|
90
88
|
Appsignal::Transaction.complete_current! unless exception
|
91
89
|
|
@@ -16,4 +16,10 @@ unless Appsignal.active?
|
|
16
16
|
Appsignal.start
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
if Appsignal.active?
|
20
|
+
::Sinatra::Base.use(
|
21
|
+
::Rack::Events,
|
22
|
+
[Appsignal::Rack::EventHandler.new]
|
23
|
+
)
|
24
|
+
::Sinatra::Base.use(Appsignal::Rack::SinatraBaseInstrumentation)
|
25
|
+
end
|
@@ -42,22 +42,22 @@ module Appsignal
|
|
42
42
|
|
43
43
|
request.env[RACK_AFTER_REPLY] ||= []
|
44
44
|
request.env[RACK_AFTER_REPLY] << proc do
|
45
|
+
next unless event_handler.request_handler?(request.env[APPSIGNAL_EVENT_HANDLER_ID])
|
46
|
+
|
45
47
|
Appsignal::Rack::EventHandler
|
46
48
|
.safe_execution("Appsignal::Rack::EventHandler's after_reply") do
|
47
|
-
next unless event_handler.request_handler?(request.env[APPSIGNAL_EVENT_HANDLER_ID])
|
48
|
-
|
49
49
|
transaction.finish_event("process_request.rack", "", "")
|
50
50
|
transaction.set_http_or_background_queue_start
|
51
|
-
|
52
|
-
# Make sure the current transaction is always closed when the request
|
53
|
-
# is finished. This is a fallback for in case the `on_finish`
|
54
|
-
# callback is not called. This is supported by servers like Puma and
|
55
|
-
# Unicorn.
|
56
|
-
#
|
57
|
-
# The EventHandler.on_finish callback should be called first, this is
|
58
|
-
# just a fallback if that doesn't get called.
|
59
|
-
Appsignal::Transaction.complete_current!
|
60
51
|
end
|
52
|
+
|
53
|
+
# Make sure the current transaction is always closed when the request
|
54
|
+
# is finished. This is a fallback for in case the `on_finish`
|
55
|
+
# callback is not called. This is supported by servers like Puma and
|
56
|
+
# Unicorn.
|
57
|
+
#
|
58
|
+
# The EventHandler.on_finish callback should be called first, this is
|
59
|
+
# just a fallback if that doesn't get called.
|
60
|
+
Appsignal::Transaction.complete_current!
|
61
61
|
end
|
62
62
|
transaction.start_event
|
63
63
|
end
|
@@ -75,26 +75,28 @@ module Appsignal
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def on_finish(request, response)
|
78
|
-
|
79
|
-
return unless request_handler?(request.env[APPSIGNAL_EVENT_HANDLER_ID])
|
78
|
+
return unless request_handler?(request.env[APPSIGNAL_EVENT_HANDLER_ID])
|
80
79
|
|
81
|
-
|
82
|
-
|
80
|
+
transaction = request.env[APPSIGNAL_TRANSACTION]
|
81
|
+
return unless transaction
|
83
82
|
|
83
|
+
self.class.safe_execution("Appsignal::Rack::EventHandler#on_finish") do
|
84
84
|
transaction.finish_event("process_request.rack", "", "")
|
85
|
-
transaction.set_tags(:response_status => response.status)
|
86
85
|
transaction.set_http_or_background_queue_start
|
87
|
-
|
88
|
-
:response_status
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
Appsignal::Transaction.complete_current!
|
86
|
+
if response
|
87
|
+
transaction.set_tags(:response_status => response.status)
|
88
|
+
Appsignal.increment_counter(
|
89
|
+
:response_status,
|
90
|
+
1,
|
91
|
+
:status => response.status,
|
92
|
+
:namespace => format_namespace(transaction.namespace)
|
93
|
+
)
|
94
|
+
end
|
97
95
|
end
|
96
|
+
|
97
|
+
# Make sure the current transaction is always closed when the request
|
98
|
+
# is finished
|
99
|
+
Appsignal::Transaction.complete_current!
|
98
100
|
end
|
99
101
|
|
100
102
|
private
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
module Rack
|
5
|
+
# @api private
|
6
|
+
class HanamiMiddleware < AbstractMiddleware
|
7
|
+
def initialize(app, options = {})
|
8
|
+
options[:request_class] ||= ::Hanami::Action::Request
|
9
|
+
options[:params_method] ||= :params
|
10
|
+
options[:instrument_span_name] ||= "process_action.hanami"
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def params_for(request)
|
17
|
+
super&.to_h
|
18
|
+
end
|
19
|
+
|
20
|
+
def request_for(env)
|
21
|
+
params = ::Hanami::Action.params_class.new(env)
|
22
|
+
@request_class.new(
|
23
|
+
:env => env,
|
24
|
+
:params => params,
|
25
|
+
:sessions_enabled => true
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -28,8 +28,6 @@ module Appsignal
|
|
28
28
|
)
|
29
29
|
|
30
30
|
begin
|
31
|
-
transaction.params = fetch_params(request)
|
32
|
-
|
33
31
|
@app.call(env)
|
34
32
|
rescue Exception => error # rubocop:disable Lint/RescueException
|
35
33
|
transaction.set_error(error)
|
@@ -39,6 +37,7 @@ module Appsignal
|
|
39
37
|
if controller
|
40
38
|
transaction.set_action_if_nil("#{controller.class}##{controller.action_name}")
|
41
39
|
end
|
40
|
+
transaction.set_params_if_nil(fetch_params(request))
|
42
41
|
request_id = fetch_request_id(env)
|
43
42
|
transaction.set_tags(:request_id => request_id) if request_id
|
44
43
|
transaction.set_metadata("path", request.path)
|
data/lib/appsignal/version.rb
CHANGED
@@ -5,32 +5,62 @@ if DependencyHelper.hanami2_present?
|
|
5
5
|
require "appsignal/integrations/hanami"
|
6
6
|
|
7
7
|
before do
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
uninstall_hanami_middleware
|
9
|
+
end
|
10
|
+
|
11
|
+
def uninstall_hanami_middleware
|
12
|
+
middleware_stack = ::Hanami.app.config.middleware.stack[::Hanami::Router::DEFAULT_PREFIX]
|
13
|
+
middleware_stack.delete_if do |middleware|
|
14
|
+
middleware.first == Appsignal::Rack::HanamiMiddleware ||
|
15
|
+
middleware.first == Rack::Events
|
16
|
+
end
|
11
17
|
end
|
12
18
|
|
13
19
|
describe Appsignal::Integrations::HanamiPlugin do
|
14
20
|
it "starts AppSignal on init" do
|
15
21
|
expect(Appsignal).to receive(:start)
|
22
|
+
expect(Appsignal).to receive(:start_logger)
|
23
|
+
Appsignal::Integrations::HanamiPlugin.init
|
16
24
|
end
|
17
25
|
|
18
|
-
it "
|
19
|
-
|
26
|
+
it "prepends the integration to Hanami::Action" do
|
27
|
+
allow(Appsignal).to receive(:active?).and_return(true)
|
28
|
+
Appsignal::Integrations::HanamiPlugin.init
|
29
|
+
expect(::Hanami::Action.included_modules)
|
30
|
+
.to include(Appsignal::Integrations::HanamiIntegration)
|
20
31
|
end
|
21
32
|
|
22
|
-
it "
|
23
|
-
|
24
|
-
|
33
|
+
it "adds middleware to the Hanami app" do
|
34
|
+
allow(Appsignal).to receive(:active?).and_return(true)
|
35
|
+
Appsignal::Integrations::HanamiPlugin.init
|
36
|
+
|
37
|
+
expect(::Hanami.app.config.middleware.stack[::Hanami::Router::DEFAULT_PREFIX])
|
38
|
+
.to include(
|
39
|
+
[Rack::Events, [[kind_of(Appsignal::Rack::EventHandler)]], nil],
|
40
|
+
[Appsignal::Rack::HanamiMiddleware, [], nil]
|
41
|
+
)
|
25
42
|
end
|
26
43
|
|
27
44
|
context "when not active" do
|
28
45
|
before { allow(Appsignal).to receive(:active?).and_return(false) }
|
29
46
|
|
30
|
-
it "does not prepend the integration" do
|
47
|
+
it "does not prepend the integration to Hanami::Action" do
|
48
|
+
Appsignal::Integrations::HanamiPlugin.init
|
31
49
|
expect(::Hanami::Action).to_not receive(:prepend)
|
32
50
|
.with(Appsignal::Integrations::HanamiIntegration)
|
33
51
|
end
|
52
|
+
|
53
|
+
it "does not add the middleware to the Hanami app" do
|
54
|
+
Appsignal::Integrations::HanamiPlugin.init
|
55
|
+
|
56
|
+
middleware_stack = ::Hanami.app.config.middleware.stack[::Hanami::Router::DEFAULT_PREFIX]
|
57
|
+
expect(middleware_stack).to_not include(
|
58
|
+
[Rack::Events, [[kind_of(Appsignal::Rack::EventHandler)]], nil]
|
59
|
+
)
|
60
|
+
expect(middleware_stack).to_not include(
|
61
|
+
[Appsignal::Rack::HanamiMiddleware, [], nil]
|
62
|
+
)
|
63
|
+
end
|
34
64
|
end
|
35
65
|
|
36
66
|
context "when APPSIGNAL_APP_ENV ENV var is provided" do
|
@@ -52,71 +82,45 @@ if DependencyHelper.hanami2_present?
|
|
52
82
|
expect(Appsignal.config.env).to eq("test")
|
53
83
|
end
|
54
84
|
end
|
55
|
-
|
56
|
-
after { Appsignal::Integrations::HanamiPlugin.init }
|
57
85
|
end
|
58
86
|
|
59
|
-
describe
|
60
|
-
let(:
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
87
|
+
describe Appsignal::Integrations::HanamiIntegration do
|
88
|
+
let(:transaction) { http_request_transaction }
|
89
|
+
around { |example| keep_transactions { example.run } }
|
90
|
+
before(:context) { start_agent }
|
91
|
+
before do
|
92
|
+
allow(Appsignal).to receive(:active?).and_return(true)
|
93
|
+
Appsignal::Integrations::HanamiPlugin.init
|
66
94
|
end
|
67
95
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:params=).with(router_params)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "sets the action name" do
|
76
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_action_if_nil)
|
77
|
-
.with("HanamiApp::Actions::Books::Index")
|
78
|
-
end
|
79
|
-
|
80
|
-
it "sets the metadata" do
|
81
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
82
|
-
.with("status", "200")
|
83
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
84
|
-
.with("path", "/books")
|
85
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
86
|
-
.with("method", "GET")
|
87
|
-
end
|
96
|
+
def make_request(env, app: HanamiApp::Actions::Books::Index)
|
97
|
+
action = app.new
|
98
|
+
action.call(env)
|
99
|
+
end
|
88
100
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
101
|
+
describe "#call" do
|
102
|
+
context "without an active transaction" do
|
103
|
+
let(:env) { {} }
|
93
104
|
|
94
|
-
|
95
|
-
|
105
|
+
it "does not set the action name" do
|
106
|
+
make_request(env)
|
96
107
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
it "sets the status to 500" do
|
102
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
103
|
-
.with("status", "500")
|
104
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata).twice
|
108
|
+
expect(transaction.to_h).to include(
|
109
|
+
"action" => nil
|
110
|
+
)
|
105
111
|
end
|
106
112
|
end
|
107
113
|
|
108
|
-
|
109
|
-
Appsignal::
|
110
|
-
|
111
|
-
action = HanamiApp::Actions::Books::Index.new
|
112
|
-
action.call(env)
|
113
|
-
end
|
114
|
+
context "with an active transaction" do
|
115
|
+
let(:env) { { Appsignal::Rack::APPSIGNAL_TRANSACTION => transaction } }
|
114
116
|
|
115
|
-
|
116
|
-
|
117
|
+
it "sets action name on the transaction" do
|
118
|
+
make_request(env)
|
117
119
|
|
118
|
-
|
119
|
-
|
120
|
+
expect(transaction.to_h).to include(
|
121
|
+
"action" => "HanamiApp::Actions::Books::Index"
|
122
|
+
)
|
123
|
+
end
|
120
124
|
end
|
121
125
|
end
|
122
126
|
end
|
@@ -50,9 +50,13 @@ if DependencyHelper.sinatra_present?
|
|
50
50
|
context "when AppSignal is not active" do
|
51
51
|
it "does not add the instrumentation middleware to Sinatra::Base" do
|
52
52
|
install_sinatra_integration
|
53
|
-
|
53
|
+
middlewares = Sinatra::Base.middleware.to_a
|
54
|
+
expect(middlewares).to_not include(
|
54
55
|
[Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
|
55
56
|
)
|
57
|
+
expect(middlewares).to_not include(
|
58
|
+
[Rack::Events, [Appsignal::Rack::EventHandler], nil]
|
59
|
+
)
|
56
60
|
end
|
57
61
|
end
|
58
62
|
|
@@ -63,7 +67,9 @@ if DependencyHelper.sinatra_present?
|
|
63
67
|
ENV["APPSIGNAL_PUSH_API_KEY"] = "my-key"
|
64
68
|
|
65
69
|
install_sinatra_integration
|
66
|
-
|
70
|
+
middlewares = Sinatra::Base.middleware.to_a
|
71
|
+
expect(middlewares).to include(
|
72
|
+
[Rack::Events, [[Appsignal::Rack::EventHandler]], nil],
|
67
73
|
[Appsignal::Rack::SinatraBaseInstrumentation, [], nil]
|
68
74
|
)
|
69
75
|
end
|
@@ -66,6 +66,30 @@ describe Appsignal::Rack::EventHandler do
|
|
66
66
|
expect(last_transaction.ext.queue_start).to eq(queue_start_time)
|
67
67
|
end
|
68
68
|
|
69
|
+
context "with error inside rack.after_reply handler" do
|
70
|
+
before do
|
71
|
+
on_start
|
72
|
+
# A random spot we can access to raise an error for this test
|
73
|
+
expect(request.env[Appsignal::Rack::APPSIGNAL_TRANSACTION])
|
74
|
+
.to receive(:finish_event)
|
75
|
+
.and_raise(ExampleStandardError, "oh no")
|
76
|
+
callback = request.env[Appsignal::Rack::RACK_AFTER_REPLY].first
|
77
|
+
callback.call
|
78
|
+
end
|
79
|
+
|
80
|
+
it "completes the transaction" do
|
81
|
+
expect(last_transaction).to be_completed
|
82
|
+
end
|
83
|
+
|
84
|
+
it "logs an error" do
|
85
|
+
expect(log).to contains_log(
|
86
|
+
:error,
|
87
|
+
"Error occurred in Appsignal::Rack::EventHandler's after_reply: " \
|
88
|
+
"ExampleStandardError: oh no"
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
69
93
|
it "logs errors from rack.after_reply callbacks" do
|
70
94
|
on_start
|
71
95
|
|
@@ -139,8 +163,8 @@ describe Appsignal::Rack::EventHandler do
|
|
139
163
|
describe "#on_finish" do
|
140
164
|
let(:response) { Rack::Events::BufferedResponse.new(200, {}, ["body"]) }
|
141
165
|
|
142
|
-
def on_finish
|
143
|
-
event_handler_instance.on_finish(
|
166
|
+
def on_finish(given_request = request, given_response = response)
|
167
|
+
event_handler_instance.on_finish(given_request, given_response)
|
144
168
|
end
|
145
169
|
|
146
170
|
it "doesn't do anything without a transaction" do
|
@@ -155,6 +179,7 @@ describe Appsignal::Rack::EventHandler do
|
|
155
179
|
"sample_data" => {},
|
156
180
|
"events" => []
|
157
181
|
)
|
182
|
+
expect(last_transaction).to_not be_completed
|
158
183
|
end
|
159
184
|
|
160
185
|
it "completes the transaction" do
|
@@ -176,6 +201,60 @@ describe Appsignal::Rack::EventHandler do
|
|
176
201
|
expect(last_transaction).to be_completed
|
177
202
|
end
|
178
203
|
|
204
|
+
context "without a response" do
|
205
|
+
it "completes the transaction" do
|
206
|
+
on_start
|
207
|
+
on_finish(request, nil)
|
208
|
+
|
209
|
+
expect(last_transaction.to_h).to include(
|
210
|
+
# The action is not set on purpose, as we can't set a normalized route
|
211
|
+
# It requires the app to set an action name
|
212
|
+
"action" => nil,
|
213
|
+
"sample_data" => hash_including(
|
214
|
+
"environment" => {
|
215
|
+
"REQUEST_METHOD" => "GET",
|
216
|
+
"PATH_INFO" => "/path"
|
217
|
+
}
|
218
|
+
)
|
219
|
+
)
|
220
|
+
expect(last_transaction.ext.queue_start).to eq(queue_start_time)
|
221
|
+
expect(last_transaction).to be_completed
|
222
|
+
end
|
223
|
+
|
224
|
+
it "does not set a response_status tag" do
|
225
|
+
on_start
|
226
|
+
on_finish(request, nil)
|
227
|
+
|
228
|
+
expect(last_transaction.to_h.dig("sample_data", "tags")).to_not have_key("response_status")
|
229
|
+
end
|
230
|
+
|
231
|
+
it "does not report a response_status counter metric" do
|
232
|
+
expect(Appsignal).to_not receive(:increment_counter)
|
233
|
+
.with(:response_status, anything, anything)
|
234
|
+
|
235
|
+
on_start
|
236
|
+
on_finish(request, nil)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
context "with error inside on_finish handler" do
|
241
|
+
before do
|
242
|
+
on_start
|
243
|
+
# A random spot we can access to raise an error for this test
|
244
|
+
expect(Appsignal).to receive(:increment_counter).and_raise(ExampleStandardError, "oh no")
|
245
|
+
on_finish
|
246
|
+
end
|
247
|
+
|
248
|
+
it "completes the transaction" do
|
249
|
+
expect(last_transaction).to be_completed
|
250
|
+
end
|
251
|
+
|
252
|
+
it "logs an error" do
|
253
|
+
expect(log).to contains_log(:error,
|
254
|
+
"Error occurred in Appsignal::Rack::EventHandler#on_finish: ExampleStandardError: oh no")
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
179
258
|
context "when the handler is nested in another EventHandler" do
|
180
259
|
it "does not complete the transaction" do
|
181
260
|
on_start
|
@@ -237,8 +316,8 @@ describe Appsignal::Rack::EventHandler do
|
|
237
316
|
end
|
238
317
|
|
239
318
|
it "logs an error in case of an error" do
|
240
|
-
|
241
|
-
|
319
|
+
# A random spot we can access to raise an error for this test
|
320
|
+
expect(Appsignal).to receive(:increment_counter).and_raise(ExampleStandardError, "oh no")
|
242
321
|
|
243
322
|
on_start
|
244
323
|
on_finish
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "appsignal/rack/hanami_middleware"
|
2
|
+
|
3
|
+
if DependencyHelper.hanami2_present?
|
4
|
+
describe Appsignal::Rack::HanamiMiddleware do
|
5
|
+
let(:app) { double(:call => true) }
|
6
|
+
let(:router_params) { { "param1" => "value1", "param2" => "value2" } }
|
7
|
+
let(:env) do
|
8
|
+
Rack::MockRequest.env_for(
|
9
|
+
"/some/path",
|
10
|
+
"router.params" => router_params
|
11
|
+
)
|
12
|
+
end
|
13
|
+
let(:middleware) { Appsignal::Rack::HanamiMiddleware.new(app, {}) }
|
14
|
+
|
15
|
+
before(:context) { start_agent }
|
16
|
+
around { |example| keep_transactions { example.run } }
|
17
|
+
|
18
|
+
def make_request(env)
|
19
|
+
middleware.call(env)
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with params" do
|
23
|
+
it "sets request parameters on the transaction" do
|
24
|
+
make_request(env)
|
25
|
+
|
26
|
+
expect(last_transaction.to_h).to include(
|
27
|
+
"sample_data" => hash_including(
|
28
|
+
"params" => { "param1" => "value1", "param2" => "value2" }
|
29
|
+
)
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "reports a process_action.hanami event" do
|
35
|
+
make_request(env)
|
36
|
+
|
37
|
+
expect(last_transaction.to_h).to include(
|
38
|
+
"events" => [
|
39
|
+
hash_including(
|
40
|
+
"body" => "",
|
41
|
+
"body_format" => Appsignal::EventFormatter::DEFAULT,
|
42
|
+
"count" => 1,
|
43
|
+
"name" => "process_action.hanami",
|
44
|
+
"title" => ""
|
45
|
+
)
|
46
|
+
]
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -115,7 +115,7 @@ if DependencyHelper.rails_present?
|
|
115
115
|
context "with custom params" do
|
116
116
|
let(:app) do
|
117
117
|
lambda do |env|
|
118
|
-
env[Appsignal::Rack::APPSIGNAL_TRANSACTION].
|
118
|
+
env[Appsignal::Rack::APPSIGNAL_TRANSACTION].set_params("custom_param" => "yes")
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
@@ -328,7 +328,7 @@ describe Appsignal::Transaction do
|
|
328
328
|
|
329
329
|
context "with custom params set on transaction" do
|
330
330
|
before do
|
331
|
-
transaction.
|
331
|
+
transaction.set_params(:foo => "bar")
|
332
332
|
end
|
333
333
|
|
334
334
|
it "returns custom parameters" do
|
@@ -352,7 +352,7 @@ describe Appsignal::Transaction do
|
|
352
352
|
|
353
353
|
it "sets params on the transaction" do
|
354
354
|
params = { "foo" => "bar" }
|
355
|
-
transaction.params = params
|
355
|
+
silence { transaction.params = params }
|
356
356
|
|
357
357
|
transaction.complete # Sample the data
|
358
358
|
expect(transaction.params).to eq(params)
|
@@ -1241,7 +1241,7 @@ describe Appsignal::Transaction do
|
|
1241
1241
|
|
1242
1242
|
context "with custom params" do
|
1243
1243
|
before do
|
1244
|
-
transaction.
|
1244
|
+
transaction.set_params(:foo => "bar", :baz => :bat)
|
1245
1245
|
end
|
1246
1246
|
|
1247
1247
|
it "returns custom params" do
|
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: 3.9.
|
4
|
+
version: 3.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Beekman
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-06-
|
13
|
+
date: 2024-06-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -274,6 +274,7 @@ files:
|
|
274
274
|
- lib/appsignal/rack/abstract_middleware.rb
|
275
275
|
- lib/appsignal/rack/event_handler.rb
|
276
276
|
- lib/appsignal/rack/generic_instrumentation.rb
|
277
|
+
- lib/appsignal/rack/hanami_middleware.rb
|
277
278
|
- lib/appsignal/rack/rails_instrumentation.rb
|
278
279
|
- lib/appsignal/rack/sinatra_instrumentation.rb
|
279
280
|
- lib/appsignal/rack/streaming_listener.rb
|
@@ -376,6 +377,7 @@ files:
|
|
376
377
|
- spec/lib/appsignal/rack/abstract_middleware_spec.rb
|
377
378
|
- spec/lib/appsignal/rack/event_handler_spec.rb
|
378
379
|
- spec/lib/appsignal/rack/generic_instrumentation_spec.rb
|
380
|
+
- spec/lib/appsignal/rack/hanami_middleware_spec.rb
|
379
381
|
- spec/lib/appsignal/rack/rails_instrumentation_spec.rb
|
380
382
|
- spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb
|
381
383
|
- spec/lib/appsignal/rack/streaming_listener_spec.rb
|