failbot 2.5.0 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5252def6736e809a4cfa4961ccce6180a4dcc593048c7185667fc5109ff37bb
4
- data.tar.gz: c1e8d453c0b18383896dac11471e9bfc026cd390eac61486d7a795f753a64462
3
+ metadata.gz: 7d95ed657556e73833f309a37497784e45ac94f959f79988acf8ac066e6f4a6b
4
+ data.tar.gz: c95554288cab069cf33ce8c1c4bdfad43ebaa5e9e1f1f83492865e67d014977d
5
5
  SHA512:
6
- metadata.gz: c4655cbdac9571d6d2384e8bd2b593ecd1c564f176126e0e54a9073999dc72d6d776ea506a16b0fc8a116e607c9447fddee7e535ceac8cad60750a2a89b39b1a
7
- data.tar.gz: 1edeeafc4c3f36f710b199b414d49d72c9b261c30f08b7da93ade8a6550bc892f66550f5f89ee1ed54c6156c28f1dd9a4444b70e06388caaeedefc10dd14b22c
6
+ metadata.gz: a1223f04684f214ed5dfcdf444a1e4b9b1a209aee0ba1aa065e85e52603b3fda012790002237b3629ca9e588533aec48a2bd482d995ffa5d149f575c8619465c
7
+ data.tar.gz: 2acb08a403bbdd7b4fdae7973e40a11320b1002bac4aba4e8393d467d8c9b45d45efa0eaae85b4b6b4e6139be1b7185e7d387ccff7edba33b9dfe4724eaad963
@@ -26,6 +26,8 @@ module Failbot
26
26
  autoload :MemoryBackend, 'failbot/memory_backend'
27
27
  autoload :JSONBackend, 'failbot/json_backend'
28
28
 
29
+ autoload :ThreadLocalVariable, 'failbot/thread_local_variable'
30
+
29
31
  # Public: Set an instrumenter to be called when exceptions are reported.
30
32
  #
31
33
  # class CustomInstrumenter
@@ -44,9 +46,6 @@ module Failbot
44
46
  #
45
47
  attr_accessor :instrumenter
46
48
 
47
- # prevent recursive calls to Failbot.report!
48
- attr_accessor :already_reporting
49
-
50
49
  # Root directory of the project's source. Used to clean up stack traces if the exception format supports it
51
50
 
52
51
  def source_root=(str)
@@ -130,9 +129,16 @@ module Failbot
130
129
  return setup_deprecated(settings)
131
130
  end
132
131
 
133
- if default_context.respond_to?(:to_hash) && !default_context.to_hash.empty?
134
- context[0] = default_context.to_hash
132
+ initial_context = if default_context.respond_to?(:to_hash) && !default_context.to_hash.empty?
133
+ default_context.to_hash
134
+ else
135
+ { 'server' => hostname }
136
+ end
137
+
138
+ @thread_local_context = ::Failbot::ThreadLocalVariable.new do
139
+ [initial_context]
135
140
  end
141
+ @thread_local_already_reporting = ::Failbot::ThreadLocalVariable.new { false }
136
142
 
137
143
  populate_context_from_settings(settings)
138
144
 
@@ -174,7 +180,7 @@ module Failbot
174
180
  # hashes are condensed down into one and included in the next report. Don't
175
181
  # mess with this structure directly - use the #push and #pop methods.
176
182
  def context
177
- @context ||= [{'server' => hostname}]
183
+ @thread_local_context.value
178
184
  end
179
185
 
180
186
  # Add info to be sent in the next failbot report, should one occur.
@@ -198,7 +204,7 @@ module Failbot
198
204
 
199
205
  # Reset the context stack to a pristine state.
200
206
  def reset!
201
- @context = [context[0]]
207
+ @thread_local_context.value = [context[0]].dup
202
208
  end
203
209
 
204
210
  # Loops through the stack of contexts and deletes the given key if it exists.
@@ -329,17 +335,25 @@ module Failbot
329
335
  end
330
336
 
331
337
  data = scrub(sanitize(data))
338
+ rescue Object => i
339
+ log_failure("processing", data, e, i)
340
+ self.already_reporting = false
341
+ return
342
+ end
332
343
 
