failbot 0.9.6 → 1.0.0

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
  SHA1:
3
- metadata.gz: 535bea1efe92287487fb8eca35fa79362b5a3467
4
- data.tar.gz: 6e95a3258b3778cb4c832201431685fed770051f
3
+ metadata.gz: 43be75d2d64074d5158ec207574a66a0b432d4b1
4
+ data.tar.gz: 87df59cc018eda249fa17c6c95588bf5bc96c569
5
5
  SHA512:
6
- metadata.gz: 837e0d280e169632d08e79fb3f5703278f622a43fc7dbc3c36dec172d7fe8b46f90fa92d9634c8e2289186f1c7e0ccc218cae974931798c0f5002d833654e6a2
7
- data.tar.gz: 75dd783805b131deda512d0234fa08a517e9482751aac30b2cdc5c05ad142430bde3531f6f749c2da451c089f815b24a3502122e9a1acd1ef527dc4ad190b77d
6
+ metadata.gz: 49262b3d84f1b2004ce2cac34030da256f8418fa323cd06c940427cc012d9d724a69bfc7a27ac8777f8d286cec225077296f38f9d2b190270ac313e0150bdc27
7
+ data.tar.gz: c2843b60c8df18431bbf0cf88d52d8b783d301b3ead6475b9e1d5d4add90517593ad1ac56a78d3f752d0d42221fa0db53fcf458479cbe86c8aac09014cdc61bc
@@ -2,6 +2,7 @@ require 'yaml'
2
2
  require 'digest/md5'
3
3
  require 'logger'
4
4
  require 'socket'
5
+ require "time"
5
6
  require "uri"
6
7
 
7
8
  require 'failbot/version'
@@ -11,13 +12,9 @@ require "failbot/compat"
11
12
  # exception logger du jour. Keeps the main app from failing or lagging if
12
13
  # the exception logger service is down or slow.
13
14
  module Failbot
14
- # The failbot relay server.
15
- autoload :Server, 'failbot/server'
16
-
17
15
  # Interface for posting exception data to haystack.
18
16
  autoload :Haystack, 'failbot/haystack'
19
17
 
20
- autoload :BERTBackend, 'failbot/bert_backend'
21
18
  autoload :FileBackend, 'failbot/file_backend'
22
19
  autoload :HerokuBackend, 'failbot/heroku_backend'
23
20
  autoload :HTTPBackend, 'failbot/http_backend'
@@ -27,10 +24,18 @@ module Failbot
27
24
  # prevent recursive calls to Failbot.report!
28
25
  attr_accessor :already_reporting
29
26
 
27
+ # see failbot/exit_hook.rb for more on these
28
+ @failbot_loaded = true
29
+ @auto_install_hook = false
30
+
31
+ # This must be required before any of the method definitions below so that
32
+ # stubbed methods are replaced properly.
33
+ require 'failbot/exit_hook'
34
+
30
35
  # Public: Setup the backend for reporting exceptions.
31
36
  def setup(settings={}, default_context={})
32
37
  deprecated_settings = %w[
33
- backend host port haystack workers service_logs
38
+ backend host port haystack
34
39
  raise_errors
35
40
  ]
36
41
 
@@ -48,8 +53,6 @@ module Failbot
48
53
 
49
54
  self.backend =
50
55
  case (name = settings["FAILBOT_BACKEND"])
51
- when "bert"
52
- Failbot::BERTBackend.new(URI(settings["FAILBOT_BACKEND_BERT_URL"]))
53
56
  when "memory"
54
57
  Failbot::MemoryBackend.new
55
58
  when "file"
@@ -62,7 +65,8 @@ module Failbot
62
65
  raise ArgumentError, "Unknown backend: #{name.inspect}"
63
66
  end
64
67
 
65
- @raise_errors = !settings["FAILBOT_RAISE"].to_s.empty?
68
+ @raise_errors = !settings["FAILBOT_RAISE"].to_s.empty?
69
+ @report_errors = settings["FAILBOT_REPORT"] != "0"
66
70
  end
67
71
 
68
72
  # Bring in deprecated methods
@@ -126,6 +130,7 @@ module Failbot
126
130
  end
127
131
 
128
132
  def report!(e, other = {})
133
+ return unless @report_errors
129
134
  data = squash_context(exception_info(e), other)
130
135
 
131
136
  if already_reporting
@@ -171,7 +176,9 @@ module Failbot
171
176
  value = (value.call rescue nil) if value.kind_of?(Proc)
