Class: Appsignal::Transaction

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

Defined Under Namespace

Classes: Formatter, ParamsSanitizer

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 REQUEST_URI PATH_INFO

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 HTTP_CLIENT_IP).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

#clear_events!Object



100
101
102
# File 'lib/appsignal/transaction.rb', line 100

def clear_events!
  events.clear
end

#complete!Object



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/appsignal/transaction.rb', line 141

def complete!
  Thread.current[:appsignal_transaction_id] = nil
  Appsignal.transactions.delete(@request_id)
  if process_action_event || exception?
    if Appsignal::IPC::Client.active?
      convert_values_to_primitives!
      Appsignal::IPC::Client.enqueue(self)
    else
      Appsignal.logger.debug("Enqueueing transaction: #{@request_id}")
      Appsignal.enqueue(self)
    end
  else
    Appsignal.logger.debug("Not processing transaction: #{@request_id} (#{events.length} events recorded)")
  end
ensure
  Appsignal.transactions.delete(@request_id)
end

#convert_values_to_primitives!Object



119
120
121
122
123
124
125
# File 'lib/appsignal/transaction.rb', line 119

def convert_values_to_primitives!
  return if have_values_been_converted_to_primitives?
  @process_action_event.sanitize! if @process_action_event
  @events.each { |event| event.sanitize! }
  add_sanitized_context!
  @have_values_been_converted_to_primitives = true
end

#exception?Boolean

Returns:

  • (Boolean)


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

def exception?
  !! exception
end

#have_values_been_converted_to_primitives?Boolean

Returns:

  • (Boolean)


127
128
129
# File 'lib/appsignal/transaction.rb', line 127

def have_values_been_converted_to_primitives?
  !! @have_values_been_converted_to_primitives
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



159
160
161
162
163
164
# File 'lib/appsignal/transaction.rb', line 159

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



166
167
168
169
170
171
172
173
174
175
176
# File 'lib/appsignal/transaction.rb', line 166

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



137
138
139
# File 'lib/appsignal/transaction.rb', line 137

def to_hash
  Formatter.new(self).to_hash
end

#truncate!Object



104
105
106
107
108
109
110
111
112
113
# File 'lib/appsignal/transaction.rb', line 104

def truncate!
  return if truncated?
  process_action_event.truncate!
  events.clear
  tags.clear
  sanitized_environment.clear
  sanitized_session_data.clear
  @env = nil
  @truncated = true
end

#truncated?Boolean

Returns:

  • (Boolean)


115
116
117
# File 'lib/appsignal/transaction.rb', line 115

def truncated?
  !! @truncated
end

#typeObject



131
132
133
134
135
# File 'lib/appsignal/transaction.rb', line 131

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