344
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
345
+ instrumentation_data = {
346
+ "report_status" => "error",
347
+ }
348
+ begin
333
349
  backend.report(data)
334
- instrument("report.failbot", data)
350
+ instrumentation_data["report_status"] = "success"
335
351
  rescue Object => i
336
- # don't fail for any reason
337
- logger.debug "FAILBOT: #{data.inspect}" rescue nil
338
- logger.debug e.message rescue nil
339
- logger.debug e.backtrace.join("\n") rescue nil
340
- logger.debug i.message rescue nil
341
- logger.debug i.backtrace.join("\n") rescue nil
352
+ log_failure("reporting", data, e, i)
353
+ instrumentation_data["exception_type"] = i.class.name
342
354
  ensure
355
+ instrumentation_data["elapsed_ms"] = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time) * 1000).to_i
356
+ instrument("report.failbot", data.merge(instrumentation_data)) rescue nil
343
357
  self.already_reporting = false
344
358
  end
345
359
  end
@@ -468,6 +482,14 @@ module Failbot
468
482
  @hostname ||= Socket.gethostname
469
483
  end
470
484
 
485
+ def already_reporting=(bool)
486
+ @thread_local_already_reporting.value = bool
487
+ end
488
+
489
+ def already_reporting
490
+ @thread_local_already_reporting.value
491
+ end
492
+
471
493
  private
472
494
 
473
495
  # Internal: Publish an event to the instrumenter
@@ -485,6 +507,15 @@ module Failbot
485
507
  end
486
508
  end
487
509
 
510
+ def log_failure(action, data, original_exception, exception)
511
+ # don't fail for any reason
512
+ logger.debug "FAILBOT EXCEPTION: action=#{action} exception=#{exception.class.name} original_type: #{original_exception.class.name} data=#{data.inspect}" rescue nil
513
+ logger.debug original_exception.message rescue nil
514
+ logger.debug original_exception.backtrace.join("\n") rescue nil
515
+ logger.debug exception.message rescue nil
516
+ logger.debug exception.backtrace.join("\n") rescue nil
517
+ end
518
+
488
519
  extend self
489
520
 
490
521
  # If the library was lazy loaded due to failbot/exit_hook.rb and a delayed
@@ -12,11 +12,8 @@ module Failbot
12
12
  end
13
13
 
14
14
  def report(data)
15
- if @fail
16
- fail
17
- end
18
-
19
15
  @reports << data
16
+ fail if @fail
20
17
  end
21
18
 
22
19
  def ping
@@ -0,0 +1,24 @@
1
+ module Failbot
2
+ # Public: A simplified implementation of [`::Concurrent::ThreadLocalVar`](https://github.com/ruby-concurrency/concurrent-ruby/blob/7dc6eb04142f008ffa79a59c125669c6fcbb85a8/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb)
3
+ #
4
+ # Why not just use `concurrent-ruby`? We wanted to minimize external dependencies to avoid conflicts with gems already installed with `github/github`.
5
+ #
6
+ class ThreadLocalVariable
7
+ def initialize(&block)
8
+ @default_block = block || proc {}
9
+ @key = "_thread_local_variable##{object_id}"
10
+ end
11
+
12
+ def value
13
+ if Thread.current.key?(@key)
14
+ Thread.current[@key]
15
+ else
16
+ Thread.current[@key] = @default_block.call
17
+ end
18
+ end
19
+
20
+ def value=(val)
21
+ Thread.current[@key] = val
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module Failbot
2
- VERSION = "2.5.0"
2
+ VERSION = "2.5.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: failbot
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - "@rtomayko"
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-04-06 00:00:00.000000000 Z
13
+ date: 2020-04-07 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -106,6 +106,7 @@ files:
106
106
  - lib/failbot/middleware.rb
107
107
  - lib/failbot/resque_failure_backend.rb
108
108
  - lib/failbot/sensitive_data_scrubber.rb
109
+ - lib/failbot/thread_local_variable.rb
109
110
  - lib/failbot/version.rb
110
111
  homepage: http://github.com/github/failbot#readme
111
112
  licenses: