Class: Appsignal::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/appsignal/transaction.rb,
lib/appsignal/transaction/formatter.rb,
lib/appsignal/transaction/params_sanitizer.rb

Defined Under Namespace

Classes: Formatter, ParamsSanitizer, ParamsSanitizerCopy, ParamsSanitizerCopyScrub, ParamsSanitizerDestructive, ParamsSanitizerDestructiveScrub

Constant Summary collapse

ENV_METHODS =

Based on what Rails uses + some variables we’d like to show

%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

HTTP_X_REQUEST_START HTTP_X_MIDDLEWARE_START HTTP_X_QUEUE_START
HTTP_X_QUEUE_TIME HTTP_X_HEROKU_QUEUE_WAIT_TIME HTTP_X_APPLICATION_START
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).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request_id, env) ⇒ Transaction

Returns a new instance of Transaction.



36
37
38
39
40
41
42
43
44
# File 'lib/appsignal/transaction.rb', line 36

def initialize(request_id, env)
  Appsignal.transactions[request_id] = self
  @request_id = request_id
  @events = []
  @process_action_event = nil
  @exception = nil
  @env = env
  @tags = {}
end

Instance Attribute Details

#actionObject (readonly)

Returns the value of attribute action.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def action
  @action
end

#envObject (readonly)

Returns the value of attribute env.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def env
  @env
end

#eventsObject (readonly)

Returns the value of attribute events.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def events
  @events
end

#exceptionObject (readonly)

Returns the value of attribute exception.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def exception
  @exception
end

#fullpathObject (readonly)

Returns the value of attribute fullpath.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def fullpath
  @fullpath
end

#kindObject (readonly)

Returns the value of attribute kind.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def kind
  @kind
end

#process_action_eventObject (readonly)

Returns the value of attribute process_action_event.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def process_action_event
  @process_action_event
end

#queue_startObject (readonly)

Returns the value of attribute queue_start.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def queue_start
  @queue_start
end

#request_idObject (readonly)

Returns the value of attribute request_id.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def request_id
  @request_id
end

#tagsObject (readonly)

Returns the value of attribute tags.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def tags
  @tags
end

#timeObject (readonly)

Returns the value of attribute time.



33
34
35
# File 'lib/appsignal/transaction.rb', line 33

def time
  @time
end

Class Method Details

.complete_current!Object



24
25
26
27
28
29
30
31
# File 'lib/appsignal/transaction.rb', line 24

def self.complete_current!
  if current
    current.complete!
    Thread.current[:appsignal_transaction_id] = nil
  else
    Appsignal.logger.error('Trying to complete current, but no transaction present')
  end
end

.create(request_id, env) ⇒ Object



14
15
16
17
18
# File 'lib/appsignal/transaction.rb', line 14

def self.create(request_id, env)
  Appsignal.logger.debug("Creating transaction: #{request_id}")
  Thread.current[:appsignal_transaction_id] = request_id
  Appsignal::Transaction.new(request_id, env)
end

.currentObject



20
21
22
# File 'lib/appsignal/transaction.rb', line 20

def self.current
  Appsignal.transactions[Thread.current[:appsignal_transaction_id]]
end

Instance Method Details

#add_event(event) ⇒ Object



78
79
80
# File 'lib/appsignal/transaction.rb', line 78

def add_event(event)
  @events << event
end

#add_exception(ex) ⇒ Object



82
83
84
85
# File 'lib/appsignal/transaction.rb', line 82

def add_exception(ex)
  @time = Time.now.utc.to_f
  @exception = ex
end

#complete!Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/appsignal/transaction.rb', line 127

def complete!
  Thread.current[:appsignal_transaction_id] = nil
  Appsignal.transactions.delete(@request_id)
  if process_action_event || exception?
    if Appsignal::Pipe.current
      Appsignal.logger.debug("Writing transaction to pipe: #{@request_id}")
      Appsignal::Pipe.current.write(self)
    else
      Appsignal.logger.debug("Enqueueing transaction: #{@request_id}")
      Appsignal.enqueue(self)
    end
  else
    Appsignal.logger.debug("Not processing transaction: #{@request_id}")
  end
