appsignal 3.9.3-java → 3.11.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +22 -19
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +180 -0
- data/Gemfile +1 -0
- data/README.md +0 -1
- data/Rakefile +1 -1
- data/benchmark.rake +99 -42
- data/build_matrix.yml +10 -12
- data/gemfiles/webmachine1.gemfile +5 -4
- data/lib/appsignal/cli/demo.rb +0 -1
- data/lib/appsignal/config.rb +57 -97
- data/lib/appsignal/demo.rb +15 -20
- data/lib/appsignal/environment.rb +6 -1
- data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -0
- data/lib/appsignal/event_formatter.rb +3 -2
- data/lib/appsignal/helpers/instrumentation.rb +490 -16
- data/lib/appsignal/hooks/action_cable.rb +21 -16
- data/lib/appsignal/hooks/active_job.rb +15 -14
- data/lib/appsignal/hooks/delayed_job.rb +1 -1
- data/lib/appsignal/hooks/shoryuken.rb +3 -63
- data/lib/appsignal/integrations/action_cable.rb +5 -7
- data/lib/appsignal/integrations/active_support_notifications.rb +1 -0
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +36 -35
- data/lib/appsignal/integrations/data_mapper.rb +1 -0
- data/lib/appsignal/integrations/delayed_job_plugin.rb +27 -33
- data/lib/appsignal/integrations/dry_monitor.rb +1 -0
- data/lib/appsignal/integrations/excon.rb +1 -0
- data/lib/appsignal/integrations/http.rb +1 -0
- data/lib/appsignal/integrations/net_http.rb +1 -0
- data/lib/appsignal/integrations/object.rb +6 -0
- data/lib/appsignal/integrations/padrino.rb +21 -25
- data/lib/appsignal/integrations/que.rb +13 -20
- data/lib/appsignal/integrations/railtie.rb +1 -1
- data/lib/appsignal/integrations/rake.rb +45 -15
- data/lib/appsignal/integrations/redis.rb +1 -0
- data/lib/appsignal/integrations/redis_client.rb +1 -0
- data/lib/appsignal/integrations/resque.rb +2 -5
- data/lib/appsignal/integrations/shoryuken.rb +75 -0
- data/lib/appsignal/integrations/sidekiq.rb +7 -25
- data/lib/appsignal/integrations/unicorn.rb +1 -0
- data/lib/appsignal/integrations/webmachine.rb +12 -9
- data/lib/appsignal/logger.rb +7 -3
- data/lib/appsignal/probes/helpers.rb +1 -0
- data/lib/appsignal/probes/mri.rb +1 -0
- data/lib/appsignal/probes/sidekiq.rb +1 -0
- data/lib/appsignal/probes.rb +3 -0
- data/lib/appsignal/rack/abstract_middleware.rb +67 -24
- data/lib/appsignal/rack/body_wrapper.rb +143 -0
- data/lib/appsignal/rack/event_handler.rb +39 -8
- data/lib/appsignal/rack/generic_instrumentation.rb +6 -4
- data/lib/appsignal/rack/grape_middleware.rb +3 -2
- data/lib/appsignal/rack/hanami_middleware.rb +1 -1
- data/lib/appsignal/rack/instrumentation_middleware.rb +62 -0
- data/lib/appsignal/rack/rails_instrumentation.rb +1 -3
- data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -3
- data/lib/appsignal/rack/streaming_listener.rb +14 -59
- data/lib/appsignal/rack.rb +60 -0
- data/lib/appsignal/span.rb +1 -0
- data/lib/appsignal/transaction.rb +353 -104
- data/lib/appsignal/utils/data.rb +0 -1
- data/lib/appsignal/utils/hash_sanitizer.rb +0 -1
- data/lib/appsignal/utils/integration_logger.rb +0 -13
- data/lib/appsignal/utils/integration_memory_logger.rb +0 -13
- data/lib/appsignal/utils/json.rb +0 -1
- data/lib/appsignal/utils/query_params_sanitizer.rb +0 -1
- data/lib/appsignal/utils/stdout_and_logger_message.rb +0 -1
- data/lib/appsignal/utils.rb +6 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +9 -6
- data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
- data/spec/lib/appsignal/config_spec.rb +139 -43
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +43 -74
- data/spec/lib/appsignal/hooks/activejob_spec.rb +9 -0
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +2 -443
- data/spec/lib/appsignal/hooks/rake_spec.rb +100 -17
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -171
- data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
- data/spec/lib/appsignal/integrations/padrino_spec.rb +181 -131
- data/spec/lib/appsignal/integrations/que_spec.rb +3 -4
- data/spec/lib/appsignal/integrations/shoryuken_spec.rb +167 -0
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +4 -4
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +10 -2
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +77 -17
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +144 -11
- data/spec/lib/appsignal/rack/body_wrapper_spec.rb +263 -0
- data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -10
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +70 -17
- data/spec/lib/appsignal/rack/grape_middleware_spec.rb +1 -1
- data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +38 -0
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +43 -120
- data/spec/lib/appsignal/rack_spec.rb +63 -0
- data/spec/lib/appsignal/transaction_spec.rb +1675 -953
- data/spec/lib/appsignal/utils/integration_logger_spec.rb +12 -16
- data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -10
- data/spec/lib/appsignal_spec.rb +517 -13
- data/spec/support/helpers/transaction_helpers.rb +44 -20
- data/spec/support/matchers/transaction.rb +15 -1
- data/spec/support/mocks/dummy_app.rb +1 -1
- data/spec/support/testing.rb +1 -1
- metadata +12 -4
- data/support/check_versions +0 -22
@@ -5,6 +5,161 @@ module Appsignal
|
|
5
5
|
module Instrumentation
|
6
6
|
include Appsignal::Utils::StdoutAndLoggerMessage
|
7
7
|
|
8
|
+
# Monitor a block of code with AppSignal.
|
9
|
+
#
|
10
|
+
# This is a helper to create an AppSignal transaction, track any errors
|
11
|
+
# that may occur and complete the transaction.
|
12
|
+
#
|
13
|
+
# This helper is recommended to be used in Ruby scripts and parts of an
|
14
|
+
# app not already instrumented by AppSignal's automatic instrumentations.
|
15
|
+
#
|
16
|
+
# Use this helper in combination with our {.instrument} helper to track
|
17
|
+
# instrumentation events.
|
18
|
+
#
|
19
|
+
# If AppSignal is not active ({Appsignal.active?}) it will still execute
|
20
|
+
# the block, but not create a transaction for it.
|
21
|
+
#
|
22
|
+
# @example Instrument a block of code
|
23
|
+
# Appsignal.monitor(
|
24
|
+
# :namespace => "my_namespace",
|
25
|
+
# :action => "MyClass#my_method"
|
26
|
+
# ) do
|
27
|
+
# # Some code
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# @example Instrument a block of code using the default namespace
|
31
|
+
# Appsignal.monitor(
|
32
|
+
# :action => "MyClass#my_method"
|
33
|
+
# ) do
|
34
|
+
# # Some code
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# @example Instrument a block of code with an instrumentation event
|
38
|
+
# Appsignal.monitor(
|
39
|
+
# :namespace => "my_namespace",
|
40
|
+
# :action => "MyClass#my_method"
|
41
|
+
# ) do
|
42
|
+
# Appsignal.instrument("some_event.some_group") do
|
43
|
+
# # Some code
|
44
|
+
# end
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# @example Set the action name in the monitor block
|
48
|
+
# Appsignal.monitor(
|
49
|
+
# :action => nil
|
50
|
+
# ) do
|
51
|
+
# # Some code
|
52
|
+
#
|
53
|
+
# Appsignal.set_action("GET /resource/:id")
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# @example Set the action name in the monitor block
|
57
|
+
# Appsignal.monitor(
|
58
|
+
# :action => :set_later # Explicit placeholder
|
59
|
+
# ) do
|
60
|
+
# # Some code
|
61
|
+
#
|
62
|
+
# Appsignal.set_action("GET /resource/:id")
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# @example Set custom metadata on the transaction
|
66
|
+
# Appsignal.monitor(
|
67
|
+
# :namespace => "my_namespace",
|
68
|
+
# :action => "MyClass#my_method"
|
69
|
+
# ) do
|
70
|
+
# # Some code
|
71
|
+
#
|
72
|
+
# Appsignal.set_tags(:tag1 => "value1", :tag2 => "value2")
|
73
|
+
# Appsignal.set_params(:param1 => "value1", :param2 => "value2")
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# @example Call monitor within monitor will do nothing
|
77
|
+
# Appsignal.monitor(
|
78
|
+
# :namespace => "my_namespace",
|
79
|
+
# :action => "MyClass#my_method"
|
80
|
+
# ) do
|
81
|
+
# # This will _not_ update the namespace and action name
|
82
|
+
# Appsignal.monitor(
|
83
|
+
# :namespace => "my_other_namespace",
|
84
|
+
# :action => "MyOtherClass#my_other_method"
|
85
|
+
# ) do
|
86
|
+
# # Some code
|
87
|
+
#
|
88
|
+
# # The reported namespace will be "my_namespace"
|
89
|
+
# # The reported action will be "MyClass#my_method"
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# @param namespace [String/Symbol] The namespace to set on the new
|
94
|
+
# transaction.
|
95
|
+
# Defaults to the 'web' namespace.
|
96
|
+
# This will not update the active transaction's namespace if
|
97
|
+
# {.monitor} is called when another transaction is already active.
|
98
|
+
# @param action [String, Symbol, NilClass]
|
99
|
+
# The action name for the transaction.
|
100
|
+
# The action name is required to be set for the transaction to be
|
101
|
+
# reported.
|
102
|
+
# The argument can be set to `nil` or `:set_later` if the action is set
|
103
|
+
# within the block with {#set_action}.
|
104
|
+
# This will not update the active transaction's action if
|
105
|
+
# {.monitor} is called when another transaction is already active.
|
106
|
+
# @yield The block to monitor.
|
107
|
+
# @raise [Exception] Any exception that occurs within the given block is
|
108
|
+
# re-raised by this method.
|
109
|
+
# @return [Object] The value of the given block is returned.
|
110
|
+
# @since 3.11.0
|
111
|
+
def monitor(
|
112
|
+
action:, namespace: nil
|
113
|
+
)
|
114
|
+
return yield unless active?
|
115
|
+
|
116
|
+
has_parent_transaction = Appsignal::Transaction.current?
|
117
|
+
if has_parent_transaction
|
118
|
+
callers = caller
|
119
|
+
Appsignal::Utils::StdoutAndLoggerMessage.warning \
|
120
|
+
"An active transaction around this 'Appsignal.monitor' call. " \
|
121
|
+
"Calling `Appsignal.monitor` in another `Appsignal.monitor` block has no effect. " \
|
122
|
+
"The namespace and action are not updated for the active transaction." \
|
123
|
+
"Did you mean to use `Appsignal.instrument`? " \
|
124
|
+
"Update the 'Appsignal.monitor' call in: #{callers.first}"
|
125
|
+
return yield if block_given?
|
126
|
+
|
127
|
+
return
|
128
|
+
end
|
129
|
+
|
130
|
+
transaction =
|
131
|
+
if has_parent_transaction
|
132
|
+
Appsignal::Transaction.current
|
133
|
+
else
|
134
|
+
Appsignal::Transaction.create(namespace || Appsignal::Transaction::HTTP_REQUEST)
|
135
|
+
end
|
136
|
+
|
137
|
+
begin
|
138
|
+
yield if block_given?
|
139
|
+
rescue Exception => error # rubocop:disable Lint/RescueException
|
140
|
+
transaction.set_error(error)
|
141
|
+
raise error
|
142
|
+
ensure
|
143
|
+
transaction.set_action_if_nil(action.to_s) if action && action != :set_later
|
144
|
+
Appsignal::Transaction.complete_current!
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Instrument a block of code and stop AppSignal.
|
149
|
+
#
|
150
|
+
# Useful for cases such as one-off scripts where there is no long running
|
151
|
+
# process active and the data needs to be sent after the process exists.
|
152
|
+
#
|
153
|
+
# Acts the same way as {.monitor}. See that method for more
|
154
|
+
# documentation.
|
155
|
+
#
|
156
|
+
# @see monitor
|
157
|
+
def monitor_and_stop(action:, namespace: nil)
|
158
|
+
monitor(:namespace => namespace, :action => action)
|
159
|
+
ensure
|
160
|
+
Appsignal.stop("monitor_and_stop")
|
161
|
+
end
|
162
|
+
|
8
163
|
# Creates an AppSignal transaction for the given block.
|
9
164
|
#
|
10
165
|
# If AppSignal is not {Appsignal.active?} it will still execute the
|
@@ -58,12 +213,22 @@ module Appsignal
|
|
58
213
|
# @return [Object] the value of the given block is returned.
|
59
214
|
# @since 0.10.0
|
60
215
|
def monitor_transaction(name, env = {}, &block)
|
216
|
+
stdout_and_logger_warning \
|
217
|
+
"The `Appsignal.monitor_transaction` helper is deprecated. " \
|
218
|
+
"Please use `Appsignal.monitor` and `Appsignal.instrument` instead. " \
|
219
|
+
"Read our instrumentation documentation: " \
|
220
|
+
"https://docs.appsignal.com/ruby/instrumentation/instrumentation.html"
|
221
|
+
_monitor_transaction(name, env, &block)
|
222
|
+
end
|
223
|
+
|
224
|
+
# @api private
|
225
|
+
def _monitor_transaction(name, env = {}, &block)
|
61
226
|
# Always verify input, even when Appsignal is not active.
|
62
227
|
# This makes it more likely invalid arguments get flagged in test/dev
|
63
228
|
# environments.
|
64
229
|
if name.start_with?("perform_job")
|
65
230
|
namespace = Appsignal::Transaction::BACKGROUND_JOB
|
66
|
-
request = Appsignal::Transaction::
|
231
|
+
request = Appsignal::Transaction::InternalGenericRequest.new(env)
|
67
232
|
elsif name.start_with?("process_action")
|
68
233
|
namespace = Appsignal::Transaction::HTTP_REQUEST
|
69
234
|
request = ::Rack::Request.new(env)
|
@@ -88,7 +253,9 @@ module Appsignal
|
|
88
253
|
raise error
|
89
254
|
ensure
|
90
255
|
transaction.set_http_or_background_action(request.env)
|
91
|
-
|
256
|
+
queue_start = Appsignal::Rack::Utils.queue_start_from(request.env) ||
|
257
|
+
(env[:queue_start]&.to_i&.* 1_000)
|
258
|
+
transaction.set_queue_start(queue_start) if queue_start
|
92
259
|
Appsignal::Transaction.complete_current!
|
93
260
|
end
|
94
261
|
end
|
@@ -101,6 +268,11 @@ module Appsignal
|
|
101
268
|
#
|
102
269
|
# @see monitor_transaction
|
103
270
|
def monitor_single_transaction(name, env = {}, &block)
|
271
|
+
stdout_and_logger_warning \
|
272
|
+
"The `Appsignal.monitor_single_transaction` helper is deprecated. " \
|
273
|
+
"Please use `Appsignal.monitor_and_stop` and `Appsignal.instrument` instead. " \
|
274
|
+
"Read our instrumentation documentation: " \
|
275
|
+
"https://docs.appsignal.com/ruby/instrumentation/instrumentation.html"
|
104
276
|
monitor_transaction(name, env, &block)
|
105
277
|
ensure
|
106
278
|
stop("monitor_single_transaction")
|
@@ -195,6 +367,7 @@ module Appsignal
|
|
195
367
|
# used to send the error.
|
196
368
|
# @return [void]
|
197
369
|
#
|
370
|
+
# @see Transaction#report_error
|
198
371
|
# @see https://docs.appsignal.com/ruby/instrumentation/exception-handling.html
|
199
372
|
# Exception handling guide
|
200
373
|
# @see https://docs.appsignal.com/ruby/instrumentation/tagging.html
|
@@ -234,8 +407,7 @@ module Appsignal
|
|
234
407
|
end
|
235
408
|
transaction = Appsignal::Transaction.new(
|
236
409
|
SecureRandom.uuid,
|
237
|
-
namespace || Appsignal::Transaction::HTTP_REQUEST
|
238
|
-
Appsignal::Transaction::GenericRequest.new({})
|
410
|
+
namespace || Appsignal::Transaction::HTTP_REQUEST
|
239
411
|
)
|
240
412
|
transaction.set_tags(tags) if tags
|
241
413
|
transaction.set_error(error)
|
@@ -294,6 +466,7 @@ module Appsignal
|
|
294
466
|
# @return [void]
|
295
467
|
#
|
296
468
|
# @see Transaction#set_error
|
469
|
+
# @see Transaction#report_error
|
297
470
|
# @see https://docs.appsignal.com/ruby/instrumentation/exception-handling.html
|
298
471
|
# Exception handling guide
|
299
472
|
# @since 0.6.6
|
@@ -334,6 +507,73 @@ module Appsignal
|
|
334
507
|
alias :set_exception :set_error
|
335
508
|
alias :add_exception :set_error
|
336
509
|
|
510
|
+
# Report an error.
|
511
|
+
#
|
512
|
+
# If a transaction is currently active, it will report the error on the
|
513
|
+
# current transaction. If no transaction is active, it will report the
|
514
|
+
# error on a new transaction.
|
515
|
+
#
|
516
|
+
# **Note**: If AppSignal is not active, no error is reported.
|
517
|
+
#
|
518
|
+
# **Note**: If the given exception argument is not an Exception subclass,
|
519
|
+
# it will not be reported.
|
520
|
+
#
|
521
|
+
# @example
|
522
|
+
# class SomeController < ApplicationController
|
523
|
+
# def create
|
524
|
+
# # Do something that breaks
|
525
|
+
# rescue => error
|
526
|
+
# Appsignal.report_error(error)
|
527
|
+
# end
|
528
|
+
# end
|
529
|
+
#
|
530
|
+
# @example Add more metadata to transaction
|
531
|
+
# Appsignal.report_error(error) do |transaction|
|
532
|
+
# transaction.set_namespace("my_namespace")
|
533
|
+
# transaction.set_action("my_action_name")
|
534
|
+
# transaction.set_params(:search_query => params[:search_query])
|
535
|
+
# transaction.set_tags(:key => "value")
|
536
|
+
# end
|
537
|
+
#
|
538
|
+
# @param exception [Exception] The error to add to the current
|
539
|
+
# transaction.
|
540
|
+
# @yield [transaction] yields block to allow modification of the
|
541
|
+
# transaction.
|
542
|
+
# @yieldparam transaction [Transaction] yields the AppSignal transaction
|
543
|
+
# used to report the error.
|
544
|
+
# @return [void]
|
545
|
+
#
|
546
|
+
# @see https://docs.appsignal.com/ruby/instrumentation/exception-handling.html
|
547
|
+
# Exception handling guide
|
548
|
+
# @since 3.10.0
|
549
|
+
def report_error(exception)
|
550
|
+
unless exception.is_a?(Exception)
|
551
|
+
internal_logger.error "Appsignal.report_error: Cannot set error. " \
|
552
|
+
"The given value is not an exception: #{exception.inspect}"
|
553
|
+
return
|
554
|
+
end
|
555
|
+
return unless active?
|
556
|
+
|
557
|
+
has_parent_transaction = Appsignal::Transaction.current?
|
558
|
+
transaction =
|
559
|
+
if has_parent_transaction
|
560
|
+
Appsignal::Transaction.current
|
561
|
+
else
|
562
|
+
Appsignal::Transaction.new(
|
563
|
+
SecureRandom.uuid,
|
564
|
+
Appsignal::Transaction::HTTP_REQUEST
|
565
|
+
)
|
566
|
+
end
|
567
|
+
|
568
|
+
transaction.set_error(exception)
|
569
|
+
yield transaction if block_given?
|
570
|
+
|
571
|
+
return if has_parent_transaction
|
572
|
+
|
573
|
+
transaction.complete
|
574
|
+
end
|
575
|
+
alias :report_exception :report_error
|
576
|
+
|
337
577
|
# Set a custom action name for the current transaction.
|
338
578
|
#
|
339
579
|
# When using an integration such as the Rails or Sinatra AppSignal will
|
@@ -404,13 +644,44 @@ module Appsignal
|
|
404
644
|
Appsignal::Transaction.current.set_namespace(namespace)
|
405
645
|
end
|
406
646
|
|
647
|
+
# Set custom data on the current transaction.
|
648
|
+
#
|
649
|
+
# Add extra information about the request or background that cannot be
|
650
|
+
# expressed in tags, like nested data structures.
|
651
|
+
#
|
652
|
+
# When this method is called multiple times, it will overwrite the
|
653
|
+
# previously set value.
|
654
|
+
#
|
655
|
+
# @example
|
656
|
+
# Appsignal.set_custom_data(:user => { :locale => "en" })
|
657
|
+
# Appsignal.set_custom_data([
|
658
|
+
# "array with data",
|
659
|
+
# :options => { :verbose => true }
|
660
|
+
# ])
|
661
|
+
#
|
662
|
+
# @since 3.10.0
|
663
|
+
# @see Transaction#set_custom_data
|
664
|
+
# @see https://docs.appsignal.com/guides/custom-data/sample-data.html
|
665
|
+
# Sample data guide
|
666
|
+
# @param data [Hash/Array]
|
667
|
+
# @return [void]
|
668
|
+
def set_custom_data(data)
|
669
|
+
return unless active?
|
670
|
+
return unless Appsignal::Transaction.current?
|
671
|
+
|
672
|
+
transaction = Appsignal::Transaction.current
|
673
|
+
transaction.set_custom_data(data)
|
674
|
+
end
|
675
|
+
|
407
676
|
# Set tags on the current transaction.
|
408
677
|
#
|
409
678
|
# Tags are extra bits of information that are added to transaction and
|
410
679
|
# appear on sample details pages on AppSignal.com.
|
411
680
|
#
|
681
|
+
# When this method is called multiple times, it will merge the tags.
|
682
|
+
#
|
412
683
|
# @example
|
413
|
-
# Appsignal.tag_request(:locale => "en")
|
684
|
+
# Appsignal.tag_request(:locale => "en", :user_id => 1)
|
414
685
|
# Appsignal.tag_request("locale" => "en")
|
415
686
|
# Appsignal.tag_request("user_id" => 1)
|
416
687
|
#
|
@@ -445,6 +716,186 @@ module Appsignal
|
|
445
716
|
transaction.set_tags(tags)
|
446
717
|
end
|
447
718
|
alias :tag_job :tag_request
|
719
|
+
alias :set_tags :tag_request
|
720
|
+
|
721
|
+
# Set parameters on the current transaction.
|
722
|
+
#
|
723
|
+
# Parameters are automatically set by most of our integrations. It should
|
724
|
+
# not be necessary to call this method unless you want to report
|
725
|
+
# different parameters.
|
726
|
+
#
|
727
|
+
# To filter parameters, see our parameter filtering guide.
|
728
|
+
#
|
729
|
+
# When this method is called multiple times, it will overwrite the
|
730
|
+
# previously set value.
|
731
|
+
#
|
732
|
+
# When no parameters are set this way, the transaction will look for
|
733
|
+
# parameters in its request environment.
|
734
|
+
#
|
735
|
+
# A block can be given to this method to defer the fetching and parsing
|
736
|
+
# of the parameters until and only when the transaction is sampled.
|
737
|
+
#
|
738
|
+
# When both the `params` argument and a block is given to this method,
|
739
|
+
# the `params` argument is leading and the block will _not_ be called.
|
740
|
+
#
|
741
|
+
# @example Set parameters
|
742
|
+
# Appsignal.set_params("param1" => "value1")
|
743
|
+
#
|
744
|
+
# @example Calling `set_params` multiple times will only keep the last call
|
745
|
+
# Appsignal.set_params("param1" => "value1")
|
746
|
+
# Appsignal.set_params("param2" => "value2")
|
747
|
+
# # The parameters are: { "param2" => "value2" }
|
748
|
+
#
|
749
|
+
# @example Calling `set_params` with a block
|
750
|
+
# Appsignal.set_params do
|
751
|
+
# # Some slow code to parse parameters
|
752
|
+
# JSON.parse('{"param1": "value1"}')
|
753
|
+
# end
|
754
|
+
# # The parameters are: { "param1" => "value1" }
|
755
|
+
#
|
756
|
+
# @example Calling `set_params` with a parameter and a block
|
757
|
+
# Appsignal.set_params("argument" => "argument value") do
|
758
|
+
# # Some slow code to parse parameters
|
759
|
+
# JSON.parse('{"param1": "value1"}')
|
760
|
+
# end
|
761
|
+
# # The parameters are: { "argument" => "argument value" }
|
762
|
+
#
|
763
|
+
# @since 3.10.0
|
764
|
+
# @param params [Hash] The parameters to set on the transaction.
|
765
|
+
# @yield This block is called when the transaction is sampled. The block's
|
766
|
+
# return value will become the new parameters.
|
767
|
+
# @see https://docs.appsignal.com/guides/custom-data/sample-data.html
|
768
|
+
# Sample data guide
|
769
|
+
# @see https://docs.appsignal.com/guides/filter-data/filter-parameters.html
|
770
|
+
# Parameter filtering guide
|
771
|
+
# @see Transaction#set_params
|
772
|
+
# @return [void]
|
773
|
+
def set_params(params = nil, &block)
|
774
|
+
return unless active?
|
775
|
+
return unless Appsignal::Transaction.current?
|
776
|
+
|
777
|
+
transaction = Appsignal::Transaction.current
|
778
|
+
transaction.set_params(params, &block)
|
779
|
+
end
|
780
|
+
|
781
|
+
# Set session data on the current transaction.
|
782
|
+
#
|
783
|
+
# Session data is automatically set by most of our integrations. It
|
784
|
+
# should not be necessary to call this method unless you want to report
|
785
|
+
# different session data.
|
786
|
+
#
|
787
|
+
# To filter session data, see our session data filtering guide.
|
788
|
+
#
|
789
|
+
# When this method is called multiple times, it will overwrite the
|
790
|
+
# previously set value.
|
791
|
+
#
|
792
|
+
# A block can be given to this method to defer the fetching and parsing
|
793
|
+
# of the session data until and only when the transaction is sampled.
|
794
|
+
#
|
795
|
+
# When both the `session_data` argument and a block is given to this
|
796
|
+
# method, the `session_data` argument is leading and the block will _not_
|
797
|
+
# be called.
|
798
|
+
#
|
799
|
+
# @example Set session data
|
800
|
+
# Appsignal.set_session_data("data" => "value")
|
801
|
+
#
|
802
|
+
# @example Calling `set_session_data` multiple times will only keep the last call
|
803
|
+
# Appsignal.set_session_data("data1" => "value1")
|
804
|
+
# Appsignal.set_session_data("data2" => "value2")
|
805
|
+
# # The session data is: { "data2" => "value2" }
|
806
|
+
#
|
807
|
+
# @example Calling `set_session_data` with a block
|
808
|
+
# Appsignal.set_session_data do
|
809
|
+
# # Some slow code to parse session data
|
810
|
+
# JSON.parse('{"data": "value"}')
|
811
|
+
# end
|
812
|
+
# # The session data is: { "data" => "value" }
|
813
|
+
#
|
814
|
+
# @example Calling `set_session_data` with a session_data argument and a block
|
815
|
+
# Appsignal.set_session_data("argument" => "argument value") do
|
816
|
+
# # Some slow code to parse session data
|
817
|
+
# JSON.parse('{"data": "value"}')
|
818
|
+
# end
|
819
|
+
# # The session data is: { "argument" => "argument value" }
|
820
|
+
#
|
821
|
+
# @since 3.11.0
|
822
|
+
# @param session_data [Hash] The session data to set on the transaction.
|
823
|
+
# @yield This block is called when the transaction is sampled. The block's
|
824
|
+
# return value will become the new session data.
|
825
|
+
# @see https://docs.appsignal.com/guides/custom-data/sample-data.html
|
826
|
+
# Sample data guide
|
827
|
+
# @see https://docs.appsignal.com/guides/filter-data/filter-session-data.html
|
828
|
+
# Session data filtering guide
|
829
|
+
# @see Transaction#set_session_data
|
830
|
+
# @return [void]
|
831
|
+
def set_session_data(session_data = nil, &block)
|
832
|
+
return unless active?
|
833
|
+
return unless Appsignal::Transaction.current?
|
834
|
+
|
835
|
+
transaction = Appsignal::Transaction.current
|
836
|
+
transaction.set_session_data(session_data, &block)
|
837
|
+
end
|
838
|
+
|
839
|
+
# Set request headers on the current transaction.
|
840
|
+
#
|
841
|
+
# Request headers are automatically set by most of our integrations. It
|
842
|
+
# should not be necessary to call this method unless you want to report
|
843
|
+
# different request headers.
|
844
|
+
#
|
845
|
+
# To filter request headers, see our session data filtering guide.
|
846
|
+
#
|
847
|
+
# When this method is called multiple times, it will overwrite the
|
848
|
+
# previously set value.
|
849
|
+
#
|
850
|
+
# A block can be given to this method to defer the fetching and parsing
|
851
|
+
# of the request headers until and only when the transaction is sampled.
|
852
|
+
#
|
853
|
+
# When both the `request_headers` argument and a block is given to this
|
854
|
+
# method, the `request_headers` argument is leading and the block will
|
855
|
+
# _not_ be called.
|
856
|
+
#
|
857
|
+
# @example Set request headers
|
858
|
+
# Appsignal.set_headers(
|
859
|
+
# "PATH_INFO" => "/some-path",
|
860
|
+
# "HTTP_USER_AGENT" => "Firefox"
|
861
|
+
# )
|
862
|
+
#
|
863
|
+
# @example Calling `set_headers` multiple times will only keep the last call
|
864
|
+
# Appsignal.set_headers("PATH_INFO" => "/some-path")
|
865
|
+
# Appsignal.set_headers("HTTP_USER_AGENT" => "Firefox")
|
866
|
+
# # The request headers are: { "HTTP_USER_AGENT" => "Firefox" }
|
867
|
+
#
|
868
|
+
# @example Calling `set_headers` with a block
|
869
|
+
# Appsignal.set_headers do
|
870
|
+
# # Some slow code to parse request headers
|
871
|
+
# JSON.parse('{"PATH_INFO": "/some-path"}')
|
872
|
+
# end
|
873
|
+
# # The session data is: { "PATH_INFO" => "/some-path" }
|
874
|
+
#
|
875
|
+
# @example Calling `set_headers` with a headers argument and a block
|
876
|
+
# Appsignal.set_headers("PATH_INFO" => "/some-path") do
|
877
|
+
# # Some slow code to parse session data
|
878
|
+
# JSON.parse('{"PATH_INFO": "/block-path"}')
|
879
|
+
# end
|
880
|
+
# # The session data is: { "PATH_INFO" => "/some-path" }
|
881
|
+
#
|
882
|
+
# @since 3.11.0
|
883
|
+
# @param headers [Hash] The request headers to set on the transaction.
|
884
|
+
# @yield This block is called when the transaction is sampled. The block's
|
885
|
+
# return value will become the new request headers.
|
886
|
+
# @see https://docs.appsignal.com/guides/custom-data/sample-data.html
|
887
|
+
# Sample data guide
|
888
|
+
# @see https://docs.appsignal.com/guides/filter-data/filter-headers.html
|
889
|
+
# Request headers filtering guide
|
890
|
+
# @see Transaction#set_headers
|
891
|
+
# @return [void]
|
892
|
+
def set_headers(headers = nil, &block)
|
893
|
+
return unless active?
|
894
|
+
return unless Appsignal::Transaction.current?
|
895
|
+
|
896
|
+
transaction = Appsignal::Transaction.current
|
897
|
+
transaction.set_headers(headers, &block)
|
898
|
+
end
|
448
899
|
|
449
900
|
# Add breadcrumbs to the transaction.
|
450
901
|
#
|
@@ -537,14 +988,11 @@ module Appsignal
|
|
537
988
|
name,
|
538
989
|
title = nil,
|
539
990
|
body = nil,
|
540
|
-
body_format = Appsignal::EventFormatter::DEFAULT
|
991
|
+
body_format = Appsignal::EventFormatter::DEFAULT,
|
992
|
+
&block
|
541
993
|
)
|
542
|
-
Appsignal::Transaction.current
|
543
|
-
|
544
|
-
ensure
|
545
|
-
Appsignal::Transaction
|
546
|
-
.current
|
547
|
-
.finish_event(name, title, body, body_format)
|
994
|
+
Appsignal::Transaction.current
|
995
|
+
.instrument(name, title, body, body_format, &block)
|
548
996
|
end
|
549
997
|
|
550
998
|
# Instrumentation helper for SQL queries.
|
@@ -587,22 +1035,48 @@ module Appsignal
|
|
587
1035
|
)
|
588
1036
|
end
|
589
1037
|
|
590
|
-
# Convenience method for
|
1038
|
+
# Convenience method for ignoring instrumentation events in a block of
|
1039
|
+
# code.
|
1040
|
+
#
|
1041
|
+
# - This helper ignores events, like those created
|
1042
|
+
# `Appsignal.instrument`, within this block.
|
1043
|
+
# This includes custom instrumentation and events recorded by AppSignal
|
1044
|
+
# integrations for requests, database queries, view rendering, etc.
|
1045
|
+
# - The time spent in the block is still reported on the transaction.
|
1046
|
+
# - Errors and metrics are reported from within this block.
|
591
1047
|
#
|
592
1048
|
# @example
|
593
|
-
# Appsignal.
|
1049
|
+
# Appsignal.instrument "my_event.my_group" do
|
594
1050
|
# # Complex code here
|
595
1051
|
# end
|
1052
|
+
# Appsignal.ignore_instrumentation_events do
|
1053
|
+
# Appsignal.instrument "my_ignored_event.my_ignored_group" do
|
1054
|
+
# # Complex code here
|
1055
|
+
# end
|
1056
|
+
# end
|
1057
|
+
#
|
1058
|
+
# # Only the "my_event.my_group" instrumentation event is reported.
|
596
1059
|
#
|
597
1060
|
# @yield block of code that shouldn't be instrumented.
|
598
1061
|
# @return [Object] Returns the return value of the block.
|
599
|
-
# @since
|
600
|
-
|
1062
|
+
# @since 3.10.0
|
1063
|
+
# @see https://docs.appsignal.com/ruby/instrumentation/ignore-instrumentation.html
|
1064
|
+
# Ignore instrumentation guide
|
1065
|
+
def ignore_instrumentation_events
|
601
1066
|
Appsignal::Transaction.current&.pause!
|
602
1067
|
yield
|
603
1068
|
ensure
|
604
1069
|
Appsignal::Transaction.current&.resume!
|
605
1070
|
end
|
1071
|
+
|
1072
|
+
# @deprecated Use {.ignore_instrumentation_events} instead.
|
1073
|
+
# @since 0.8.7
|
1074
|
+
def without_instrumentation(&block)
|
1075
|
+
stdout_and_logger_warning \
|
1076
|
+
"The `Appsignal.without_instrumentation` helper is deprecated. " \
|
1077
|
+
"Please use `Appsignal.ignore_instrumentation_events` instead."
|
1078
|
+
ignore_instrumentation_events(&block)
|
1079
|
+
end
|
606
1080
|
end
|
607
1081
|
end
|
608
1082
|
end
|
@@ -17,12 +17,13 @@ module Appsignal
|
|
17
17
|
require "appsignal/integrations/action_cable"
|
18
18
|
ActionCable::Channel::Base.prepend Appsignal::Integrations::ActionCableIntegration
|
19
19
|
|
20
|
-
|
20
|
+
install_subscribe_callback
|
21
|
+
install_unsubscribe_callback
|
21
22
|
end
|
22
23
|
|
23
24
|
private
|
24
25
|
|
25
|
-
def
|
26
|
+
def install_subscribe_callback
|
26
27
|
ActionCable::Channel::Base.set_callback :subscribe, :around,
|
27
28
|
:prepend => true do |channel, inner|
|
28
29
|
# The request is only the original websocket request
|
@@ -32,14 +33,11 @@ module Appsignal
|
|
32
33
|
# in apps' test suites.
|
33
34
|
env = connection.respond_to?(:env) ? connection.env : {}
|
34
35
|
request = ActionDispatch::Request.new(env)
|
35
|
-
|
36
|
-
|
36
|
+
request_id = request.request_id || SecureRandom.uuid
|
37
|
+
env[Appsignal::Hooks::ActionCableHook::REQUEST_ID] ||= request_id
|
37
38
|
|
38
|
-
transaction =
|
39
|
-
|
40
|
-
Appsignal::Transaction::ACTION_CABLE,
|
41
|
-
request
|
42
|
-
)
|
39
|
+
transaction =
|
40
|
+
Appsignal::Transaction.create(Appsignal::Transaction::ACTION_CABLE)
|
43
41
|
|
44
42
|
begin
|
45
43
|
Appsignal.instrument "subscribed.action_cable" do
|
@@ -52,10 +50,16 @@ module Appsignal
|
|
52
50
|
transaction.set_action_if_nil("#{channel.class}#subscribed")
|
53
51
|
transaction.set_metadata("path", request.path)
|
54
52
|
transaction.set_metadata("method", "websocket")
|
53
|
+
transaction.set_params_if_nil { request.params }
|
54
|
+
transaction.set_headers_if_nil { request.env }
|
55
|
+
transaction.set_session_data { request.session if request.respond_to? :session }
|
56
|
+
transaction.set_tags(:request_id => request_id) if request_id
|
55
57
|
Appsignal::Transaction.complete_current!
|
56
58
|
end
|
57
59
|
end
|
60
|
+
end
|
58
61
|
|
62
|
+
def install_unsubscribe_callback
|
59
63
|
ActionCable::Channel::Base.set_callback :unsubscribe, :around,
|
60
64
|
:prepend => true do |channel, inner|
|
61
65
|
# The request is only the original websocket request
|
@@ -65,14 +69,11 @@ module Appsignal
|
|
65
69
|
# in apps' test suites.
|
66
70
|
env = connection.respond_to?(:env) ? connection.env : {}
|
67
71
|
request = ActionDispatch::Request.new(env)
|
68
|
-
|
69
|
-
|
72
|
+
request_id = request.request_id || SecureRandom.uuid
|
73
|
+
env[Appsignal::Hooks::ActionCableHook::REQUEST_ID] ||= request_id
|
70
74
|
|
71
|
-
transaction =
|
72
|
-
|
73
|
-
Appsignal::Transaction::ACTION_CABLE,
|
74
|
-
request
|
75
|
-
)
|
75
|
+
transaction =
|
76
|
+
Appsignal::Transaction.create(Appsignal::Transaction::ACTION_CABLE)
|
76
77
|
|
77
78
|
begin
|
78
79
|
Appsignal.instrument "unsubscribed.action_cable" do
|
@@ -85,6 +86,10 @@ module Appsignal
|
|
85
86
|
transaction.set_action_if_nil("#{channel.class}#unsubscribed")
|
86
87
|
transaction.set_metadata("path", request.path)
|
87
88
|
transaction.set_metadata("method", "websocket")
|
89
|
+
transaction.set_params_if_nil { request.params }
|
90
|
+
transaction.set_headers_if_nil { request.env }
|
91
|
+
transaction.set_session_data { request.session if request.respond_to? :session }
|
92
|
+
transaction.set_tags(:request_id => request_id) if request_id
|
88
93
|
Appsignal::Transaction.complete_current!
|
89
94
|
end
|
90
95
|
end
|