Class: Appsignal::Transaction

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

Defined Under Namespace

Classes: GenericRequest, NilTransaction

Constant Summary collapse

HTTP_REQUEST =
"http_request".freeze
BACKGROUND_JOB =
"background_job".freeze
ACTION_CABLE =
"action_cable".freeze
FRONTEND =
"frontend".freeze
BLANK =
"".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(transaction_id, namespace, request, options = {}) ⇒ Transaction

Returns a new instance of Transaction.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/appsignal/transaction.rb', line 72

def initialize(transaction_id, namespace, request, options = {})
  @transaction_id = transaction_id
  @action = nil
  @namespace = namespace
  @request = request
  @paused = false
  @discarded = false
  @tags = {}
  @store = Hash.new({})
  @options = options
  @options[:params_method] ||= :params

  @ext = Appsignal::Extension.start_transaction(
    @transaction_id,
    @namespace,
    self.class.garbage_collection_profiler.total_time
  )
end

Instance Attribute Details

#actionObject (readonly)

Returns the value of attribute action.



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

def action
  @action
end

#discardedObject (readonly)

Returns the value of attribute discarded.



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

def discarded
  @discarded
end

#extObject (readonly)

Returns the value of attribute ext.



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

def ext
  @ext
end

#namespaceObject (readonly)

Returns the value of attribute namespace.



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

def namespace
  @namespace
end

#optionsObject (readonly)

Returns the value of attribute options.



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

def options
  @options
end

#paramsHash

Attribute for parameters of the transaction.

When no parameters are set with #params= the parameters it will look for parameters on the #request environment.

The parameters set using #params= are leading over those extracted from a request's environment.

Returns:

  • (Hash)


70
# File 'lib/appsignal/transaction.rb', line 70

attr_writer :params

#pausedObject (readonly)

Returns the value of attribute paused.



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

def paused
  @paused
end

#requestObject (readonly)

Returns the value of attribute request.



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

def request
  @request
end

#tagsObject (readonly)

Returns the value of attribute tags.



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

def tags
  @tags
end

#transaction_idObject (readonly)

Returns the value of attribute transaction_id.



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

def transaction_id
  @transaction_id
end

Class Method Details

.clear_current_transaction!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Remove current transaction from current Thread.



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

def clear_current_transaction!
  Thread.current[:appsignal_transaction] = nil
end

.complete_current!Object



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

def complete_current!
  current.complete
rescue => e
  Appsignal.logger.error("Failed to complete transaction ##{current.transaction_id}. #{e.message}")
ensure
  clear_current_transaction!
end

.create(id, namespace, request, options = {}) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/appsignal/transaction.rb', line 14

def create(id, namespace, request, options = {})
  # Allow middleware to force a new transaction
  if options.include?(:force) && options[:force]
    Thread.current[:appsignal_transaction] = nil
  end

  # Check if we already have a running transaction
  if Thread.current[:appsignal_transaction] != nil
    # Log the issue and return the current transaction
    Appsignal.logger.debug "Trying to start new transaction with id " \
      "'#{id}', but a transaction with id '#{current.transaction_id}' " \
      "is already running. Using transaction '#{current.transaction_id}'."

    # Return the current (running) transaction
    current
  else
    # Otherwise, start a new transaction
    Thread.current[:appsignal_transaction] = Appsignal::Transaction.new(id, namespace, request, options)
  end
end

.currentObject



35
36
37
# File 'lib/appsignal/transaction.rb', line 35

def current
  Thread.current[:appsignal_transaction] || NilTransaction.new
end

.garbage_collection_profilerObject



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

def garbage_collection_profiler
  @garbage_collection_profiler ||= Appsignal::GarbageCollectionProfiler.new
end

Instance Method Details

#completeObject



95
96
97
98
99
100
101
102
103
104
105
# File 'lib/appsignal/transaction.rb', line 95

def complete
  if discarded?
    Appsignal.logger.debug "Skipping transaction '#{transaction_id}' " \
      "because it was manually discarded."
    return
  end
  if @ext.finish(self.class.garbage_collection_profiler.total_time)
    sample_data
  end
  @ext.complete
end

#discard!Object



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

def discard!
  @discarded = true
end

#discarded?Boolean

Returns:

  • (Boolean)


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

def discarded?
  @discarded == true
end

#finish_event(name, title, body, body_format = Appsignal::EventFormatter::DEFAULT) ⇒ Object



280
281
282
283
284
285
286
287
288
# File 'lib/appsignal/transaction.rb', line 280

def finish_event(name, title, body, body_format = Appsignal::EventFormatter::DEFAULT)
  @ext.finish_event(
    name,
    title || BLANK,
    body || BLANK,
    body_format || Appsignal::EventFormatter::DEFAULT,
    self.class.garbage_collection_profiler.total_time
  )
end

#instrument(name, title = nil, body = nil, body_format = Appsignal::EventFormatter::DEFAULT) ⇒ Object



301
302
303
304
305
306
# File 'lib/appsignal/transaction.rb', line 301

def instrument(name, title = nil, body = nil, body_format = Appsignal::EventFormatter::DEFAULT)
  start_event
  yield if block_given?
ensure
  finish_event(name, title, body, body_format)
end

#nil_transaction?Boolean

Returns:

  • (Boolean)


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

def nil_transaction?
  false
end

#pause!Object



107
108
109
# File 'lib/appsignal/transaction.rb', line 107

def pause!
  @paused = true
end

#paused?Boolean

Returns:

  • (Boolean)


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