172
177
  merged[key.to_s] =
173
178
  case value
174
- when String, Numeric, true, false
179
+ when Numeric
180
+ value
181
+ when String, true, false
175
182
  value.to_s
176
183
  else
177
184
  value.inspect
@@ -216,33 +223,6 @@ module Failbot
216
223
  res
217
224
  end
218
225
 
219
- # Installs an at_exit hook to report exceptions that raise all the way out of
220
- # the stack and halt the interpreter. This is useful for catching boot time
221
- # errors as well and even signal kills.
222
- #
223
- # To use, call this method very early during the program's boot to cover as
224
- # much code as possible:
225
- #
226
- # require 'failbot'
227
- # Failbot.install_unhandled_exception_hook!
228
- #
229
- # Returns true when the hook was installed, nil when the hook had previously
230
- # been installed by another component.
231
- def install_unhandled_exception_hook!
232
- # only install the hook once, even when called from multiple locations
233
- return if @unhandled_exception_hook_installed
234
-
235
- # the $! is set when the interpreter is exiting due to an exception
236
- at_exit do
237
- boom = $!
238
- if boom && !@raise_errors && !boom.is_a?(SystemExit)
239
- report(boom, 'argv' => ([$0]+ARGV).join(" "), 'halting' => true)
240
- end
241
- end
242
-
243
- @unhandled_exception_hook_installed = true
244
- end
245
-
246
226
  def logger
247
227
  @logger ||= Logger.new($stderr)
248
228
  end
@@ -256,4 +236,12 @@ module Failbot
256
236
  end
257
237
 
258
238
  extend self
239
+
240
+ # If the library was lazy loaded due to failbot/exit_hook.rb and a delayed
241
+ # config is set, configure the library now.
242
+ if @delayed_settings
243
+ setup(@delayed_settings, @delayed_default_context)
244
+ @delayed_settings = nil
245
+ @delayed_default_context = nil
246
+ end
259
247
  end
@@ -40,9 +40,6 @@ module Failbot
40
40
  # memory - Dummy backend that simply save exceptions in memory. Typically
41
41
  # used in testing environments.
42
42
  #
43
- # bert - The BERT-RPC backend relays exceptions using the bert library.
44
- # See <https://github.com/mojombo/bert> for details.
45
- #
46
43
  # heroku - In-process posting for outside of vpn apps
47
44
  #
48
45
  # file - Append JSON-encoded exceptions to a file.
@@ -77,6 +74,23 @@ module Failbot
77
74
  @raise_errors = v
78
75
  end
79
76
 
77
+ def report_errors?
78
+ warn "#{caller[0]} Failbot.report_errors? is deprecated and will be " \
79
+ "removed in subsequent releases."
80
+
81
+ if @report_errors.nil?
82
+ config['report_errors']
83
+ else
84
+ @report_errors
85
+ end
86
+ end
87
+
88
+ def report_errors=(v)
89
+ warn "#{caller[0]} Failbot.report_errors= is deprecated and will be " \
90
+ "removed in subsequent releases."
91
+ @report_errors = v
92
+ end
93
+
80
94
  # Load and initialize the exception reporting backend as specified by
81
95
  # the 'backend' configuration option.
82
96
  #
@@ -90,9 +104,6 @@ module Failbot
90
104
  warn "#{caller[0]} Failbot.backend! is deprecated and will be " \
91
105
  "removed in subsequent releases."
92
106
  case backend_name
93
- when 'bert'
94
- url = URI("bertrpc://#{config["host"]}:#{config["port"]}")
95
- Failbot::BERTBackend.new(url)
96
107
  when 'memory'
97
108
  Failbot::MemoryBackend.new
98
109
  when 'file'
@@ -128,14 +139,6 @@ module Failbot
128
139
  backend.report(data)
129
140
  end
130
141
 
131
- def service
132
- warn "#{caller[0]} Failbot.service is deprecated and will be " \
133
- "removed in subsequent releases."
134
- @service ||= BERTRPC::Service.new(config['host'], config['port'])
135
- end
136
-
137
- alias svc service
138
-
139
142
  def fail
140
143
  warn "#{caller[0]} Failbot.fail is deprecated and will be " \
141
144
  "removed in subsequent releases."
@@ -1,16 +1,86 @@
1
1
  # This file exists so that the unhandled exception hook may easily be injected
