failbot 0.9.6 → 1.0.0

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
  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