Module: Errorgap

Defined in:
lib/errorgap.rb,
lib/errorgap/notice.rb,
lib/errorgap/version.rb,
lib/errorgap/notifier.rb,
lib/errorgap/transacter.rb,
lib/errorgap/breadcrumbs.rb,
lib/errorgap/transaction.rb,
lib/errorgap/log_delivery.rb,
lib/errorgap/configuration.rb,
lib/errorgap/rails/railtie.rb,
lib/errorgap/span_recorder.rb,
lib/errorgap/span_collector.rb,
lib/errorgap/rack_middleware.rb,
lib/generators/errorgap/install_generator.rb

Defined Under Namespace

Modules: Rails Classes: Breadcrumbs, Configuration, InstallGenerator, LogDelivery, Notice, Notifier, RackMiddleware, Span, SpanCollector, SpanRecorder, Transacter, Transaction

Constant Summary collapse

VERSION =
"0.5.0"

Class Method Summary collapse

Class Method Details

.add_breadcrumb(message, category: nil, metadata: nil) ⇒ Object

Record a diagnostic breadcrumb attached to subsequent notices.



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

def add_breadcrumb(message, category: nil, metadata: nil)
  breadcrumbs.add(message, category: category, metadata: )
end


41
42
43
# File 'lib/errorgap.rb', line 41

def breadcrumbs
  @breadcrumbs ||= Breadcrumbs.new(configuration.max_breadcrumbs)
end

.clear_breadcrumbsObject



62
63
64
# File 'lib/errorgap.rb', line 62

def clear_breadcrumbs
  breadcrumbs.clear
end

.configurationObject



25
26
27
# File 'lib/errorgap.rb', line 25

def configuration
  @configuration ||= Configuration.new
end

.configure {|configuration| ... } ⇒ Object

Yields:



17
18
19
20
21
22
23
# File 'lib/errorgap.rb', line 17

def configure
  yield(configuration)
  notifier.configure(configuration)
  transacter.configure(configuration)
  log_delivery.configure(configuration)
  @breadcrumbs = Breadcrumbs.new(configuration.max_breadcrumbs)
end

.flushObject

Join any in-flight async delivery threads. Call before process exit to avoid dropping queued notices/transactions/logs.



133
134
135
136
137
138
139
140
141
# File 'lib/errorgap.rb', line 133

def flush
  threads = thread_mutex.synchronize do
    pending = delivery_threads.dup
    delivery_threads.clear
    pending
  end
  threads.each { |thread| thread.join(5) }
  nil
end

.log(message, level: "info", source: nil, environment: nil, occurred_at: nil, sync: false) ⇒ Object

Deliver a structured log line at the given level.



67
68
69
70
71
72
73
74
75
76
# File 'lib/errorgap.rb', line 67

def log(message, level: "info", source: nil, environment: nil, occurred_at: nil, sync: false)
  log_delivery.log(
    message,
    level: level,
    source: source,
    environment: environment,
    occurred_at: occurred_at,
    sync: sync
  )
end

.log_deliveryObject



37
38
39
# File 'lib/errorgap.rb', line 37

def log_delivery
  @log_delivery ||= LogDelivery.new(configuration)
end

.notifierObject



29
30
31
# File 'lib/errorgap.rb', line 29

def notifier
  @notifier ||= Notifier.new(configuration)
end

.notify(error, context: {}, environment: {}, session: {}, params: {}, sync: false) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/errorgap.rb', line 45

def notify(error, context: {}, environment: {}, session: {}, params: {}, sync: false)
  notifier.notify(
    error,
    context: context,
    environment: environment,
    session: session,
    params: params,
    breadcrumbs: breadcrumbs.to_a,
    sync: sync
  )
end

.notify_transaction(transaction, sync: false) ⇒ Object

Deliver a prebuilt APM transaction, honoring apm_enabled and sampling.



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/errorgap.rb', line 79

def notify_transaction(transaction, sync: false)
  return unless configuration.apm_enabled
  return if configuration.ignored_environment?
  return unless sample_apm?

  if sync || !configuration.async
    transacter.deliver(transaction)
  else
    register_thread(Thread.new { transacter.deliver(transaction) })
  end
end

.register_thread(thread) ⇒ Object



143
144
145
146
# File 'lib/errorgap.rb', line 143

def register_thread(thread)
  thread_mutex.synchronize { delivery_threads << thread }
  thread
end

.track_job(job_class, queue: "default", environment: nil, sync: false) ⇒ Object

Time a background job and deliver it as a job transaction.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/errorgap.rb', line 113

def track_job(job_class, queue: "default", environment: nil, sync: false)
  SpanCollector.start
  started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  occurred = Time.now
  begin
    yield(SpanRecorder.new) if block_given?
  ensure
    elapsed_ms = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - started) * 1000.0
    transaction = Transaction.new(
      kind: "job", job_class: job_class, queue: queue,
      duration_ms: elapsed_ms.round(2),
      environment: environment || configuration.environment,
      occurred_at: occurred, spans: SpanCollector.flush
    )
    notify_transaction(transaction, sync: sync)
  end
end

.track_transaction(method: nil, path: nil, path_raw: nil, status_code: nil, kind: "web", environment: nil, sync: false) ⇒ Object

Time an HTTP interaction and deliver it as a transaction. The block receives a SpanRecorder for manual DB/HTTP spans; any automatic sql.active_record spans recorded during the block are merged in.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/errorgap.rb', line 94

def track_transaction(method: nil, path: nil, path_raw: nil, status_code: nil, kind: "web", environment: nil, sync: false)
  SpanCollector.start
  started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  occurred = Time.now
  begin
    yield(SpanRecorder.new) if block_given?
  ensure
    elapsed_ms = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - started) * 1000.0
    transaction = Transaction.new(
      kind: kind, method: method, path: path, path_raw: path_raw,
      status_code: status_code, duration_ms: elapsed_ms.round(2),
      environment: environment || configuration.environment,
      occurred_at: occurred, spans: SpanCollector.flush
    )
    notify_transaction(transaction, sync: sync)
  end
end

.transacterObject



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

def transacter
  @transacter ||= Transacter.new(configuration)
end