2
- # into programs that don't register it themselves. To use, set RUBYOPT or pass
3
- # an -r argument to ruby:
2
+ # into programs that don't register it themselves. It also provides a
3
+ # lightweight failbot interface that doesn't bring in any other libraries until
4
+ # a report is made, which is useful for environments where boot time is
5
+ # important.
4
6
  #
5
- # With RUBYOPT:
7
+ # To use, set RUBYOPT or pass an -r argument to ruby:
6
8
  #
7
9
  # RUBYOPT=rfailbot/exit_hook some-program.rb
8
10
  #
9
- # With ruby -r:
11
+ # Or:
10
12
  #
11
13
  # ruby -rfailbot/exit_hook some-program.rb
12
14
  #
13
- # Note: it may be necessary to also require rubygems w/ RUBYOPT or -r before
14
- # requiring failbot/exit_hook.
15
- require 'failbot'
16
- Failbot.install_unhandled_exception_hook!
15
+ # Your program can also require this library instead of 'failbot' to minimize
16
+ # the amount of up-front processing required and automatically install the exit
17
+ # hook.
18
+ #
19
+ # require 'failbot/exit_hook'
20
+ #
21
+ # The 'failbot' lib is loaded in full the first time an actual report is made.
22
+ module Failbot
23
+ # Config hash sent to setup method. We store this off so we have it when we
24
+ # need to actually load stuff.
25
+ @delayed_settings = nil
26
+ @delayed_default_context = nil
27
+
28
+ # Have we loaded the whole failbot lib yet?
29
+ @failbot_loaded = false if !defined?(@failbot_loaded)
30
+
31
+ # Has the unhandled exception hook been installed yet?
32
+ @unhandled_exception_hook_installed = false
33
+
34
+ # Should we automatically install the exit hook? This is true when this
35
+ # library is required directly, false when the main 'failbot' library is
36
+ # required directly.
37
+ @auto_install_hook = true if !defined?(@auto_install_hook)
38
+
39
+ # Installs an at_exit hook to report exceptions that raise all the way out of
40
+ # the stack and halt the interpreter. This is useful for catching boot time
41
+ # errors as well and even signal kills.
42
+ #
43
+ # To use, call this method very early during the program's boot to cover as
44
+ # much code as possible:
45
+ #
46
+ # require 'failbot'
47
+ # Failbot.install_unhandled_exception_hook!
48
+ #
49
+ # Returns true when the hook was installed, nil when the hook had previously
50
+ # been installed by another component.
51
+ def install_unhandled_exception_hook!
52
+ # only install the hook once, even when called from multiple locations
53
+ return if @unhandled_exception_hook_installed
54
+
55
+ # the $! is set when the interpreter is exiting due to an exception
56
+ at_exit do
57
+ boom = $!
58
+ if boom && !@raise_errors && !boom.is_a?(SystemExit)
59
+ report(boom, 'argv' => ([$0]+ARGV).join(" "), 'halting' => true)
60
+ end
61
+ end
62
+
63
+ @unhandled_exception_hook_installed = true
64
+ end
65
+
66
+ # Shim into Failbot.setup and store config information off for the first time
67
+ # a real method is invoked.
68
+ def setup(settings = {}, default_context = {})
69
+ @delayed_settings = settings.dup
70
+ @delayed_default_context = default_context.dup
71
+ end
72
+
73
+ # Tap into any other method invocation on the Failbot module (especially report)
74
+ # and lazy load and configure everything the first time.
75
+ def method_missing(method, *args, &block)
76
+ return super if @failbot_loaded
77
+ require 'failbot'
78
+ send(method, *args, &block)
79
+ end
80
+
81
+ extend self
82
+
83
+ # If failbot/exit_hook was required directly, without the main lib, install
84
+ # the exit hook automatically.
85
+ install_unhandled_exception_hook! if @auto_install_hook
86
+ end
@@ -3,32 +3,29 @@ development:
3
3
  host: localhost
4
4
  port: 6668
5
5
  haystack: http://haystack.dev/_needles
6
- workers: 1
7
- service_log: /tmp/failbot.log
8
6
  raise_errors: true
7
+ report_errors: false
9
8
 
10
9
  test:
11
10
  backend: memory
12
11
  host: localhost
13
12
  port: 6666
14
13
  haystack: http://haystack.dev/_needles
15
- workers: 0
16
14
  raise_errors: true
15
+ report_errors: false
17
16
 
18
17
  production:
19
18
  backend: json
