Class: Sqewer::Contrib::AppsignalWrapper

Inherits:
Object
  • Object
show all
Defined in:
lib/sqewer/extensions/appsignal_wrapper.rb

Overview

Can be used as a wrapper middleware in an ExecutionContext to log exceptions to Appsignal and to monitor performance. Will only activate if the Appsignal gem is loaded within the current process and active.

Defined Under Namespace

Classes: FakeRequest

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.newObject



8
9
10
11
12
13
14
# File 'lib/sqewer/extensions/appsignal_wrapper.rb', line 8

def self.new
  if defined?(Appsignal)
    super
  else
    nil
  end
end

Instance Method Details

#around_deserialization(serializer, msg_id, msg_payload, msg_attributes) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/sqewer/extensions/appsignal_wrapper.rb', line 25

def around_deserialization(serializer, msg_id, msg_payload, msg_attributes)
  return yield unless Appsignal.active?

  # This creates a transaction, but also sets it as the Appsignal.current_transaction
  # which is a thread-local variable. We DO share this middleware between threads,
  # but since the object lives in thread locals it should be fine.
  transaction = Appsignal::Transaction.create(
    SecureRandom.uuid,
    namespace = Appsignal::Transaction::BACKGROUND_JOB,
    request = FakeRequest.new)

  transaction.set_action('%s#%s' % [serializer.class, 'unserialize'])
  transaction.request.params = {:sqs_message_body => msg_payload.to_s}
  if msg_attributes.key?('SentTimestamp')
    transaction.set_queue_start = Time.at(msg_attributes['SentTimestamp'].to_i / 1000.0)
  end

  job_unserialized = yield

  if !job_unserialized
    # If the job is nil or falsy, we skip the execution. In that case we finish the transaction.
    Appsignal::Transaction.complete_current!
  else
    # If not, then the job will be executed - keep the transaction open for execution block
    # that comes next. Hacky but should work.
    set_transaction_details_from_job(transaction, job_unserialized)
  end
  return job_unserialized
rescue Exception => e
  if transaction
    # If an exception is raised, raise it through and also set it as the Appsignal exception
    # and commit the transaction.
    transaction.set_error(e)
    Appsignal::Transaction.complete_current!
  end
  raise e
end

#around_execution(job, context) ⇒ Object

Run the job with Appsignal monitoring.



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/sqewer/extensions/appsignal_wrapper.rb', line 71

def around_execution(job, context)
  return yield unless Appsignal.active?
  transaction = Appsignal::Transaction.current
  set_transaction_details_from_job(transaction, job)
  yield
rescue Exception => e
  transaction.set_error(e) if transaction
  raise e
ensure
  Appsignal::Transaction.complete_current! if transaction
end

#set_transaction_details_from_job(transaction, job) ⇒ Object



63
64
65
66
67
68
# File 'lib/sqewer/extensions/appsignal_wrapper.rb', line 63

def set_transaction_details_from_job(transaction, job)
  job_class_string = job.respond_to?(:class_name) ? job.class_name : job.class.to_s
  transaction.set_action('%s#%s' % [job_class_string, 'run'])
  job_params = job.respond_to?(:to_h) ? job.to_h : {}
  transaction.request.params = job_params
end