def paused?
  @paused == true
end

#record_event(name, title, body, duration, body_format = Appsignal::EventFormatter::DEFAULT) ⇒ Object



290
291
292
293
294
295
296
297
298
299
# File 'lib/appsignal/transaction.rb', line 290

def record_event(name, title, body, duration, body_format = Appsignal::EventFormatter::DEFAULT)
  @ext.record_event(
    name,
    title || BLANK,
    body || BLANK,
    body_format || Appsignal::EventFormatter::DEFAULT,
    duration,
    self.class.garbage_collection_profiler.total_time
  )
end

#restore!Object



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

def restore!
  @discarded = false
end

#resume!Object



111
112
113
# File 'lib/appsignal/transaction.rb', line 111

def resume!
  @paused = false
end

#sample_dataObject



251
252
253
254
255
256
257
258
259
260
261
# File 'lib/appsignal/transaction.rb', line 251

def sample_data
  {
    :params       => sanitized_params,
    :environment  => sanitized_environment,
    :session_data => sanitized_session_data,
    :metadata     => ,
    :tags         => sanitized_tags
  }.each do |key, data|
    set_sample_data(key, data)
  end
end

#set_action(action) ⇒ void

This method returns an undefined value.

Set an action name for the transaction.

An action name is used to identify the location of a certain sample; error and performance issues.

Parameters:

  • action (String)

    the action name to set.

See Also:

Since:

  • 2.2.0



166
167
168
169
170
# File 'lib/appsignal/transaction.rb', line 166

def set_action(action)
  return unless action
  @action = action
  @ext.set_action(action)
end

#set_action_if_nil(action) ⇒ void

This method returns an undefined value.

Set an action name only if there is no current action set.

Commonly used by AppSignal integrations so that they don't override custom action names.

Examples:

Appsignal.set_action("foo")
Appsignal.set_action_if_nil("bar")
# Transaction action will be "foo"

Parameters:

  • action (String)

See Also:

Since:

  • 2.2.0



186
187
188
189
# File 'lib/appsignal/transaction.rb', line 186

def set_action_if_nil(action)
  return if @action
  set_action(action)
end

#set_error(error) ⇒ Object Also known as: add_exception



263
264
265
266
267
268
269
270
271
272
273
# File 'lib/appsignal/transaction.rb', line 263

def set_error(error)
  return unless error
  return unless Appsignal.active?

  backtrace = cleaned_backtrace(error.backtrace)
  @ext.set_error(
    error.class.name,
    error.message.to_s,
    backtrace ? Appsignal::Utils.data_generate(backtrace) : Appsignal::Extension.data_array_new
  )
end

#set_http_or_background_action(from = request.params) ⇒ Object



212
213
214
215
216
217
218
219
# File 'lib/appsignal/transaction.rb', line 212

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

#set_http_or_background_queue_startObject



228
229
230
231
232
233
234
# File 'lib/appsignal/transaction.rb', line 228

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
end

#set_metadata(key, value) ⇒ Object



236
237
238
239
# File 'lib/appsignal/transaction.rb', line 236

def (key, value)
  return unless key && value
  @ext.(key, value)
end

#set_namespace(namespace) ⇒ void

This method returns an undefined value.

Set the namespace for this transaction.

Useful to split up parts of an application into certain namespaces. For example: http requests, background jobs and administration panel controllers.

Note: The "http_request" namespace gets transformed on AppSignal.com to "Web" and "background_job" gets transformed to "Background".

Examples:

transaction.set_action("admin")

Parameters:

  • namespace (String)

    namespace name to use for this transaction.

Since:

  • 2.2.0



206
207
208
209
210
# File 'lib/appsignal/transaction.rb', line 206

def set_namespace(namespace)
  return unless namespace
  @namespace = namespace
  @ext.set_namespace(namespace)
end

#set_queue_start(start) ⇒ Object



221
222
223
224
225
226
# File 'lib/appsignal/transaction.rb', line 221

def set_queue_start(start)
  return unless start
  @ext.set_queue_start(start)
rescue RangeError
  Appsignal.logger.warn("Queue start value #{start} is too big")
end

#set_sample_data(key, data) ⇒ Object



241
242
243
244
245
246
247
248
249
# File 'lib/appsignal/transaction.rb', line 241

def set_sample_data(key, data)
  return unless key && data && (data.is_a?(Array) || data.is_a?(Hash))
  @ext.set_sample_data(
    key.to_s,
    Appsignal::Utils.data_generate(data)
  )
rescue RuntimeError => e
  Appsignal.logger.error("Error generating data (#{e.class}: #{e.message}) for '#{data.inspect}'")
end

#set_tags(given_tags = {}) ⇒ void

This method returns an undefined value.

Set tags on the transaction.

Parameters:

  • given_tags (Hash) (defaults to: {})

    Collection of tags.

Options Hash (given_tags):

  • :any (String, Symbol, Integer)

    The name of the tag as a Symbol.

  • "any" (String, Symbol, Integer)

    The name of the tag as a String.

See Also:



152
153
154
# File 'lib/appsignal/transaction.rb', line 152

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

#start_eventObject



276
277
278
# File 'lib/appsignal/transaction.rb', line 276

def start_event
  @ext.start_event(self.class.garbage_collection_profiler.total_time)
end

#store(key) ⇒ Object



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

def store(key)
  @store[key]
end

#to_hObject Also known as: to_hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



309
310
311
# File 'lib/appsignal/transaction.rb', line 309

def to_h
  JSON.parse(@ext.to_json)
end