20
19
  host: localhost
21
20
  port: 6668
22
21
  haystack: https://haystack.githubapp.com/_needles
23
- workers: 2
24
- service_log: /data/github/current/log/failbot.log
25
22
  raise_errors: false
23
+ report_errors: true
26
24
 
27
25
  staging:
28
26
  backend: json
29
27
  host: localhost
30
28
  port: 6668
31
29
  haystack: https://haystack.githubapp.com/_needles
32
- workers: 1
33
- service_log: /data/github/current/log/failbot.log
34
30
  raise_errors: false
31
+ report_errors: true
@@ -1,15 +1,23 @@
1
- require 'json'
1
+ require 'yajl'
2
2
 
3
3
  module Failbot
4
4
  class JSONBackend
5
5
  def initialize(host, port)
6
+ if host.to_s.empty?
7
+ raise ArgumentError, "FAILBOT_BACKEND_JSON_HOST setting required."
8
+ end
9
+ if port.to_s.empty?
10
+ raise ArgumentError, "FAILBOT_BACKEND_JSON_PORT setting required."
11
+ end
12
+
6
13
  @host = host
7
14
  @port = port
8
15
  end
9
16
 
10
17
  def report(data)
11
18
  @socket = TCPSocket.new @host, @port
12
- @socket.send(data.to_json, 0)
19
+ payload = Yajl.dump(data)
20
+ @socket.send(payload, 0)
13
21
  @socket.close
14
22
  end
15
23
 
@@ -1,3 +1,3 @@
1
1
  module Failbot
2
- VERSION = "0.9.6"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,88 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: failbot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.6
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - '@rtomayko'
8
- - '@atmos'
9
- - '@sr'
7
+ - "@rtomayko"
8
+ - "@atmos"
9
+ - "@sr"
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-08-11 00:00:00.000000000 Z
13
+ date: 2014-08-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: yajl-ruby
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - ~>
19
+ - - "~>"
20
20
  - !ruby/object:Gem::Version
21
21
  version: '1.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - ~>
26
+ - - "~>"
27
27
  - !ruby/object:Gem::Version
28
28
  version: '1.1'
29
- - !ruby/object:Gem::Dependency
30
- name: bertrpc
31
- requirement: !ruby/object:Gem::Requirement
32
- requirements:
33
- - - ~>
34
- - !ruby/object:Gem::Version
35
- version: 1.3.0
36
- type: :runtime
37
- prerelease: false
38
- version_requirements: !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ~>
41
- - !ruby/object:Gem::Version
42
- version: 1.3.0
43
29
  - !ruby/object:Gem::Dependency
44
30
  name: rake
45
31
  requirement: !ruby/object:Gem::Requirement
46
32
  requirements:
47
- - - ~>
33
+ - - "~>"
48
34
  - !ruby/object:Gem::Version
49
35
  version: 0.8.7
50
36
  type: :development
51
37
  prerelease: false
52
38
  version_requirements: !ruby/object:Gem::Requirement
53
39
  requirements:
54
- - - ~>
40
+ - - "~>"
55
41
  - !ruby/object:Gem::Version
56
42
  version: 0.8.7
57
43
  - !ruby/object:Gem::Dependency
58
44
  name: rack-test
59
45
  requirement: !ruby/object:Gem::Requirement
60
46
  requirements:
61
- - - ~>
47
+ - - "~>"
62
48
  - !ruby/object:Gem::Version
63
49
  version: '0.6'
64
50
  type: :development
65
51
  prerelease: false
66
52
  version_requirements: !ruby/object:Gem::Requirement
67
53
  requirements:
68
- - - ~>
54
+ - - "~>"
69
55
  - !ruby/object:Gem::Version
70
56
  version: '0.6'
71
- description: '...'
57
+ description: "..."
72
58
  email:
73
59
  - github+failbot@lists.github.com
74
- executables:
75
- - failbot
60
+ executables: []
76
61
  extensions: []
77
62
  extra_rdoc_files: []
78
63
  files:
79
64
  - lib/failbot.rb
80
- - lib/failbot/bert_backend.rb
81
65
  - lib/failbot/compat.rb
82
66
  - lib/failbot/exit_hook.rb
83
67
  - lib/failbot/failbot.yml
84
68
  - lib/failbot/file_backend.rb
85
- - lib/failbot/handler.rb
86
69
  - lib/failbot/haystack.rb
87
70
  - lib/failbot/heroku_backend.rb
88
71
  - lib/failbot/http_backend.rb
@@ -90,9 +73,7 @@ files:
90
73
  - lib/failbot/memory_backend.rb
91
74
  - lib/failbot/middleware.rb
92
75
  - lib/failbot/resque_failure_backend.rb
93
- - lib/failbot/server.rb
94
76
  - lib/failbot/version.rb
95
- - bin/failbot
96
77
  homepage: http://github.com/github/failbot#readme
97
78
  licenses: []
98
79
  metadata: {}
@@ -102,17 +83,17 @@ require_paths:
102
83
  - lib
103
84
  required_ruby_version: !ruby/object:Gem::Requirement
104
85
  requirements:
105
- - - '>='
86
+ - - ">="
106
87
  - !ruby/object:Gem::Version
107
88
  version: '0'
108
89
  required_rubygems_version: !ruby/object:Gem::Requirement
109
90
  requirements:
110
- - - '>='
91
+ - - ">="
111
92
  - !ruby/object:Gem::Version
112
93
  version: 1.3.6
113
94
  requirements: []
114
95
  rubyforge_project:
115
- rubygems_version: 2.0.3
96
+ rubygems_version: 2.2.2
116
97
  signing_key:
117
98
  specification_version: 4
118
99
  summary: Deliver exceptions to Haystack
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'failbot'
3
- Failbot::Server.new(port=ARGV.shift, tmp=ARGV.shift).exec!
4
-
5
- # vim:ft=ruby
@@ -1,17 +0,0 @@
1
- require 'bertrpc'
2
-
3
- module Failbot
4
- class BERTBackend
5
- def initialize(url)
6
- @service = BERTRPC::Service.new(url.host, url.port)
7
- end
8
-
9
- def report(data)
10
- @service.cast.failbot.report(data)
11
- end
12
-
13
- def reports
14
- raise NotImplementedError
15
- end
16
- end
17
- end
@@ -1,28 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'time'
3
- require 'failbot'
4
-
5
- # Reopen stderr/stdout on the logfile if enabled.
6
- if log_file = Failbot::config['service_log']
7
- $stderr.reopen(log_file, 'ab')
8
- $stdout.reopen($stderr)
9
- [$stderr, $stdout].each { |fd| fd.sync = true }
10
- end
11
- warn "failbot handler #$$ starting in #{Failbot::environment} at #{Time.now.iso8601}"
12
-
13
- require 'ernie'
14
- require 'failbot/haystack'
15
-
16
- # The Ernie handler implementation responsible for delivering exception reports
17
- # to the exception backend. The report method is made available as a BERT-RPC
18
- # service.
19
- module Failbot::Handler
20
- def report(data)
21
- Failbot::Haystack.send_data(data)
22
- true
23
- end
24
- end
25
-
26
- Ernie.expose(:failbot, Failbot::Handler)
27
-
28
- # vim:ft=ruby
@@ -1,53 +0,0 @@
1
- require 'failbot'
2
- require 'tmpdir'
3
-
4
- module Failbot
5
- # Interface for starting the exception relay server. This class constructs a
6
- # temporary config file for ernie and starts the erlang server process.
7
- class Server
8
- def initialize(port=nil, tmpdir=nil)
9
- @port = (port || 6666).to_i
10
- @tmp = tmpdir || Dir.tmpdir
11
- end
12
-
13
- attr_reader :port
14
- attr_reader :tmp
15
-
16
- def workers
17
- Failbot.config['workers'] || 1
18
- end
19
-
20
- def handler_file
21
- File.expand_path('../handler.rb', __FILE__)
22
- end
23
-
24
- def pid_file
25
- "#{@tmp}/failbot.#{port}.pid"
26
- end
27
-
28
- def configure
29
- write_config
30
- config_file
31
- end
32
-
33
- def config_file
34
- "#{@tmp}/ernie.failbot.#{Failbot.environment}.cfg"
35
- end
36
-
37
- def write_config
38
- File.open(config_file, 'wb') do |io|
39
- io.write((<<-ERLANG).gsub(/^ {10}/, ''))
40
- [{module, failbot},
41
- {type, external},
42
- {command, "ruby #{handler_file}"},
43
- {count, #{workers}}].
44
- ERLANG
45
- end
46
- end
47
-
48
- def exec!
49
- configure
50
- exec "ernie", "-p", port.to_s, "-P", pid_file, "-d", "-c", config_file
51
- end
52
- end
53
- end