lib/appsignal/transaction.rb in appsignal-0.12.beta.31 vs lib/appsignal/transaction.rb in appsignal-0.12.beta.32
- old
+ new
@@ -1,9 +1,10 @@
module Appsignal
class Transaction
HTTP_REQUEST = 'http_request'.freeze
BACKGROUND_JOB = 'background_job'.freeze
+ FRONTEND = 'frontend'.freeze
# Based on what Rails uses + some variables we'd like to show
ENV_METHODS = %w(CONTENT_LENGTH AUTH_TYPE GATEWAY_INTERFACE
PATH_TRANSLATED REMOTE_HOST REMOTE_IDENT REMOTE_USER REMOTE_ADDR
REQUEST_METHOD SERVER_NAME SERVER_PORT SERVER_PROTOCOL REQUEST_URI PATH_INFO
@@ -13,12 +14,12 @@
HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE
HTTP_CACHE_CONTROL HTTP_CONNECTION HTTP_USER_AGENT HTTP_FROM HTTP_NEGOTIATE
HTTP_PRAGMA HTTP_REFERER HTTP_X_FORWARDED_FOR HTTP_CLIENT_IP).freeze
class << self
- def create(request_id, env)
- Thread.current[:appsignal_transaction] = Appsignal::Transaction.new(request_id, env)
+ def create(id, namespace, request, options={})
+ Thread.current[:appsignal_transaction] = Appsignal::Transaction.new(id, namespace, request, options)
end
def current
Thread.current[:appsignal_transaction]
end
@@ -31,72 +32,78 @@
Appsignal.logger.error('Trying to complete current, but no transaction present')
end
end
end
- attr_reader :request_id, :transaction_index, :process_action_event, :action, :exception,
- :env, :fullpath, :time, :tags, :kind, :queue_start, :paused, :root_event_payload
+ attr_reader :transaction_index, :transaction_id, :namespace, :request, :paused, :tags, :options
- def initialize(request_id, env)
- @root_event_payload = nil
- @request_id = request_id
- @process_action_event = nil
- @exception = nil
- @env = env
- @tags = {}
+ def initialize(transaction_id, namespace, request, options)
+ @transaction_id = transaction_id
+ @namespace = namespace
+ @request = request
@paused = false
- @queue_start = -1
- @transaction_index = Appsignal::Extension.start_transaction(@request_id)
+ @tags = {}
+
+ @options = options
+ @options[:params_method] ||= :params
+
+ @transaction_index = Appsignal::Extension.start_transaction(@transaction_id, @namespace)
end
- def sanitized_environment
- @sanitized_environment ||= {}
+ def pause!
+ @paused = true
end
- def sanitized_session_data
- @sanitized_session_data ||= {}
+ def resume!
+ @paused = false
end
- def request
- @request ||= ::Rack::Request.new(env)
+ def paused?
+ @paused == true
end
def set_tags(given_tags={})
@tags.merge!(given_tags)
end
- def set_root_event(name, payload)
- @root_event_payload = payload
- if name.start_with?(Subscriber::PROCESS_ACTION_PREFIX)
- @action = "#{@root_event_payload[:controller]}##{@root_event_payload[:action]}"
- @kind = HTTP_REQUEST
- set_http_queue_start
- set_metadata('path', payload[:path])
- set_metadata('request_format', payload[:request_format])
- set_metadata('request_method', payload[:request_method])
- set_metadata('status', payload[:status].to_s)
- elsif name.start_with?(Subscriber::PERFORM_JOB_PREFIX)
- @action = "#{@root_event_payload[:class]}##{@root_event_payload[:method]}"
- @kind = BACKGROUND_JOB
- set_background_queue_start
+ def set_action(action)
+ return unless action
+ Appsignal::Extension.set_transaction_action(transaction_index, action)
+ end
+
+ def set_http_or_background_action(from=request.params)
+ return unless from
+ group_and_action = [
+ from[:controller] || from[:class],
+ from[:action] || from[:method]
+ ]
+ set_action(group_and_action.compact.join('#'))
+ end
+
+ def set_queue_start(start)
+ return unless start
+ Appsignal::Extension.set_transaction_queue_start(transaction_index, start)
+ end
+
+ def set_http_or_background_queue_start
+ if namespace == HTTP_REQUEST
+ set_queue_start(http_queue_start)
+ elsif namespace == BACKGROUND_JOB
+ set_queue_start(background_queue_start)
end
- Appsignal::Extension.set_transaction_base_data(
- transaction_index,
- kind,
- action,
- queue_start
- )
end
def set_metadata(key, value)
- return unless value
+ return unless key && value
Appsignal::Extension.set_transaction_metadata(transaction_index, key, value)
end
def set_error(error)
return unless error
- Appsignal.logger.debug("Adding #{error.class.name} to transaction: #{request_id}")
+ return if Appsignal.is_ignored_error?(error)
+
+ Appsignal.logger.debug("Adding #{error.class.name} to transaction: #{transaction_id}")
Appsignal::Extension.set_transaction_error(
transaction_index,
error.class.name,
error.message
)
@@ -120,63 +127,68 @@
end
end
end
alias_method :add_exception, :set_error
- def pause!
- @paused = true
- end
+ class GenericRequest
+ attr_reader :env
- def resume!
- @paused = false
- end
+ def initialize(env)
+ @env = env
+ end
- def paused?
- @paused == true
+ def params
+ env[:params]
+ end
end
protected
- def set_background_queue_start
- return unless root_event_payload
- queue_start = root_event_payload[:queue_start]
+ def background_queue_start
+ return unless request.env
+ queue_start = request.env[:queue_start]
return unless queue_start
- @queue_start = (queue_start.to_f * 1000.0).to_i
+ (queue_start.to_f * 1000.0).to_i
end
- def sanitized_params
- return unless root_event_payload
- Appsignal::ParamsSanitizer.sanitize(root_event_payload[:params])
+ def http_queue_start
+ return unless request.env
+ return unless env_var = request.env['HTTP_X_QUEUE_START'.freeze] || request.env['HTTP_X_REQUEST_START'.freeze]
+ cleaned_value = env_var.tr('^0-9'.freeze, ''.freeze)
+ return if cleaned_value.empty?
+ value = cleaned_value.to_i
+ [1_000_000.0, 1_000.0].each do |factor|
+ queue_start = (value / factor).to_i
+ return queue_start if queue_start > 946_681_200 # Ok if it's later than 2000
+ end
+ nil
end
- def set_http_queue_start
- return unless env
- env_var = env['HTTP_X_QUEUE_START'] || env['HTTP_X_REQUEST_START']
- if env_var
- cleaned_value = env_var.tr('^0-9', '')
- unless cleaned_value.empty?
- value = cleaned_value.to_i
- [1_000_000.0, 1_000.0].each do |factor|
- @queue_start = (value / factor).to_i
- break if @queue_start > 946_681_200.0 # Ok if it's later than 2000
- end
- end
+ def sanitized_params
+ return unless Appsignal.config[:send_params]
+ return unless request.respond_to?(options[:params_method])
+ return unless params = request.send(options[:params_method])
+ if params.is_a?(Hash)
+ Appsignal::ParamsSanitizer.sanitize(params)
+ elsif params.is_a?(Array)
+ params
end
end
def sanitized_environment
- return unless env
+ return unless request.env
{}.tap do |out|
ENV_METHODS.each do |key|
- out[key] = env[key] if env[key]
+ out[key] = request.env[key] if request.env[key]
end
end
end
def sanitized_session_data
- return if Appsignal.config[:skip_session_data] || !env
- Appsignal::ParamsSanitizer.sanitize(request.session.to_hash)
+ return if Appsignal.config[:skip_session_data] || !request.respond_to?(:session)
+ return unless session = request.session
+ Appsignal::ParamsSanitizer.sanitize(session.to_hash)
end
# Only keep tags if they meet the following criteria:
# * Key is a symbol or string with less then 100 chars
# * Value is a symbol or string with less then 100 chars
@@ -187,14 +199,13 @@
(((v.is_a?(Symbol) || v.is_a?(String)) && v.length <= 100) || (v.is_a?(Integer)))
end
end
def cleaned_backtrace(backtrace)
- if defined?(::Rails)
+ if defined?(::Rails) && backtrace
::Rails.backtrace_cleaner.clean(backtrace, nil)
else
backtrace
end
end
-
end
end