appsignal 0.12.beta.31 → 0.12.beta.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/Rakefile +1 -0
- data/benchmark.rake +20 -20
- data/ext/appsignal_extension.c +31 -23
- data/gemfiles/padrino.gemfile +7 -0
- data/lib/appsignal.rb +50 -27
- data/lib/appsignal/capistrano.rb +2 -1
- data/lib/appsignal/config.rb +94 -39
- data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +12 -17
- data/lib/appsignal/integrations/padrino.rb +65 -0
- data/lib/appsignal/integrations/rails.rb +4 -2
- data/lib/appsignal/integrations/rake.rb +30 -0
- data/lib/appsignal/integrations/sidekiq.rb +2 -2
- data/lib/appsignal/integrations/sinatra.rb +0 -1
- data/lib/appsignal/js_exception_transaction.rb +4 -9
- data/lib/appsignal/params_sanitizer.rb +8 -5
- data/lib/appsignal/rack/rails_instrumentation.rb +41 -0
- data/lib/appsignal/rack/sinatra_instrumentation.rb +31 -24
- data/lib/appsignal/subscriber.rb +2 -9
- data/lib/appsignal/transaction.rb +86 -75
- data/lib/appsignal/transmitter.rb +30 -3
- data/lib/appsignal/version.rb +2 -2
- data/spec/lib/appsignal/cli_spec.rb +1 -1
- data/spec/lib/appsignal/config_spec.rb +38 -131
- data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +27 -29
- data/spec/lib/appsignal/extension_spec.rb +11 -29
- data/spec/lib/appsignal/integrations/padrino_spec.rb +191 -0
- data/spec/lib/appsignal/integrations/rails_spec.rb +3 -4
- data/spec/lib/appsignal/integrations/rake_spec.rb +78 -0
- data/spec/lib/appsignal/integrations/resque_spec.rb +2 -2
- data/spec/lib/appsignal/integrations/sequel_spec.rb +2 -3
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +22 -5
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -6
- data/spec/lib/appsignal/js_exception_transaction_spec.rb +4 -6
- data/spec/lib/appsignal/params_sanitizer_spec.rb +27 -11
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +79 -0
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +71 -71
- data/spec/lib/appsignal/subscriber_spec.rb +3 -37
- data/spec/lib/appsignal/transaction_spec.rb +290 -155
- data/spec/lib/appsignal/transmitter_spec.rb +10 -0
- data/spec/lib/appsignal_spec.rb +80 -47
- data/spec/spec_helper.rb +21 -2
- data/spec/support/helpers/env_helpers.rb +31 -0
- data/spec/support/helpers/notification_helpers.rb +1 -30
- data/spec/support/helpers/transaction_helpers.rb +7 -7
- data/spec/support/project_fixture/config/appsignal.yml +2 -0
- metadata +14 -8
- data/lib/appsignal/rack/instrumentation.rb +0 -32
- data/lib/appsignal/rack/listener.rb +0 -32
- data/spec/lib/appsignal/rack/instrumentation_spec.rb +0 -72
- data/spec/lib/appsignal/rack/listener_spec.rb +0 -104
@@ -4,13 +4,12 @@ module Appsignal
|
|
4
4
|
class SqlFormatter < Appsignal::EventFormatter
|
5
5
|
register 'sql.active_record'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
SANITIZED_VALUE = '\1?\2'.freeze
|
7
|
+
SINGLE_QUOTED_STRING = /'(.?|[^'])*'/.freeze
|
8
|
+
DOUBLE_QUOTED_STRING = /"(.?|[^"])*"/.freeze
|
9
|
+
IN_OPERATOR_CONTENT = /(IN \()[^\)]+(\))/.freeze
|
10
|
+
NUMERIC = /\d*\.?\d+/.freeze
|
11
|
+
REPLACEMENT = '\1?\2'.freeze
|
12
|
+
SCHEMA = 'SCHEMA'.freeze
|
14
13
|
|
15
14
|
attr_reader :adapter_uses_double_quoted_table_names
|
16
15
|
|
@@ -25,23 +24,19 @@ module Appsignal
|
|
25
24
|
def format(payload)
|
26
25
|
return nil if schema_query?(payload) || !payload[:sql]
|
27
26
|
sql_string = payload[:sql].dup
|
28
|
-
|
29
|
-
sql_string.gsub!(
|
30
|
-
sql_string.gsub!(SINGLE_QUOTED_DATA, SANITIZED_VALUE)
|
31
|
-
else
|
32
|
-
sql_string.gsub!(SINGLE_QUOTE, SANITIZED_VALUE)
|
33
|
-
sql_string.gsub!(DOUBLE_QUOTE, SANITIZED_VALUE)
|
34
|
-
sql_string.gsub!(QUOTED_DATA, SANITIZED_VALUE)
|
27
|
+
unless adapter_uses_double_quoted_table_names
|
28
|
+
sql_string.gsub!(DOUBLE_QUOTED_STRING, REPLACEMENT)
|
35
29
|
end
|
36
|
-
sql_string.gsub!(
|
37
|
-
sql_string.gsub!(
|
30
|
+
sql_string.gsub!(SINGLE_QUOTED_STRING, REPLACEMENT)
|
31
|
+
sql_string.gsub!(IN_OPERATOR_CONTENT, REPLACEMENT)
|
32
|
+
sql_string.gsub!(NUMERIC, REPLACEMENT)
|
38
33
|
[payload[:name], sql_string]
|
39
34
|
end
|
40
35
|
|
41
36
|
protected
|
42
37
|
|
43
38
|
def schema_query?(payload)
|
44
|
-
payload[:name] ==
|
39
|
+
payload[:name] == SCHEMA
|
45
40
|
end
|
46
41
|
|
47
42
|
def connection_config
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'appsignal'
|
2
|
+
|
3
|
+
module Appsignal::Integrations
|
4
|
+
module PadrinoPlugin
|
5
|
+
def self.init
|
6
|
+
Appsignal.logger.info("Loading Padrino (#{Padrino::VERSION}) integration")
|
7
|
+
|
8
|
+
root = Padrino.mounted_root
|
9
|
+
Appsignal.config = Appsignal::Config.new(root, Padrino.env)
|
10
|
+
|
11
|
+
Appsignal.start_logger(File.join(root, 'log'))
|
12
|
+
Appsignal.start
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Padrino::Routing::InstanceMethods
|
18
|
+
alias route_without_appsignal route!
|
19
|
+
|
20
|
+
def route!(base=settings, pass_block=nil)
|
21
|
+
if !Appsignal.active? || env['sinatra.static_file']
|
22
|
+
route_without_appsignal(base, pass_block)
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
transaction = Appsignal::Transaction.create(
|
27
|
+
SecureRandom.uuid,
|
28
|
+
Appsignal::Transaction::HTTP_REQUEST,
|
29
|
+
request
|
30
|
+
)
|
31
|
+
begin
|
32
|
+
ActiveSupport::Notifications.instrument('process_action.padrino') do
|
33
|
+
route_without_appsignal(base, pass_block)
|
34
|
+
end
|
35
|
+
rescue => error
|
36
|
+
transaction.set_error(error)
|
37
|
+
raise error
|
38
|
+
ensure
|
39
|
+
transaction.set_action(get_payload_action(request))
|
40
|
+
transaction.set_metadata('path', request.path)
|
41
|
+
transaction.set_metadata('method', request.request_method)
|
42
|
+
transaction.set_http_or_background_queue_start
|
43
|
+
Appsignal::Transaction.complete_current!
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_payload_action(request)
|
48
|
+
# Short-circut is there's no request object to obtain information from
|
49
|
+
return "#{settings.name}" if request.nil?
|
50
|
+
|
51
|
+
# Older versions of Padrino work with a route object
|
52
|
+
route_obj = defined?(request.route_obj) && request.route_obj
|
53
|
+
if route_obj && route_obj.respond_to?(:original_path)
|
54
|
+
return "#{settings.name}:#{request.route_obj.original_path}"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Newer versions expose the action / controller on the request class
|
58
|
+
request_data = request.respond_to?(:action) ? request.action : request.fullpath
|
59
|
+
"#{settings.name}:#{request.controller}##{request_data}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
Padrino.after_load do
|
64
|
+
Appsignal::Integrations::PadrinoPlugin.init
|
65
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
if defined?(::Rails)
|
2
2
|
Appsignal.logger.info("Loading Rails (#{Rails.version}) integration")
|
3
3
|
|
4
|
+
require 'appsignal/rack/rails_instrumentation'
|
5
|
+
|
4
6
|
module Appsignal
|
5
7
|
module Integrations
|
6
8
|
class Railtie < ::Rails::Railtie
|
@@ -21,13 +23,13 @@ if defined?(::Rails)
|
|
21
23
|
|
22
24
|
app.middleware.insert_before(
|
23
25
|
ActionDispatch::RemoteIp,
|
24
|
-
Appsignal::Rack::
|
26
|
+
Appsignal::Rack::RailsInstrumentation
|
25
27
|
)
|
26
28
|
|
27
29
|
if Appsignal.config.active? &&
|
28
30
|
Appsignal.config[:enable_frontend_error_catching] == true
|
29
31
|
app.middleware.insert_before(
|
30
|
-
Appsignal::Rack::
|
32
|
+
Appsignal::Rack::RailsInstrumentation,
|
31
33
|
Appsignal::Rack::JSExceptionCatcher,
|
32
34
|
)
|
33
35
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Rake
|
2
|
+
class Task
|
3
|
+
alias_method :invoke_without_appsignal, :invoke
|
4
|
+
|
5
|
+
def invoke(*args)
|
6
|
+
if Appsignal.active?
|
7
|
+
invoke_with_appsignal(*args)
|
8
|
+
else
|
9
|
+
invoke_without_appsignal(*args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def invoke_with_appsignal(*args)
|
14
|
+
invoke_without_appsignal(*args)
|
15
|
+
rescue => error
|
16
|
+
transaction = Appsignal::Transaction.create(
|
17
|
+
SecureRandom.uuid,
|
18
|
+
Appsignal::Transaction::BACKGROUND_JOB,
|
19
|
+
Appsignal::Transaction::GenericRequest.new(
|
20
|
+
:params => args
|
21
|
+
)
|
22
|
+
)
|
23
|
+
transaction.set_action(name)
|
24
|
+
transaction.set_error(error)
|
25
|
+
transaction.complete!
|
26
|
+
sleep 0.5 # Give us some time to flush to the agent
|
27
|
+
raise error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -15,7 +15,7 @@ if defined?(::Sidekiq)
|
|
15
15
|
def call(worker, item, queue)
|
16
16
|
Appsignal.monitor_transaction(
|
17
17
|
'perform_job.sidekiq',
|
18
|
-
:class => item['class'],
|
18
|
+
:class => item['wrapped'] || item['class'],
|
19
19
|
:method => 'perform',
|
20
20
|
:metadata => formatted_metadata(item),
|
21
21
|
:params => format_args(item['args']),
|
@@ -48,7 +48,7 @@ if defined?(::Sidekiq)
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def truncate(text)
|
51
|
-
text.size >
|
51
|
+
text.size > 200 ? "#{text[0...197]}..." : text
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -5,21 +5,16 @@ module Appsignal
|
|
5
5
|
def initialize(data)
|
6
6
|
@data = data
|
7
7
|
@uuid = SecureRandom.uuid
|
8
|
-
@transaction_index = Appsignal::Extension.start_transaction(@uuid)
|
8
|
+
@transaction_index = Appsignal::Extension.start_transaction(@uuid, Appsignal::Transaction::FRONTEND)
|
9
9
|
|
10
|
-
|
10
|
+
set_action
|
11
11
|
set_metadata
|
12
12
|
set_error
|
13
13
|
set_error_data
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
Appsignal::Extension.
|
18
|
-
@transaction_index,
|
19
|
-
'frontend',
|
20
|
-
@data['action'],
|
21
|
-
0
|
22
|
-
)
|
16
|
+
def set_action
|
17
|
+
Appsignal::Extension.set_transaction_action(@transaction_index, @data['action'])
|
23
18
|
end
|
24
19
|
|
25
20
|
def set_metadata
|
@@ -25,8 +25,10 @@ module Appsignal
|
|
25
25
|
sanitize_hash(value)
|
26
26
|
when Array
|
27
27
|
sanitize_array(value)
|
28
|
-
when Fixnum, String, Symbol
|
28
|
+
when Fixnum, String, Symbol, Float
|
29
29
|
unmodified(value)
|
30
|
+
when TrueClass, FalseClass
|
31
|
+
stringified(value)
|
30
32
|
else
|
31
33
|
inspected(value)
|
32
34
|
end
|
@@ -46,15 +48,16 @@ module Appsignal
|
|
46
48
|
target_array
|
47
49
|
end
|
48
50
|
|
51
|
+
def stringified(value)
|
52
|
+
value.to_s
|
53
|
+
end
|
54
|
+
|
49
55
|
def unmodified(value)
|
50
56
|
value
|
51
57
|
end
|
52
58
|
|
53
59
|
def inspected(value)
|
54
|
-
value.
|
55
|
-
rescue
|
56
|
-
# It turns out that sometimes inspect can fail
|
57
|
-
"#<#{value.class.to_s}/>"
|
60
|
+
"#<#{value.class.to_s}>"
|
58
61
|
end
|
59
62
|
end
|
60
63
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
module Rack
|
5
|
+
class RailsInstrumentation
|
6
|
+
def initialize(app, options = {})
|
7
|
+
Appsignal.logger.debug 'Initializing Appsignal::Rack::RailsInstrumentation'
|
8
|
+
@app, @options = app, options
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
if Appsignal.active?
|
13
|
+
call_with_appsignal_monitoring(env)
|
14
|
+
else
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def call_with_appsignal_monitoring(env)
|
20
|
+
request = ActionDispatch::Request.new(env)
|
21
|
+
transaction = Appsignal::Transaction.create(
|
22
|
+
env['action_dispatch.request_id'],
|
23
|
+
Appsignal::Transaction::HTTP_REQUEST,
|
24
|
+
request
|
25
|
+
)
|
26
|
+
begin
|
27
|
+
@app.call(env)
|
28
|
+
rescue => error
|
29
|
+
transaction.set_error(error)
|
30
|
+
raise error
|
31
|
+
ensure
|
32
|
+
transaction.set_http_or_background_action
|
33
|
+
transaction.set_http_or_background_queue_start
|
34
|
+
transaction.set_metadata('path', request.path)
|
35
|
+
transaction.set_metadata('method', request.request_method)
|
36
|
+
Appsignal::Transaction.complete_current!
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -9,33 +9,40 @@ module Appsignal
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def call(env)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
begin
|
17
|
-
@app.call(env)
|
18
|
-
ensure
|
19
|
-
# This information is available only after the
|
20
|
-
# request has been processed by Sinatra.
|
21
|
-
payload[:action] = env['sinatra.route']
|
22
|
-
end
|
12
|
+
if Appsignal.active?
|
13
|
+
call_with_appsignal_monitoring(env)
|
14
|
+
else
|
15
|
+
@app.call(env)
|
23
16
|
end
|
24
|
-
ensure
|
25
|
-
# In production newer versions of Sinatra don't raise errors, but store
|
26
|
-
# them in the sinatra.error env var.
|
27
|
-
Appsignal::Transaction.current.add_exception(env['sinatra.error']) if env['sinatra.error']
|
28
17
|
end
|
29
18
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
19
|
+
def call_with_appsignal_monitoring(env)
|
20
|
+
if @options[:params_method]
|
21
|
+
env[:params_method] = @options[:params_method]
|
22
|
+
end
|
23
|
+
request = @options.fetch(:request_class, Sinatra::Request).new(env)
|
24
|
+
transaction = Appsignal::Transaction.create(
|
25
|
+
SecureRandom.uuid,
|
26
|
+
Appsignal::Transaction::HTTP_REQUEST,
|
27
|
+
request
|
28
|
+
)
|
29
|
+
begin
|
30
|
+
ActiveSupport::Notifications.instrument('process_action.sinatra') do
|
31
|
+
@app.call(env)
|
32
|
+
end
|
33
|
+
rescue => error
|
34
|
+
transaction.set_error(error)
|
35
|
+
raise error
|
36
|
+
ensure
|
37
|
+
# In production newer versions of Sinatra don't raise errors, but store
|
38
|
+
# them in the sinatra.error env var.
|
39
|
+
transaction.set_error(env['sinatra.error']) if env['sinatra.error']
|
40
|
+
transaction.set_action(env['sinatra.route'])
|
41
|
+
transaction.set_metadata('path', request.path)
|
42
|
+
transaction.set_metadata('method', request.request_method)
|
43
|
+
transaction.set_http_or_background_queue_start
|
44
|
+
Appsignal::Transaction.complete_current!
|
45
|
+
end
|
39
46
|
end
|
40
47
|
end
|
41
48
|
end
|
data/lib/appsignal/subscriber.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Appsignal
|
2
2
|
class Subscriber
|
3
|
-
|
4
|
-
PERFORM_JOB_PREFIX = 'perform_job'.freeze
|
5
|
-
BLANK = ''.freeze
|
3
|
+
BLANK = ''.freeze
|
6
4
|
|
7
5
|
def initialize
|
8
6
|
subscribe
|
@@ -33,18 +31,13 @@ module Appsignal
|
|
33
31
|
|
34
32
|
def start(name, id, payload)
|
35
33
|
return unless transaction = Appsignal::Transaction.current
|
36
|
-
|
37
34
|
return if transaction.paused?
|
35
|
+
|
38
36
|
Appsignal::Extension.start_event(transaction.transaction_index)
|
39
37
|
end
|
40
38
|
|
41
39
|
def finish(name, id, payload)
|
42
40
|
return unless transaction = Appsignal::Transaction.current
|
43
|
-
|
44
|
-
if name.start_with?(PROCESS_ACTION_PREFIX, PERFORM_JOB_PREFIX)
|
45
|
-
transaction.set_root_event(name, payload)
|
46
|
-
end
|
47
|
-
|
48
41
|
return if transaction.paused?
|
49
42
|
|
50
43
|
title, body = Appsignal::EventFormatter.format(name, payload)
|
@@ -2,6 +2,7 @@ module Appsignal
|
|
2
2
|
class Transaction
|
3
3
|
HTTP_REQUEST = 'http_request'.freeze
|
4
4
|
BACKGROUND_JOB = 'background_job'.freeze
|
5
|
+
FRONTEND = 'frontend'.freeze
|
5
6
|
|
6
7
|
# Based on what Rails uses + some variables we'd like to show
|
7
8
|
ENV_METHODS = %w(CONTENT_LENGTH AUTH_TYPE GATEWAY_INTERFACE
|
@@ -15,8 +16,8 @@ module Appsignal
|
|
15
16
|
HTTP_PRAGMA HTTP_REFERER HTTP_X_FORWARDED_FOR HTTP_CLIENT_IP).freeze
|
16
17
|
|
17
18
|
class << self
|
18
|
-
def create(
|
19
|
-
Thread.current[:appsignal_transaction] = Appsignal::Transaction.new(
|
19
|
+
def create(id, namespace, request, options={})
|
20
|
+
Thread.current[:appsignal_transaction] = Appsignal::Transaction.new(id, namespace, request, options)
|
20
21
|
end
|
21
22
|
|
22
23
|
def current
|
@@ -33,68 +34,74 @@ module Appsignal
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
attr_reader :
|
37
|
-
:env, :fullpath, :time, :tags, :kind, :queue_start, :paused, :root_event_payload
|
37
|
+
attr_reader :transaction_index, :transaction_id, :namespace, :request, :paused, :tags, :options
|
38
38
|
|
39
|
-
def initialize(
|
40
|
-
@
|
41
|
-
@
|
42
|
-
@
|
43
|
-
@exception = nil
|
44
|
-
@env = env
|
45
|
-
@tags = {}
|
39
|
+
def initialize(transaction_id, namespace, request, options)
|
40
|
+
@transaction_id = transaction_id
|
41
|
+
@namespace = namespace
|
42
|
+
@request = request
|
46
43
|
@paused = false
|
47
|
-
@
|
48
|
-
|
44
|
+
@tags = {}
|
45
|
+
|
46
|
+
@options = options
|
47
|
+
@options[:params_method] ||= :params
|
48
|
+
|
49
|
+
@transaction_index = Appsignal::Extension.start_transaction(@transaction_id, @namespace)
|
49
50
|
end
|
50
51
|
|
51
|
-
def
|
52
|
-
@
|
52
|
+
def pause!
|
53
|
+
@paused = true
|
53
54
|
end
|
54
55
|
|
55
|
-
def
|
56
|
-
@
|
56
|
+
def resume!
|
57
|
+
@paused = false
|
57
58
|
end
|
58
59
|
|
59
|
-
def
|
60
|
-
@
|
60
|
+
def paused?
|
61
|
+
@paused == true
|
61
62
|
end
|
62
63
|
|
63
64
|
def set_tags(given_tags={})
|
64
65
|
@tags.merge!(given_tags)
|
65
66
|
end
|
66
67
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
68
|
+
def set_action(action)
|
69
|
+
return unless action
|
70
|
+
Appsignal::Extension.set_transaction_action(transaction_index, action)
|
71
|
+
end
|
72
|
+
|
73
|
+
def set_http_or_background_action(from=request.params)
|
74
|
+
return unless from
|
75
|
+
group_and_action = [
|
76
|
+
from[:controller] || from[:class],
|
77
|
+
from[:action] || from[:method]
|
78
|
+
]
|
79
|
+
set_action(group_and_action.compact.join('#'))
|
80
|
+
end
|
81
|
+
|
82
|
+
def set_queue_start(start)
|
83
|
+
return unless start
|
84
|
+
Appsignal::Extension.set_transaction_queue_start(transaction_index, start)
|
85
|
+
end
|
86
|
+
|
87
|
+
def set_http_or_background_queue_start
|
88
|
+
if namespace == HTTP_REQUEST
|
89
|
+
set_queue_start(http_queue_start)
|
90
|
+
elsif namespace == BACKGROUND_JOB
|
91
|
+
set_queue_start(background_queue_start)
|
81
92
|
end
|
82
|
-
Appsignal::Extension.set_transaction_base_data(
|
83
|
-
transaction_index,
|
84
|
-
kind,
|
85
|
-
action,
|
86
|
-
queue_start
|
87
|
-
)
|
88
93
|
end
|
89
94
|
|
90
95
|
def set_metadata(key, value)
|
91
|
-
return unless value
|
96
|
+
return unless key && value
|
92
97
|
Appsignal::Extension.set_transaction_metadata(transaction_index, key, value)
|
93
98
|
end
|
94
99
|
|
95
100
|
def set_error(error)
|
96
101
|
return unless error
|
97
|
-
Appsignal.
|
102
|
+
return if Appsignal.is_ignored_error?(error)
|
103
|
+
|
104
|
+
Appsignal.logger.debug("Adding #{error.class.name} to transaction: #{transaction_id}")
|
98
105
|
Appsignal::Extension.set_transaction_error(
|
99
106
|
transaction_index,
|
100
107
|
error.class.name,
|
@@ -122,59 +129,64 @@ module Appsignal
|
|
122
129
|
end
|
123
130
|
alias_method :add_exception, :set_error
|
124
131
|
|
125
|
-
|
126
|
-
|
127
|
-
end
|
132
|
+
class GenericRequest
|
133
|
+
attr_reader :env
|
128
134
|
|
129
|
-
|
130
|
-
|
131
|
-
|
135
|
+
def initialize(env)
|
136
|
+
@env = env
|
137
|
+
end
|
132
138
|
|
133
|
-
|
134
|
-
|
139
|
+
def params
|
140
|
+
env[:params]
|
141
|
+
end
|
135
142
|
end
|
136
143
|
|
137
144
|
protected
|
138
145
|
|
139
|
-
def
|
140
|
-
return unless
|
141
|
-
queue_start =
|
146
|
+
def background_queue_start
|
147
|
+
return unless request.env
|
148
|
+
queue_start = request.env[:queue_start]
|
142
149
|
return unless queue_start
|
143
|
-
|
150
|
+
(queue_start.to_f * 1000.0).to_i
|
151
|
+
end
|
152
|
+
|
153
|
+
def http_queue_start
|
154
|
+
return unless request.env
|
155
|
+
return unless env_var = request.env['HTTP_X_QUEUE_START'.freeze] || request.env['HTTP_X_REQUEST_START'.freeze]
|
156
|
+
cleaned_value = env_var.tr('^0-9'.freeze, ''.freeze)
|
157
|
+
return if cleaned_value.empty?
|
158
|
+
value = cleaned_value.to_i
|
159
|
+
[1_000_000.0, 1_000.0].each do |factor|
|
160
|
+
queue_start = (value / factor).to_i
|
161
|
+
return queue_start if queue_start > 946_681_200 # Ok if it's later than 2000
|
162
|
+
end
|
163
|
+
nil
|
144
164
|
end
|
145
165
|
|
146
166
|
def sanitized_params
|
147
|
-
return unless
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
if env_var
|
155
|
-
cleaned_value = env_var.tr('^0-9', '')
|
156
|
-
unless cleaned_value.empty?
|
157
|
-
value = cleaned_value.to_i
|
158
|
-
[1_000_000.0, 1_000.0].each do |factor|
|
159
|
-
@queue_start = (value / factor).to_i
|
160
|
-
break if @queue_start > 946_681_200.0 # Ok if it's later than 2000
|
161
|
-
end
|
162
|
-
end
|
167
|
+
return unless Appsignal.config[:send_params]
|
168
|
+
return unless request.respond_to?(options[:params_method])
|
169
|
+
return unless params = request.send(options[:params_method])
|
170
|
+
if params.is_a?(Hash)
|
171
|
+
Appsignal::ParamsSanitizer.sanitize(params)
|
172
|
+
elsif params.is_a?(Array)
|
173
|
+
params
|
163
174
|
end
|
164
175
|
end
|
165
176
|
|
166
177
|
def sanitized_environment
|
167
|
-
return unless env
|
178
|
+
return unless request.env
|
168
179
|
{}.tap do |out|
|
169
180
|
ENV_METHODS.each do |key|
|
170
|
-
out[key] = env[key] if env[key]
|
181
|
+
out[key] = request.env[key] if request.env[key]
|
171
182
|
end
|
172
183
|
end
|
173
184
|
end
|
174
185
|
|
175
186
|
def sanitized_session_data
|
176
|
-
return if Appsignal.config[:skip_session_data] || !
|
177
|
-
|
187
|
+
return if Appsignal.config[:skip_session_data] || !request.respond_to?(:session)
|
188
|
+
return unless session = request.session
|
189
|
+
Appsignal::ParamsSanitizer.sanitize(session.to_hash)
|
178
190
|
end
|
179
191
|
|
180
192
|
# Only keep tags if they meet the following criteria:
|
@@ -189,12 +201,11 @@ module Appsignal
|
|
189
201
|
end
|
190
202
|
|
191
203
|
def cleaned_backtrace(backtrace)
|
192
|
-
if defined?(::Rails)
|
204
|
+
if defined?(::Rails) && backtrace
|
193
205
|
::Rails.backtrace_cleaner.clean(backtrace, nil)
|
194
206
|
else
|
195
207
|
backtrace
|
196
208
|
end
|
197
209
|
end
|
198
|
-
|
199
210
|
end
|
200
211
|
end
|