appsignal 3.9.3-java → 3.11.0-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 +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
|