ensure
  Appsignal.transactions.delete(@request_id)
end

#convert_values_to_primitives!Object



109
110
111
112
113
114
115
# File 'lib/appsignal/transaction.rb', line 109

def convert_values_to_primitives!
  Appsignal::Transaction::ParamsSanitizer.sanitize!(@process_action_event.payload) if @process_action_event
  @events.map do |o|
    Appsignal::Transaction::ParamsSanitizer.sanitize(o.payload)
  end
  add_sanitized_context!
end

#exception?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/appsignal/transaction.rb', line 87

def exception?
  !!exception
end

#requestObject



54
55
56
# File 'lib/appsignal/transaction.rb', line 54

def request
  ::Rack::Request.new(@env)
end

#sanitized_environmentObject



46
47
48
# File 'lib/appsignal/transaction.rb', line 46

def sanitized_environment
  @sanitized_environment ||= {}
end

#sanitized_session_dataObject



50
51
52
# File 'lib/appsignal/transaction.rb', line 50

def sanitized_session_data
  @sanitized_session_data ||= {}
end

#set_background_queue_startObject



145
146
147
148
149
150
# File 'lib/appsignal/transaction.rb', line 145

def set_background_queue_start
  queue_start = process_action_event.payload[:queue_start]
  return unless queue_start
  Appsignal.logger.debug("Setting background queue start: #{queue_start}")
  @queue_start = queue_start.to_f
end

#set_http_queue_startObject



152
153
154
155
156
157
158
159
160
161
162
# File 'lib/appsignal/transaction.rb', line 152

def set_http_queue_start
  return unless env
  env_var = env['HTTP_X_QUEUE_START'] || env['HTTP_X_REQUEST_START']
  if env_var
    Appsignal.logger.debug("Setting http queue start: #{env_var}")
    value = env_var.tr('^0-9', '')
    unless value.empty?
      @queue_start = value.to_f / 1000.0
    end
  end
end

#set_perform_job_event(event) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/appsignal/transaction.rb', line 70

def set_perform_job_event(event)
  return unless event && event.payload
  @process_action_event = event.dup
  @action = "#{@process_action_event.payload[:class]}##{@process_action_event.payload[:method]}"
  @kind = 'background_job'
  set_background_queue_start
end

#set_process_action_event(event) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/appsignal/transaction.rb', line 62

def set_process_action_event(event)
  return unless event && event.payload
  @process_action_event = event.dup
  @action = "#{@process_action_event.payload[:controller]}##{@process_action_event.payload[:action]}"
  @kind = 'http_request'
  set_http_queue_start
end

#set_tags(given_tags = {}) ⇒ Object



58
59
60
# File 'lib/appsignal/transaction.rb', line 58

def set_tags(given_tags={})
  @tags.merge!(given_tags)
end

#slow_request?Boolean

Returns:

  • (Boolean)


91
92
93
94
# File 'lib/appsignal/transaction.rb', line 91

def slow_request?
  return false unless process_action_event && process_action_event.payload
  Appsignal.config[:slow_request_threshold] <= process_action_event.duration
end

#slower?(transaction) ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/appsignal/transaction.rb', line 96

def slower?(transaction)
  process_action_event.duration > transaction.process_action_event.duration
end

#to_hashObject



123
124
125
# File 'lib/appsignal/transaction.rb', line 123

def to_hash
  Formatter.new(self).to_hash
end

#truncate!Object



100
101
102
103
104
105
106
107
# File 'lib/appsignal/transaction.rb', line 100

def truncate!
  process_action_event.payload.clear
  events.clear
  tags.clear
  sanitized_environment.clear
  sanitized_session_data.clear
  @env = nil
end

#typeObject



117
118
119
120
121
# File 'lib/appsignal/transaction.rb', line 117

def type
  return :exception if exception?
  return :slow_request if slow_request?
  :regular_request
end