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
|
@@ -6,28 +6,80 @@ module Appsignal
|
|
|
6
6
|
class Transaction
|
|
7
7
|
HTTP_REQUEST = "http_request"
|
|
8
8
|
BACKGROUND_JOB = "background_job"
|
|
9
|
+
# @api private
|
|
9
10
|
ACTION_CABLE = "action_cable"
|
|
11
|
+
# @api private
|
|
10
12
|
FRONTEND = "frontend"
|
|
13
|
+
# @api private
|
|
11
14
|
BLANK = ""
|
|
15
|
+
# @api private
|
|
12
16
|
ALLOWED_TAG_KEY_TYPES = [Symbol, String].freeze
|
|
13
|
-
|
|
17
|
+
# @api private
|
|
18
|
+
ALLOWED_TAG_VALUE_TYPES = [Symbol, String, Integer, TrueClass, FalseClass].freeze
|
|
19
|
+
# @api private
|
|
14
20
|
BREADCRUMB_LIMIT = 20
|
|
21
|
+
# @api private
|
|
15
22
|
ERROR_CAUSES_LIMIT = 10
|
|
16
23
|
|
|
17
24
|
class << self
|
|
18
|
-
|
|
25
|
+
# Create a new transaction and set it as the currently active
|
|
26
|
+
# transaction.
|
|
27
|
+
#
|
|
28
|
+
# @param id_or_namespace [String] Namespace of the to be created transaction.
|
|
29
|
+
# @return [Transaction]
|
|
30
|
+
def create(id_or_namespace, arg_namespace = nil, request = nil, options = {})
|
|
31
|
+
if id_or_namespace && arg_namespace
|
|
32
|
+
Appsignal::Utils::StdoutAndLoggerMessage.warning(
|
|
33
|
+
"Appsignal::Transaction.create: " \
|
|
34
|
+
"A new Transaction is created using the transaction ID argument. " \
|
|
35
|
+
"This argument is deprecated without replacement."
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
if arg_namespace
|
|
39
|
+
Appsignal::Utils::StdoutAndLoggerMessage.warning(
|
|
40
|
+
"Appsignal::Transaction.create: " \
|
|
41
|
+
"A Transaction is created using the namespace argument. " \
|
|
42
|
+
"Specify the namespace as the first argument to the 'create' " \
|
|
43
|
+
"method without the ID argument."
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
if request
|
|
47
|
+
Appsignal::Utils::StdoutAndLoggerMessage.warning(
|
|
48
|
+
"Appsignal::Transaction.create: " \
|
|
49
|
+
"A Transaction is created using the request argument. " \
|
|
50
|
+
"This argument is deprecated. Please use the `Appsignal.set_*` helpers instead."
|
|
51
|
+
)
|
|
52
|
+
end
|
|
19
53
|
# Allow middleware to force a new transaction
|
|
20
|
-
|
|
54
|
+
if options[:force]
|
|
55
|
+
Appsignal::Utils::StdoutAndLoggerMessage.warning(
|
|
56
|
+
"Appsignal::Transaction.create: " \
|
|
57
|
+
"A Transaction is created using the `:force => true` option argument. " \
|
|
58
|
+
"The options argument is deprecated without replacement."
|
|
59
|
+
)
|
|
60
|
+
Thread.current[:appsignal_transaction] = nil
|
|
61
|
+
end
|
|
62
|
+
if arg_namespace
|
|
63
|
+
id = id_or_namespace
|
|
64
|
+
namespace = arg_namespace
|
|
65
|
+
else
|
|
66
|
+
id = SecureRandom.uuid
|
|
67
|
+
namespace = id_or_namespace
|
|
68
|
+
end
|
|
21
69
|
|
|
22
70
|
# Check if we already have a running transaction
|
|
23
71
|
if Thread.current[:appsignal_transaction].nil?
|
|
24
72
|
# If not, start a new transaction
|
|
25
73
|
Thread.current[:appsignal_transaction] =
|
|
26
|
-
Appsignal::Transaction.new(
|
|
74
|
+
Appsignal::Transaction.new(
|
|
75
|
+
id,
|
|
76
|
+
namespace,
|
|
77
|
+
request,
|
|
78
|
+
options
|
|
79
|
+
)
|
|
27
80
|
else
|
|
28
81
|
# Otherwise, log the issue about trying to start another transaction
|
|
29
|
-
Appsignal.internal_logger.
|
|
30
|
-
:transaction_id,
|
|
82
|
+
Appsignal.internal_logger.warn(
|
|
31
83
|
"Trying to start new transaction with id " \
|
|
32
84
|
"'#{id}', but a transaction with id '#{current.transaction_id}' " \
|
|
33
85
|
"is already running. Using transaction '#{current.transaction_id}'."
|
|
@@ -56,6 +108,8 @@ module Appsignal
|
|
|
56
108
|
current && !current.nil_transaction?
|
|
57
109
|
end
|
|
58
110
|
|
|
111
|
+
# Complete the currently active transaction and unset it as the active
|
|
112
|
+
# transaction.
|
|
59
113
|
def complete_current!
|
|
60
114
|
current.complete
|
|
61
115
|
rescue => e
|
|
@@ -73,21 +127,32 @@ module Appsignal
|
|
|
73
127
|
end
|
|
74
128
|
end
|
|
75
129
|
|
|
130
|
+
# @api private
|
|
76
131
|
attr_reader :ext, :transaction_id, :action, :namespace, :request, :paused, :tags, :options,
|
|
77
|
-
:
|
|
132
|
+
:breadcrumbs, :custom_data
|
|
78
133
|
|
|
79
|
-
|
|
134
|
+
# Use {.create} to create new transactions.
|
|
135
|
+
#
|
|
136
|
+
# @param transaction_id [String] ID of the to be created transaction.
|
|
137
|
+
# @param namespace [String] Namespace of the to be created transaction.
|
|
138
|
+
# @see create
|
|
139
|
+
# @api private
|
|
140
|
+
def initialize(transaction_id, namespace, request = nil, options = {})
|
|
80
141
|
@transaction_id = transaction_id
|
|
81
142
|
@action = nil
|
|
82
143
|
@namespace = namespace
|
|
83
|
-
@request = request
|
|
144
|
+
@request = request || InternalGenericRequest.new({})
|
|
84
145
|
@paused = false
|
|
85
146
|
@discarded = false
|
|
86
147
|
@tags = {}
|
|
148
|
+
@custom_data = nil
|
|
87
149
|
@breadcrumbs = []
|
|
88
150
|
@store = Hash.new({})
|
|
89
151
|
@options = options
|
|
90
152
|
@options[:params_method] ||= :params
|
|
153
|
+
@params = nil
|
|
154
|
+
@session_data = nil
|
|
155
|
+
@headers = nil
|
|
91
156
|
|
|
92
157
|
@ext = Appsignal::Extension.start_transaction(
|
|
93
158
|
@transaction_id,
|
|
@@ -106,42 +171,57 @@ module Appsignal
|
|
|
106
171
|
"because it was manually discarded."
|
|
107
172
|
return
|
|
108
173
|
end
|
|
109
|
-
|
|
174
|
+
_sample_data if @ext.finish(0)
|
|
110
175
|
@ext.complete
|
|
111
176
|
end
|
|
112
177
|
|
|
178
|
+
# @api private
|
|
113
179
|
def pause!
|
|
114
180
|
@paused = true
|
|
115
181
|
end
|
|
116
182
|
|
|
183
|
+
# @api private
|
|
117
184
|
def resume!
|
|
118
185
|
@paused = false
|
|
119
186
|
end
|
|
120
187
|
|
|
188
|
+
# @api private
|
|
121
189
|
def paused?
|
|
122
190
|
@paused == true
|
|
123
191
|
end
|
|
124
192
|
|
|
193
|
+
# @api private
|
|
125
194
|
def discard!
|
|
126
195
|
@discarded = true
|
|
127
196
|
end
|
|
128
197
|
|
|
198
|
+
# @api private
|
|
129
199
|
def restore!
|
|
130
200
|
@discarded = false
|
|
131
201
|
end
|
|
132
202
|
|
|
203
|
+
# @api private
|
|
133
204
|
def discarded?
|
|
134
205
|
@discarded == true
|
|
135
206
|
end
|
|
136
207
|
|
|
208
|
+
# @api private
|
|
137
209
|
def store(key)
|
|
138
210
|
@store[key]
|
|
139
211
|
end
|
|
140
212
|
|
|
213
|
+
# @api private
|
|
141
214
|
def params
|
|
142
|
-
|
|
215
|
+
parameters = @params || request_params
|
|
143
216
|
|
|
144
|
-
|
|
217
|
+
if parameters.respond_to? :call
|
|
218
|
+
parameters.call
|
|
219
|
+
else
|
|
220
|
+
parameters
|
|
221
|
+
end
|
|
222
|
+
rescue => e
|
|
223
|
+
Appsignal.internal_logger.error("Exception while fetching params: #{e.class}: #{e}")
|
|
224
|
+
nil
|
|
145
225
|
end
|
|
146
226
|
|
|
147
227
|
# Set parameters on the transaction.
|
|
@@ -152,9 +232,17 @@ module Appsignal
|
|
|
152
232
|
# The parameters set using {#set_params} are leading over those extracted
|
|
153
233
|
# from a request's environment.
|
|
154
234
|
#
|
|
235
|
+
# When both the `given_params` and a block is given to this method, the
|
|
236
|
+
# `given_params` argument is leading and the block will _not_ be called.
|
|
237
|
+
#
|
|
238
|
+
# @since 3.9.1
|
|
155
239
|
# @param given_params [Hash] The parameters to set on the transaction.
|
|
240
|
+
# @yield This block is called when the transaction is sampled. The block's
|
|
241
|
+
# return value will become the new parameters.
|
|
156
242
|
# @return [void]
|
|
157
|
-
|
|
243
|
+
# @see Helpers::Instrumentation#set_params
|
|
244
|
+
def set_params(given_params = nil, &block)
|
|
245
|
+
@params = block if block
|
|
158
246
|
@params = given_params if given_params
|
|
159
247
|
end
|
|
160
248
|
|
|
@@ -172,14 +260,22 @@ module Appsignal
|
|
|
172
260
|
# When no parameters are set this way, the transaction will look for
|
|
173
261
|
# parameters on the {#request} environment.
|
|
174
262
|
#
|
|
263
|
+
# @since 3.9.1
|
|
175
264
|
# @param given_params [Hash] The parameters to set on the transaction if none are already set.
|
|
265
|
+
# @yield This block is called when the transaction is sampled. The block's
|
|
266
|
+
# return value will become the new parameters.
|
|
176
267
|
# @return [void]
|
|
177
|
-
|
|
178
|
-
|
|
268
|
+
#
|
|
269
|
+
# @see #set_params
|
|
270
|
+
# @see Helpers::Instrumentation#set_params_if_nil
|
|
271
|
+
def set_params_if_nil(given_params = nil, &block)
|
|
272
|
+
set_params(given_params, &block) unless @params
|
|
179
273
|
end
|
|
180
274
|
|
|
181
275
|
# Set tags on the transaction.
|
|
182
276
|
#
|
|
277
|
+
# When this method is called multiple times, it will merge the tags.
|
|
278
|
+
#
|
|
183
279
|
# @param given_tags [Hash] Collection of tags.
|
|
184
280
|
# @option given_tags [String, Symbol, Integer] :any
|
|
185
281
|
# The name of the tag as a Symbol.
|
|
@@ -187,13 +283,112 @@ module Appsignal
|
|
|
187
283
|
# The name of the tag as a String.
|
|
188
284
|
# @return [void]
|
|
189
285
|
#
|
|
190
|
-
# @see
|
|
286
|
+
# @see Helpers::Instrumentation#tag_request
|
|
191
287
|
# @see https://docs.appsignal.com/ruby/instrumentation/tagging.html
|
|
192
288
|
# Tagging guide
|
|
193
289
|
def set_tags(given_tags = {})
|
|
194
290
|
@tags.merge!(given_tags)
|
|
195
291
|
end
|
|
196
292
|
|
|
293
|
+
# Set session data on the transaction.
|
|
294
|
+
#
|
|
295
|
+
# When both the `given_session_data` and a block is given to this method,
|
|
296
|
+
# the `given_session_data` argument is leading and the block will _not_ be
|
|
297
|
+
# called.
|
|
298
|
+
#
|
|
299
|
+
# @param given_session_data [Hash] A hash containing session data.
|
|
300
|
+
# @yield This block is called when the transaction is sampled. The block's
|
|
301
|
+
# return value will become the new session data.
|
|
302
|
+
# @return [void]
|
|
303
|
+
#
|
|
304
|
+
# @since 3.10.1
|
|
305
|
+
# @see Helpers::Instrumentation#set_session_data
|
|
306
|
+
# @see https://docs.appsignal.com/guides/custom-data/sample-data.html
|
|
307
|
+
# Sample data guide
|
|
308
|
+
def set_session_data(given_session_data = nil, &block)
|
|
309
|
+
@session_data = block if block
|
|
310
|
+
@session_data = given_session_data if given_session_data
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# Set session data on the transaction if not already set.
|
|
314
|
+
#
|
|
315
|
+
# When both the `given_session_data` and a block is given to this method,
|
|
316
|
+
# the `given_session_data` argument is leading and the block will _not_ be
|
|
317
|
+
# called.
|
|
318
|
+
#
|
|
319
|
+
# @param given_session_data [Hash] A hash containing session data.
|
|
320
|
+
# @yield This block is called when the transaction is sampled. The block's
|
|
321
|
+
# return value will become the new session data.
|
|
322
|
+
# @return [void]
|
|
323
|
+
#
|
|
324
|
+
# @since 3.10.1
|
|
325
|
+
# @see #set_session_data
|
|
326
|
+
# @see https://docs.appsignal.com/guides/custom-data/sample-data.html
|
|
327
|
+
# Sample data guide
|
|
328
|
+
def set_session_data_if_nil(given_session_data = nil, &block)
|
|
329
|
+
set_session_data(given_session_data, &block) unless @session_data
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# Set headers on the transaction.
|
|
333
|
+
#
|
|
334
|
+
# When both the `given_headers` and a block is given to this method,
|
|
335
|
+
# the `given_headers` argument is leading and the block will _not_ be
|
|
336
|
+
# called.
|
|
337
|
+
#
|
|
338
|
+
# @param given_headers [Hash] A hash containing headers.
|
|
339
|
+
# @yield This block is called when the transaction is sampled. The block's
|
|
340
|
+
# return value will become the new headers.
|
|
341
|
+
# @return [void]
|
|
342
|
+
#
|
|
343
|
+
# @since 3.10.1
|
|
344
|
+
# @see Helpers::Instrumentation#set_headers
|
|
345
|
+
# @see https://docs.appsignal.com/guides/custom-data/sample-data.html
|
|
346
|
+
# Sample data guide
|
|
347
|
+
def set_headers(given_headers = nil, &block)
|
|
348
|
+
@headers = block if block
|
|
349
|
+
@headers = given_headers if given_headers
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Set headers on the transaction if not already set.
|
|
353
|
+
#
|
|
354
|
+
# When both the `given_headers` and a block is given to this method,
|
|
355
|
+
# the `given_headers` argument is leading and the block will _not_ be
|
|
356
|
+
# called.
|
|
357
|
+
#
|
|
358
|
+
# @param given_headers [Hash] A hash containing headers.
|
|
359
|
+
# @yield This block is called when the transaction is sampled. The block's
|
|
360
|
+
# return value will become the new headers.
|
|
361
|
+
# @return [void]
|
|
362
|
+
#
|
|
363
|
+
# @since 3.10.1
|
|
364
|
+
# @see #set_headers
|
|
365
|
+
# @see https://docs.appsignal.com/guides/custom-data/sample-data.html
|
|
366
|
+
# Sample data guide
|
|
367
|
+
def set_headers_if_nil(given_headers = nil, &block)
|
|
368
|
+
set_headers(given_headers, &block) unless @headers
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# Set custom data on the transaction.
|
|
372
|
+
#
|
|
373
|
+
# When this method is called multiple times, it will overwrite the
|
|
374
|
+
# previously set value.
|
|
375
|
+
#
|
|
376
|
+
# @since 3.10.0
|
|
377
|
+
# @see Appsignal.set_custom_data
|
|
378
|
+
# @see https://docs.appsignal.com/guides/custom-data/sample-data.html
|
|
379
|
+
# Sample data guide
|
|
380
|
+
# @param data [Hash/Array]
|
|
381
|
+
# @return [void]
|
|
382
|
+
def set_custom_data(data)
|
|
383
|
+
case data
|
|
384
|
+
when Array, Hash
|
|
385
|
+
@custom_data = data
|
|
386
|
+
else
|
|
387
|
+
Appsignal.internal_logger
|
|
388
|
+
.error("set_custom_data: Unsupported data type #{data.class} received.")
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
197
392
|
# Add breadcrumbs to the transaction.
|
|
198
393
|
#
|
|
199
394
|
# @param category [String] category of breadcrumb
|
|
@@ -284,6 +479,8 @@ module Appsignal
|
|
|
284
479
|
@ext.set_namespace(namespace)
|
|
285
480
|
end
|
|
286
481
|
|
|
482
|
+
# @deprecated Use the {#set_action} helper.
|
|
483
|
+
# @api private
|
|
287
484
|
def set_http_or_background_action(from = request.params)
|
|
288
485
|
return unless from
|
|
289
486
|
|
|
@@ -296,8 +493,6 @@ module Appsignal
|
|
|
296
493
|
|
|
297
494
|
# Set queue start time for transaction.
|
|
298
495
|
#
|
|
299
|
-
# Most commononly called by {set_http_or_background_queue_start}.
|
|
300
|
-
#
|
|
301
496
|
# @param start [Integer] Queue start time in milliseconds.
|
|
302
497
|
# @raise [RangeError] When the queue start time value is too big, this
|
|
303
498
|
# method raises a RangeError.
|
|
@@ -327,14 +522,21 @@ module Appsignal
|
|
|
327
522
|
# AppSignal as seconds.
|
|
328
523
|
#
|
|
329
524
|
# @see https://docs.appsignal.com/ruby/instrumentation/request-queue-time.html
|
|
525
|
+
# @deprecated Use {#set_queue_start} instead.
|
|
330
526
|
# @return [void]
|
|
331
527
|
def set_http_or_background_queue_start
|
|
528
|
+
Appsignal::Utils::StdoutAndLoggerMessage.warning \
|
|
529
|
+
"The Appsignal::Transaction#set_http_or_background_queue_start " \
|
|
530
|
+
"method has been deprecated. " \
|
|
531
|
+
"Please use the Appsignal::Transaction#set_queue_start method instead."
|
|
532
|
+
|
|
332
533
|
start = http_queue_start || background_queue_start
|
|
333
534
|
return unless start
|
|
334
535
|
|
|
335
536
|
set_queue_start(start)
|
|
336
537
|
end
|
|
337
538
|
|
|
539
|
+
# @api private
|
|
338
540
|
def set_metadata(key, value)
|
|
339
541
|
return unless key && value
|
|
340
542
|
return if Appsignal.config[:filter_metadata].include?(key.to_s)
|
|
@@ -342,46 +544,29 @@ module Appsignal
|
|
|
342
544
|
@ext.set_metadata(key, value)
|
|
343
545
|
end
|
|
344
546
|
|
|
547
|
+
# @deprecated Use one of the set_tags, set_params, set_session_data,
|
|
548
|
+
# set_params or set_custom_data helpers instead.
|
|
549
|
+
# @api private
|
|
345
550
|
def set_sample_data(key, data)
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
"Invalid sample data for '#{key}'. Value is not an Array or Hash: '#{data.inspect}'"
|
|
351
|
-
)
|
|
352
|
-
return
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
@ext.set_sample_data(
|
|
356
|
-
key.to_s,
|
|
357
|
-
Appsignal::Utils::Data.generate(data)
|
|
551
|
+
Appsignal::Utils::StdoutAndLoggerMessage.warning(
|
|
552
|
+
"Appsignal::Transaction#set_sample_data is deprecated. " \
|
|
553
|
+
"Please use one of the instrumentation helpers: set_tags, " \
|
|
554
|
+
"set_params, set_session_data, set_params or set_custom_data."
|
|
358
555
|
)
|
|
359
|
-
|
|
360
|
-
begin
|
|
361
|
-
inspected_data = data.inspect
|
|
362
|
-
Appsignal.internal_logger.error(
|
|
363
|
-
"Error generating data (#{e.class}: #{e.message}) for '#{inspected_data}'"
|
|
364
|
-
)
|
|
365
|
-
rescue => e
|
|
366
|
-
Appsignal.internal_logger.error(
|
|
367
|
-
"Error generating data (#{e.class}: #{e.message}). Can't inspect data."
|
|
368
|
-
)
|
|
369
|
-
end
|
|
556
|
+
_set_sample_data(key, data)
|
|
370
557
|
end
|
|
371
558
|
|
|
559
|
+
# @deprecated No replacement.
|
|
560
|
+
# @api private
|
|
372
561
|
def sample_data
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
:tags => sanitized_tags,
|
|
379
|
-
:breadcrumbs => breadcrumbs
|
|
380
|
-
}.each do |key, data|
|
|
381
|
-
set_sample_data(key, data)
|
|
382
|
-
end
|
|
562
|
+
Appsignal::Utils::StdoutAndLoggerMessage.warning(
|
|
563
|
+
"Appsignal::Transaction#sample_data is deprecated. " \
|
|
564
|
+
"Please remove any calls to this method."
|
|
565
|
+
)
|
|
566
|
+
_sample_data
|
|
383
567
|
end
|
|
384
568
|
|
|
569
|
+
# @see Appsignal::Helpers::Instrumentation#set_error
|
|
385
570
|
def set_error(error)
|
|
386
571
|
unless error.is_a?(Exception)
|
|
387
572
|
Appsignal.internal_logger.error "Appsignal::Transaction#set_error: Cannot set error. " \
|
|
@@ -428,19 +613,23 @@ module Appsignal
|
|
|
428
613
|
|
|
429
614
|
causes_sample_data.last[:is_root_cause] = false if root_cause_missing
|
|
430
615
|
|
|
431
|
-
|
|
616
|
+
_set_sample_data(
|
|
432
617
|
"error_causes",
|
|
433
618
|
causes_sample_data
|
|
434
619
|
)
|
|
435
620
|
end
|
|
436
621
|
alias_method :add_exception, :set_error
|
|
437
622
|
|
|
623
|
+
# @see Helpers::Instrumentation#instrument
|
|
624
|
+
# @api private
|
|
438
625
|
def start_event
|
|
439
626
|
return if paused?
|
|
440
627
|
|
|
441
628
|
@ext.start_event(0)
|
|
442
629
|
end
|
|
443
630
|
|
|
631
|
+
# @see Helpers::Instrumentation#instrument
|
|
632
|
+
# @api private
|
|
444
633
|
def finish_event(name, title, body, body_format = Appsignal::EventFormatter::DEFAULT)
|
|
445
634
|
return if paused?
|
|
446
635
|
|
|
@@ -453,6 +642,8 @@ module Appsignal
|
|
|
453
642
|
)
|
|
454
643
|
end
|
|
455
644
|
|
|
645
|
+
# @see Helpers::Instrumentation#instrument
|
|
646
|
+
# @api private
|
|
456
647
|
def record_event(name, title, body, duration, body_format = Appsignal::EventFormatter::DEFAULT)
|
|
457
648
|
return if paused?
|
|
458
649
|
|
|
@@ -466,6 +657,7 @@ module Appsignal
|
|
|
466
657
|
)
|
|
467
658
|
end
|
|
468
659
|
|
|
660
|
+
# @see Helpers::Instrumentation#instrument
|
|
469
661
|
def instrument(name, title = nil, body = nil, body_format = Appsignal::EventFormatter::DEFAULT)
|
|
470
662
|
start_event
|
|
471
663
|
yield if block_given?
|
|
@@ -479,7 +671,8 @@ module Appsignal
|
|
|
479
671
|
end
|
|
480
672
|
alias_method :to_hash, :to_h
|
|
481
673
|
|
|
482
|
-
|
|
674
|
+
# @api private
|
|
675
|
+
class InternalGenericRequest
|
|
483
676
|
attr_reader :env
|
|
484
677
|
|
|
485
678
|
def initialize(env)
|
|
@@ -491,8 +684,64 @@ module Appsignal
|
|
|
491
684
|
end
|
|
492
685
|
end
|
|
493
686
|
|
|
687
|
+
# @deprecated Use the instrumentation helpers to set metadata on the
|
|
688
|
+
# transaction, rather than rely on the GenericRequest automation. See the
|
|
689
|
+
# {Helpers::Instrumentation} module for a list of helpers.
|
|
690
|
+
# @api private
|
|
691
|
+
class GenericRequest < InternalGenericRequest
|
|
692
|
+
def initialize(_env)
|
|
693
|
+
Appsignal::Utils::StdoutAndLoggerMessage.warning(
|
|
694
|
+
"The use of Appsignal::Transaction::GenericRequest is deprecated. " \
|
|
695
|
+
"Use the `Appsignal.set_*` helpers instead. " \
|
|
696
|
+
"https://docs.appsignal.com/guides/custom-data/sample-data.html"
|
|
697
|
+
)
|
|
698
|
+
super
|
|
699
|
+
end
|
|
700
|
+
end
|
|
701
|
+
|
|
494
702
|
private
|
|
495
703
|
|
|
704
|
+
def _set_sample_data(key, data)
|
|
705
|
+
return unless key && data
|
|
706
|
+
|
|
707
|
+
if !data.is_a?(Array) && !data.is_a?(Hash)
|
|
708
|
+
Appsignal.internal_logger.error(
|
|
709
|
+
"Invalid sample data for '#{key}'. Value is not an Array or Hash: '#{data.inspect}'"
|
|
710
|
+
)
|
|
711
|
+
return
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
@ext.set_sample_data(
|
|
715
|
+
key.to_s,
|
|
716
|
+
Appsignal::Utils::Data.generate(data)
|
|
717
|
+
)
|
|
718
|
+
rescue RuntimeError => e
|
|
719
|
+
begin
|
|
720
|
+
inspected_data = data.inspect
|
|
721
|
+
Appsignal.internal_logger.error(
|
|
722
|
+
"Error generating data (#{e.class}: #{e.message}) for '#{inspected_data}'"
|
|
723
|
+
)
|
|
724
|
+
rescue => e
|
|
725
|
+
Appsignal.internal_logger.error(
|
|
726
|
+
"Error generating data (#{e.class}: #{e.message}). Can't inspect data."
|
|
727
|
+
)
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
def _sample_data
|
|
732
|
+
{
|
|
733
|
+
:params => sanitized_params,
|
|
734
|
+
:environment => sanitized_environment,
|
|
735
|
+
:session_data => sanitized_session_data,
|
|
736
|
+
:metadata => sanitized_metadata,
|
|
737
|
+
:tags => sanitized_tags,
|
|
738
|
+
:breadcrumbs => breadcrumbs,
|
|
739
|
+
:custom_data => custom_data
|
|
740
|
+
}.each do |key, data|
|
|
741
|
+
_set_sample_data(key, data)
|
|
742
|
+
end
|
|
743
|
+
end
|
|
744
|
+
|
|
496
745
|
# Returns calculated background queue start time in milliseconds, based on
|
|
497
746
|
# environment values.
|
|
498
747
|
#
|
|
@@ -516,25 +765,7 @@ module Appsignal
|
|
|
516
765
|
# @return [Integer] queue start in milliseconds.
|
|
517
766
|
def http_queue_start
|
|
518
767
|
env = environment
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
env_var = env["HTTP_X_QUEUE_START"] || env["HTTP_X_REQUEST_START"]
|
|
522
|
-
return unless env_var
|
|
523
|
-
|
|
524
|
-
cleaned_value = env_var.tr("^0-9", "")
|
|
525
|
-
return if cleaned_value.empty?
|
|
526
|
-
|
|
527
|
-
value = cleaned_value.to_i
|
|
528
|
-
if value > 4_102_441_200_000
|
|
529
|
-
# Value is in microseconds. Transform to milliseconds.
|
|
530
|
-
value / 1_000
|
|
531
|
-
elsif value < 946_681_200_000
|
|
532
|
-
# Value is too low to be plausible
|
|
533
|
-
nil
|
|
534
|
-
else
|
|
535
|
-
# Value is in milliseconds
|
|
536
|
-
value
|
|
537
|
-
end
|
|
768
|
+
Appsignal::Rack::Utils.queue_start_from(env)
|
|
538
769
|
end
|
|
539
770
|
|
|
540
771
|
def sanitized_params
|
|
@@ -550,28 +781,25 @@ module Appsignal
|
|
|
550
781
|
begin
|
|
551
782
|
request.send options[:params_method]
|
|
552
783
|
rescue => e
|
|
553
|
-
|
|
554
|
-
Appsignal.internal_logger.debug "Exception while getting params: #{e}"
|
|
784
|
+
Appsignal.internal_logger.warn "Exception while getting params: #{e}"
|
|
555
785
|
nil
|
|
556
786
|
end
|
|
557
787
|
end
|
|
558
788
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
# @return [Hash<String, Object>]
|
|
566
|
-
def sanitized_environment
|
|
567
|
-
env = environment
|
|
568
|
-
return if env.empty?
|
|
569
|
-
|
|
570
|
-
{}.tap do |out|
|
|
571
|
-
Appsignal.config[:request_headers].each do |key|
|
|
572
|
-
out[key] = env[key] if env[key]
|
|
789
|
+
def session_data
|
|
790
|
+
if @session_data
|
|
791
|
+
if @session_data.respond_to? :call
|
|
792
|
+
@session_data.call
|
|
793
|
+
else
|
|
794
|
+
@session_data
|
|
573
795
|
end
|
|
796
|
+
elsif request.respond_to?(:session)
|
|
797
|
+
request.session
|
|
574
798
|
end
|
|
799
|
+
rescue => e
|
|
800
|
+
Appsignal.internal_logger.error \
|
|
801
|
+
"Exception while fetching session data: #{e.class}: #{e}"
|
|
802
|
+
nil
|
|
575
803
|
end
|
|
576
804
|
|
|
577
805
|
# Returns sanitized session data.
|
|
@@ -583,23 +811,21 @@ module Appsignal
|
|
|
583
811
|
# @return [nil] if the {#request} session data is `nil`.
|
|
584
812
|
# @return [Hash<String, Object>]
|
|
585
813
|
def sanitized_session_data
|
|
586
|
-
return
|
|
587
|
-
!request.respond_to?(:session)
|
|
588
|
-
|
|
589
|
-
session = request.session
|
|
590
|
-
return unless session
|
|
814
|
+
return unless Appsignal.config[:send_session_data]
|
|
591
815
|
|
|
592
816
|
Appsignal::Utils::HashSanitizer.sanitize(
|
|
593
|
-
|
|
817
|
+
session_data&.to_hash, Appsignal.config[:filter_session_data]
|
|
594
818
|
)
|
|
595
819
|
end
|
|
596
820
|
|
|
597
|
-
# Returns sanitized metadata set
|
|
598
|
-
# {#environment}.
|
|
821
|
+
# Returns sanitized metadata set on the request environment.
|
|
599
822
|
#
|
|
600
823
|
# @return [Hash<String, Object>]
|
|
601
824
|
def sanitized_metadata
|
|
602
|
-
|
|
825
|
+
env = environment
|
|
826
|
+
return unless env
|
|
827
|
+
|
|
828
|
+
metadata = env[:metadata]
|
|
603
829
|
return unless metadata
|
|
604
830
|
|
|
605
831
|
metadata
|
|
@@ -607,17 +833,40 @@ module Appsignal
|
|
|
607
833
|
.reject { |key, _value| Appsignal.config[:filter_metadata].include?(key) }
|
|
608
834
|
end
|
|
609
835
|
|
|
610
|
-
|
|
836
|
+
def environment
|
|
837
|
+
if @headers
|
|
838
|
+
if @headers.respond_to? :call
|
|
839
|
+
@headers.call
|
|
840
|
+
else
|
|
841
|
+
@headers
|
|
842
|
+
end
|
|
843
|
+
elsif request.respond_to?(:env)
|
|
844
|
+
request.env
|
|
845
|
+
end
|
|
846
|
+
rescue => e
|
|
847
|
+
Appsignal.internal_logger.error \
|
|
848
|
+
"Exception while fetching headers: #{e.class}: #{e}"
|
|
849
|
+
nil
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
# Returns sanitized environment for a transaction.
|
|
611
853
|
#
|
|
612
|
-
#
|
|
613
|
-
#
|
|
854
|
+
# The environment of a transaction can contain a lot of information, not
|
|
855
|
+
# all of it useful for debugging.
|
|
614
856
|
#
|
|
857
|
+
# @return [nil] if no environment is present.
|
|
615
858
|
# @return [Hash<String, Object>]
|
|
616
|
-
def
|
|
617
|
-
|
|
618
|
-
return
|
|
859
|
+
def sanitized_environment
|
|
860
|
+
env = environment
|
|
861
|
+
return unless env
|
|
862
|
+
return unless env.respond_to?(:empty?)
|
|
863
|
+
return if env.empty?
|
|
619
864
|
|
|
620
|
-
|
|
865
|
+
{}.tap do |out|
|
|
866
|
+
Appsignal.config[:request_headers].each do |key|
|
|
867
|
+
out[key] = env[key] if env[key]
|
|
868
|
+
end
|
|
869
|
+
end
|
|
621
870
|
end
|
|
622
871
|
|
|
623
872
|
# Only keep tags if they meet the following criteria:
|