appsignal 3.10.0-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/.rubocop.yml +1 -1
- data/CHANGELOG.md +88 -0
- data/Gemfile +1 -0
- data/benchmark.rake +99 -42
- data/lib/appsignal/cli/demo.rb +0 -1
- data/lib/appsignal/config.rb +54 -98
- data/lib/appsignal/demo.rb +15 -20
- 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 +331 -19
- data/lib/appsignal/hooks/action_cable.rb +21 -16
- data/lib/appsignal/hooks/active_job.rb +14 -8
- 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/que.rb +13 -20
- data/lib/appsignal/integrations/railtie.rb +1 -1
- data/lib/appsignal/integrations/rake.rb +1 -5
- 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 -15
- data/lib/appsignal/integrations/unicorn.rb +1 -0
- data/lib/appsignal/integrations/webmachine.rb +2 -5
- 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 +18 -12
- data/lib/appsignal/rack/event_handler.rb +39 -8
- data/lib/appsignal/rack/generic_instrumentation.rb +1 -0
- data/lib/appsignal/rack/grape_middleware.rb +2 -1
- data/lib/appsignal/rack/streaming_listener.rb +1 -0
- data/lib/appsignal/rack.rb +29 -0
- data/lib/appsignal/span.rb +1 -0
- data/lib/appsignal/transaction.rb +308 -101
- 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 +6 -5
- data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
- data/spec/lib/appsignal/config_spec.rb +138 -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/shoryuken_spec.rb +0 -171
- data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
- 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/webmachine_spec.rb +13 -1
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +48 -3
- data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -10
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
- data/spec/lib/appsignal/rack_spec.rb +63 -0
- data/spec/lib/appsignal/transaction_spec.rb +1634 -1071
- 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 +323 -10
- data/spec/support/helpers/transaction_helpers.rb +44 -20
- data/spec/support/matchers/transaction.rb +15 -1
- data/spec/support/testing.rb +1 -1
- metadata +6 -2
|
@@ -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,14 +127,21 @@ 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 = {}
|
|
@@ -90,6 +151,8 @@ module Appsignal
|
|
|
90
151
|
@options = options
|
|
91
152
|
@options[:params_method] ||= :params
|
|
92
153
|
@params = nil
|
|
154
|
+
@session_data = nil
|
|
155
|
+
@headers = nil
|
|
93
156
|
|
|
94
157
|
@ext = Appsignal::Extension.start_transaction(
|
|
95
158
|
@transaction_id,
|
|
@@ -108,38 +171,46 @@ module Appsignal
|
|
|
108
171
|
"because it was manually discarded."
|
|
109
172
|
return
|
|
110
173
|
end
|
|
111
|
-
|
|
174
|
+
_sample_data if @ext.finish(0)
|
|
112
175
|
@ext.complete
|
|
113
176
|
end
|
|
114
177
|
|
|
178
|
+
# @api private
|
|
115
179
|
def pause!
|
|
116
180
|
@paused = true
|
|
117
181
|
end
|
|
118
182
|
|
|
183
|
+
# @api private
|
|
119
184
|
def resume!
|
|
120
185
|
@paused = false
|
|
121
186
|
end
|
|
122
187
|
|
|
188
|
+
# @api private
|
|
123
189
|
def paused?
|
|
124
190
|
@paused == true
|
|
125
191
|
end
|
|
126
192
|
|
|
193
|
+
# @api private
|
|
127
194
|
def discard!
|
|
128
195
|
@discarded = true
|
|
129
196
|
end
|
|
130
197
|
|
|
198
|
+
# @api private
|
|
131
199
|
def restore!
|
|
132
200
|
@discarded = false
|
|
133
201
|
end
|
|
134
202
|
|
|
203
|
+
# @api private
|
|
135
204
|
def discarded?
|
|
136
205
|
@discarded == true
|
|
137
206
|
end
|
|
138
207
|
|
|
208
|
+
# @api private
|
|
139
209
|
def store(key)
|
|
140
210
|
@store[key]
|
|
141
211
|
end
|
|
142
212
|
|
|
213
|
+
# @api private
|
|
143
214
|
def params
|
|
144
215
|
parameters = @params || request_params
|
|
145
216
|
|
|
@@ -148,6 +219,9 @@ module Appsignal
|
|
|
148
219
|
else
|
|
149
220
|
parameters
|
|
150
221
|
end
|
|
222
|
+
rescue => e
|
|
223
|
+
Appsignal.internal_logger.error("Exception while fetching params: #{e.class}: #{e}")
|
|
224
|
+
nil
|
|
151
225
|
end
|
|
152
226
|
|
|
153
227
|
# Set parameters on the transaction.
|
|
@@ -166,7 +240,7 @@ module Appsignal
|
|
|
166
240
|
# @yield This block is called when the transaction is sampled. The block's
|
|
167
241
|
# return value will become the new parameters.
|
|
168
242
|
# @return [void]
|
|
169
|
-
# @see
|
|
243
|
+
# @see Helpers::Instrumentation#set_params
|
|
170
244
|
def set_params(given_params = nil, &block)
|
|
171
245
|
@params = block if block
|
|
172
246
|
@params = given_params if given_params
|
|
@@ -191,7 +265,9 @@ module Appsignal
|
|
|
191
265
|
# @yield This block is called when the transaction is sampled. The block's
|
|
192
266
|
# return value will become the new parameters.
|
|
193
267
|
# @return [void]
|
|
194
|
-
#
|
|
268
|
+
#
|
|
269
|
+
# @see #set_params
|
|
270
|
+
# @see Helpers::Instrumentation#set_params_if_nil
|
|
195
271
|
def set_params_if_nil(given_params = nil, &block)
|
|
196
272
|
set_params(given_params, &block) unless @params
|
|
197
273
|
end
|
|
@@ -214,6 +290,84 @@ module Appsignal
|
|
|
214
290
|
@tags.merge!(given_tags)
|
|
215
291
|
end
|
|
216
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
|
+
|
|
217
371
|
# Set custom data on the transaction.
|
|
218
372
|
#
|
|
219
373
|
# When this method is called multiple times, it will overwrite the
|
|
@@ -325,6 +479,8 @@ module Appsignal
|
|
|
325
479
|
@ext.set_namespace(namespace)
|
|
326
480
|
end
|
|
327
481
|
|
|
482
|
+
# @deprecated Use the {#set_action} helper.
|
|
483
|
+
# @api private
|
|
328
484
|
def set_http_or_background_action(from = request.params)
|
|
329
485
|
return unless from
|
|
330
486
|
|
|
@@ -337,8 +493,6 @@ module Appsignal
|
|
|
337
493
|
|
|
338
494
|
# Set queue start time for transaction.
|
|
339
495
|
#
|
|
340
|
-
# Most commononly called by {set_http_or_background_queue_start}.
|
|
341
|
-
#
|
|
342
496
|
# @param start [Integer] Queue start time in milliseconds.
|
|
343
497
|
# @raise [RangeError] When the queue start time value is too big, this
|
|
344
498
|
# method raises a RangeError.
|
|
@@ -368,14 +522,21 @@ module Appsignal
|
|
|
368
522
|
# AppSignal as seconds.
|
|
369
523
|
#
|
|
370
524
|
# @see https://docs.appsignal.com/ruby/instrumentation/request-queue-time.html
|
|
525
|
+
# @deprecated Use {#set_queue_start} instead.
|
|
371
526
|
# @return [void]
|
|
372
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
|
+
|
|
373
533
|
start = http_queue_start || background_queue_start
|
|
374
534
|
return unless start
|
|
375
535
|
|
|
376
536
|
set_queue_start(start)
|
|
377
537
|
end
|
|
378
538
|
|
|
539
|
+
# @api private
|
|
379
540
|
def set_metadata(key, value)
|
|
380
541
|
return unless key && value
|
|
381
542
|
return if Appsignal.config[:filter_metadata].include?(key.to_s)
|
|
@@ -383,47 +544,29 @@ module Appsignal
|
|
|
383
544
|
@ext.set_metadata(key, value)
|
|
384
545
|
end
|
|
385
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
|
|
386
550
|
def set_sample_data(key, data)
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
"Invalid sample data for '#{key}'. Value is not an Array or Hash: '#{data.inspect}'"
|
|
392
|
-
)
|
|
393
|
-
return
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
@ext.set_sample_data(
|
|
397
|
-
key.to_s,
|
|
398
|
-
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."
|
|
399
555
|
)
|
|
400
|
-
|
|
401
|
-
begin
|
|
402
|
-
inspected_data = data.inspect
|
|
403
|
-
Appsignal.internal_logger.error(
|
|
404
|
-
"Error generating data (#{e.class}: #{e.message}) for '#{inspected_data}'"
|
|
405
|
-
)
|
|
406
|
-
rescue => e
|
|
407
|
-
Appsignal.internal_logger.error(
|
|
408
|
-
"Error generating data (#{e.class}: #{e.message}). Can't inspect data."
|
|
409
|
-
)
|
|
410
|
-
end
|
|
556
|
+
_set_sample_data(key, data)
|
|
411
557
|
end
|
|
412
558
|
|
|
559
|
+
# @deprecated No replacement.
|
|
560
|
+
# @api private
|
|
413
561
|
def sample_data
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
:tags => sanitized_tags,
|
|
420
|
-
:breadcrumbs => breadcrumbs,
|
|
421
|
-
:custom_data => custom_data
|
|
422
|
-
}.each do |key, data|
|
|
423
|
-
set_sample_data(key, data)
|
|
424
|
-
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
|
|
425
567
|
end
|
|
426
568
|
|
|
569
|
+
# @see Appsignal::Helpers::Instrumentation#set_error
|
|
427
570
|
def set_error(error)
|
|
428
571
|
unless error.is_a?(Exception)
|
|
429
572
|
Appsignal.internal_logger.error "Appsignal::Transaction#set_error: Cannot set error. " \
|
|
@@ -470,19 +613,23 @@ module Appsignal
|
|
|
470
613
|
|
|
471
614
|
causes_sample_data.last[:is_root_cause] = false if root_cause_missing
|
|
472
615
|
|
|
473
|
-
|
|
616
|
+
_set_sample_data(
|
|
474
617
|
"error_causes",
|
|
475
618
|
causes_sample_data
|
|
476
619
|
)
|
|
477
620
|
end
|
|
478
621
|
alias_method :add_exception, :set_error
|
|
479
622
|
|
|
623
|
+
# @see Helpers::Instrumentation#instrument
|
|
624
|
+
# @api private
|
|
480
625
|
def start_event
|
|
481
626
|
return if paused?
|
|
482
627
|
|
|
483
628
|
@ext.start_event(0)
|
|
484
629
|
end
|
|
485
630
|
|
|
631
|
+
# @see Helpers::Instrumentation#instrument
|
|
632
|
+
# @api private
|
|
486
633
|
def finish_event(name, title, body, body_format = Appsignal::EventFormatter::DEFAULT)
|
|
487
634
|
return if paused?
|
|
488
635
|
|
|
@@ -495,6 +642,8 @@ module Appsignal
|
|
|
495
642
|
)
|
|
496
643
|
end
|
|
497
644
|
|
|
645
|
+
# @see Helpers::Instrumentation#instrument
|
|
646
|
+
# @api private
|
|
498
647
|
def record_event(name, title, body, duration, body_format = Appsignal::EventFormatter::DEFAULT)
|
|
499
648
|
return if paused?
|
|
500
649
|
|
|
@@ -508,6 +657,7 @@ module Appsignal
|
|
|
508
657
|
)
|
|
509
658
|
end
|
|
510
659
|
|
|
660
|
+
# @see Helpers::Instrumentation#instrument
|
|
511
661
|
def instrument(name, title = nil, body = nil, body_format = Appsignal::EventFormatter::DEFAULT)
|
|
512
662
|
start_event
|
|
513
663
|
yield if block_given?
|
|
@@ -521,7 +671,8 @@ module Appsignal
|
|
|
521
671
|
end
|
|
522
672
|
alias_method :to_hash, :to_h
|
|
523
673
|
|
|
524
|
-
|
|
674
|
+
# @api private
|
|
675
|
+
class InternalGenericRequest
|
|
525
676
|
attr_reader :env
|
|
526
677
|
|
|
527
678
|
def initialize(env)
|
|
@@ -533,8 +684,64 @@ module Appsignal
|
|
|
533
684
|
end
|
|
534
685
|
end
|
|
535
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
|
+
|
|
536
702
|
private
|
|
537
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
|
+
|
|
538
745
|
# Returns calculated background queue start time in milliseconds, based on
|
|
539
746
|
# environment values.
|
|
540
747
|
#
|
|
@@ -558,25 +765,7 @@ module Appsignal
|
|
|
558
765
|
# @return [Integer] queue start in milliseconds.
|
|
559
766
|
def http_queue_start
|
|
560
767
|
env = environment
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
env_var = env["HTTP_X_QUEUE_START"] || env["HTTP_X_REQUEST_START"]
|
|
564
|
-
return unless env_var
|
|
565
|
-
|
|
566
|
-
cleaned_value = env_var.tr("^0-9", "")
|
|
567
|
-
return if cleaned_value.empty?
|
|
568
|
-
|
|
569
|
-
value = cleaned_value.to_i
|
|
570
|
-
if value > 4_102_441_200_000
|
|
571
|
-
# Value is in microseconds. Transform to milliseconds.
|
|
572
|
-
value / 1_000
|
|
573
|
-
elsif value < 946_681_200_000
|
|
574
|
-
# Value is too low to be plausible
|
|
575
|
-
nil
|
|
576
|
-
else
|
|
577
|
-
# Value is in milliseconds
|
|
578
|
-
value
|
|
579
|
-
end
|
|
768
|
+
Appsignal::Rack::Utils.queue_start_from(env)
|
|
580
769
|
end
|
|
581
770
|
|
|
582
771
|
def sanitized_params
|
|
@@ -592,28 +781,25 @@ module Appsignal
|
|
|
592
781
|
begin
|
|
593
782
|
request.send options[:params_method]
|
|
594
783
|
rescue => e
|
|
595
|
-
|
|
596
|
-
Appsignal.internal_logger.debug "Exception while getting params: #{e}"
|
|
784
|
+
Appsignal.internal_logger.warn "Exception while getting params: #{e}"
|
|
597
785
|
nil
|
|
598
786
|
end
|
|
599
787
|
end
|
|
600
788
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
# @return [Hash<String, Object>]
|
|
608
|
-
def sanitized_environment
|
|
609
|
-
env = environment
|
|
610
|
-
return if env.empty?
|
|
611
|
-
|
|
612
|
-
{}.tap do |out|
|
|
613
|
-
Appsignal.config[:request_headers].each do |key|
|
|
614
|
-
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
|
|
615
795
|
end
|
|
796
|
+
elsif request.respond_to?(:session)
|
|
797
|
+
request.session
|
|
616
798
|
end
|
|
799
|
+
rescue => e
|
|
800
|
+
Appsignal.internal_logger.error \
|
|
801
|
+
"Exception while fetching session data: #{e.class}: #{e}"
|
|
802
|
+
nil
|
|
617
803
|
end
|
|
618
804
|
|
|
619
805
|
# Returns sanitized session data.
|
|
@@ -625,23 +811,21 @@ module Appsignal
|
|
|
625
811
|
# @return [nil] if the {#request} session data is `nil`.
|
|
626
812
|
# @return [Hash<String, Object>]
|
|
627
813
|
def sanitized_session_data
|
|
628
|
-
return
|
|
629
|
-
!request.respond_to?(:session)
|
|
630
|
-
|
|
631
|
-
session = request.session
|
|
632
|
-
return unless session
|
|
814
|
+
return unless Appsignal.config[:send_session_data]
|
|
633
815
|
|
|
634
816
|
Appsignal::Utils::HashSanitizer.sanitize(
|
|
635
|
-
|
|
817
|
+
session_data&.to_hash, Appsignal.config[:filter_session_data]
|
|
636
818
|
)
|
|
637
819
|
end
|
|
638
820
|
|
|
639
|
-
# Returns sanitized metadata set
|
|
640
|
-
# {#environment}.
|
|
821
|
+
# Returns sanitized metadata set on the request environment.
|
|
641
822
|
#
|
|
642
823
|
# @return [Hash<String, Object>]
|
|
643
824
|
def sanitized_metadata
|
|
644
|
-
|
|
825
|
+
env = environment
|
|
826
|
+
return unless env
|
|
827
|
+
|
|
828
|
+
metadata = env[:metadata]
|
|
645
829
|
return unless metadata
|
|
646
830
|
|
|
647
831
|
metadata
|
|
@@ -649,17 +833,40 @@ module Appsignal
|
|
|
649
833
|
.reject { |key, _value| Appsignal.config[:filter_metadata].include?(key) }
|
|
650
834
|
end
|
|
651
835
|
|
|
652
|
-
|
|
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.
|
|
653
853
|
#
|
|
654
|
-
#
|
|
655
|
-
#
|
|
854
|
+
# The environment of a transaction can contain a lot of information, not
|
|
855
|
+
# all of it useful for debugging.
|
|
656
856
|
#
|
|
857
|
+
# @return [nil] if no environment is present.
|
|
657
858
|
# @return [Hash<String, Object>]
|
|
658
|
-
def
|
|
659
|
-
|
|
660
|
-
return
|
|
859
|
+
def sanitized_environment
|
|
860
|
+
env = environment
|
|
861
|
+
return unless env
|
|
862
|
+
return unless env.respond_to?(:empty?)
|
|
863
|
+
return if env.empty?
|
|
661
864
|
|
|
662
|
-
|
|
865
|
+
{}.tap do |out|
|
|
866
|
+
Appsignal.config[:request_headers].each do |key|
|
|
867
|
+
out[key] = env[key] if env[key]
|
|
868
|
+
end
|
|
869
|
+
end
|
|
663
870
|
end
|
|
664
871
|
|
|
665
872
|
# Only keep tags if they meet the following criteria:
|
data/lib/appsignal/utils/data.rb
CHANGED
|
@@ -2,20 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Appsignal
|
|
4
4
|
module Utils
|
|
5
|
-
# Subclass of logger with method to only log a warning once
|
|
6
|
-
# prevents the local log from filling up with repeated messages.
|
|
7
5
|
class IntegrationLogger < ::Logger
|
|
8
|
-
def seen_keys
|
|
9
|
-
@seen_keys ||= Set.new
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def warn_once_then_debug(key, message)
|
|
13
|
-
if seen_keys.add?(key).nil?
|
|
14
|
-
debug message
|
|
15
|
-
else
|
|
16
|
-
warn message
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
6
|
end
|
|
20
7
|
end
|
|
21
8
|
end
|