failbot 2.5.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
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: