Module: PlainApm::EventAttributes

Included in:
PlainApm::Extensions::Exceptions::Rack, Hooks::ActiveSupportSubscriber, Hooks::ErrorReporter
Defined in:
lib/plain_apm/event_attributes.rb

Constant Summary collapse

SOURCES_WITH_EXTRA_ATTRIBUTES =
%w[
  action_controller
  action_mailer
  active_job
  exception
].freeze
IGNORED_EXCEPTIONS =

FIXME: This is duplicated for ErrorReporter

[
  "Sidekiq::JobRetry::Skip", # Sidekiq uses exceptions for control flow.
  "ActionController::RoutingError" # Rails unmapped route, raised before the request hits the app.
].freeze

Instance Method Summary collapse

Instance Method Details

#attributes_from_exception(e, context, error_source) ⇒ Object



19
20
21
22
23
24
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
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/plain_apm/event_attributes.rb', line 19

def attributes_from_exception(e, context, error_source)
  name = "exception"

  return [name, nil] if IGNORED_EXCEPTIONS.include?(e.class.name)

  attrs = context_attributes

  attrs[:class] = e.class.name
  attrs[:message] = e.message
  attrs[:backtrace] = e.backtrace

  attrs[:event_time] = now
  attrs[:event_utc_time] = utc_now

  if error_source
    attrs[:event_source] = error_source
  end

  if context[:controller]&.is_a?(ActionController::Base)
    attrs[:controller] = context[:controller].class.name
  end

  if context[:job]&.is_a?(ActiveJob::Base)
    attrs[:job_class] = context[:job].class.name
    attrs[:queue_name] = context[:job].queue_name
  end

  if context[:env]
    attrs[:params] = context.dig(:env, "action_dispatch.request.parameters")
    attrs[:action] = context.dig(:env, "action_dispatch.request.parameters", :action)
    attrs[:controller] = context.dig(:env, "action_controller.instance")&.class.name
  end

  # https://bugs.ruby-lang.org/issues/19197
  root_cause = e
  root_cause = root_cause.cause while root_cause.cause

  if root_cause != e
    attrs[:root_cause_class] = root_cause.class.name
    attrs[:root_cause_message] = root_cause.message
    attrs[:root_cause_backtrace] = root_cause.backtrace
    loc = source_location(root_cause.backtrace)
    if !loc.nil?
      attrs[:root_cause_location] = loc
    end
  end

  loc = source_location(e.backtrace)
  if !loc.nil?
    attrs[:source_location] = loc
  end

  add_trace_attributes(attrs)

  [name, attrs]
end

#attributes_from_notification(event) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/plain_apm/event_attributes.rb', line 76

def attributes_from_notification(event)
  name, source = *event.name.split(".")
  loc = source_location

  attrs = context_attributes

  attrs[:source] = source
  attrs[:name] = name
  attrs[:allocations] = event.allocations
  attrs[:thread_cpu_time] = event.cpu_time
  attrs[:event_time] = event.time
  attrs[:duration] = event.duration

  if event.respond_to?(:utc_time)
    attrs[:event_utc_time] = event.utc_time
  end

  if event.respond_to?(:gc_time)
    attrs[:gc_time] = event.gc_time
  end

  if event.respond_to?(:gc_major_count)
    attrs[:gc_major_count] = event.gc_major_count
  end

  if event.respond_to?(:gc_minor_count)
    attrs[:gc_minor_count] = event.gc_minor_count
  end

  if event.respond_to?(:thread_allocations)
    attrs[:thread_allocations] = event.thread_allocations
  end

  if !loc.nil?
    attrs[:source_location] = loc
  end

  add_trace_attributes(attrs)

  [name, attrs]
end