Permalink
Browse files

Now depend on safely for safely running code and logging backtraces

  • Loading branch information...
kennethkalmer committed May 8, 2011
1 parent 0961fdd commit b189804ef596c5313b283a38953d60b870a58fbc
View
@@ -1,3 +1,10 @@
+== 0.1.9 (WIP)
+
+* Depend on the 'safely' gem for the safely method and logging backtraces
+* Fixed compatibility with ruote-amqp 2.2.0
+* AMQP fixes by @marcbowes
+* Updated to rspec 2 (various contributors)
+
== 0.1.18.1 2010-08-04
* Fixed issue with our own amqp.rb file causing havoc on Ruby 1.8.7
View
@@ -19,7 +19,6 @@ module DaemonKit
autoload :Application, 'daemon_kit/application'
autoload :Arguments, 'daemon_kit/arguments'
autoload :Config, 'daemon_kit/config'
- autoload :Safety, 'daemon_kit/safety'
autoload :PidFile, 'daemon_kit/pid_file'
autoload :AbstractLogger, 'daemon_kit/abstract_logger'
autoload :EM, 'daemon_kit/em'
@@ -1,32 +0,0 @@
-module DaemonKit
- module ErrorHandlers
- # Error handlers in DaemonKit are used by the #Safety class. Any
- # error handler has to support the interface provided by this
- # class. It's also required that safety handlers implement a
- # singleton approach (handled by default by #Base).
- class Base
-
- class << self
-
- @instance = nil
-
- def instance
- @instance ||= new
- end
- private :new
-
- # When we're inherited, immediately register the handler with
- # the safety net
- def inherited( child ) #:nodoc:
- Safety.register_error_handler( child )
- end
- end
-
- # Error handlers should overwrite this method and implement
- # their own reporting method.
- def handle_exception( exception )
- raise NoMethodError, "Error handler doesn't support #handle_exception"
- end
- end
- end
-end
@@ -1,180 +0,0 @@
-require 'net/http'
-
-module DaemonKit
- module ErrorHandlers
- # Error reporting via Hoptoad.
- class Hoptoad < Base
-
- # Front end to parsing the backtrace for each notice
- # (Graciously borrowed from http://github.com/thoughtbot/hoptoad_notifier)
- class Backtrace
-
- # Handles backtrace parsing line by line
- # (Graciously borrowed from http://github.com/thoughtbot/hoptoad_notifier)
- class Line
-
- INPUT_FORMAT = %r{^([^:]+):(\d+)(?::in `([^']+)')?$}.freeze
-
- # The file portion of the line (such as app/models/user.rb)
- attr_reader :file
-
- # The line number portion of the line
- attr_reader :number
-
- # The method of the line (such as index)
- attr_reader :method
-
- # Parses a single line of a given backtrace
- # @param [String] unparsed_line The raw line from +caller+ or some backtrace
- # @return [Line] The parsed backtrace line
- def self.parse(unparsed_line)
- _, file, number, method = unparsed_line.match(INPUT_FORMAT).to_a
- new(file, number, method)
- end
-
- def initialize(file, number, method)
- self.file = file
- self.number = number
- self.method = method
- end
-
- # Reconstructs the line in a readable fashion
- def to_s
- "#{file}:#{number}:in `#{method}'"
- end
-
- def ==(other)
- to_s == other.to_s
- end
-
- def inspect
- "<Line:#{to_s}>"
- end
-
- def to_xml
- data = [ method, file, number ].map { |s| URI.escape( s || 'unknown', %q{"'<>&} ) }
- %q{<line method="%s" file="%s" number="%s" />} % data
- end
-
- private
-
- attr_writer :file, :number, :method
- end
-
- # holder for an Array of Backtrace::Line instances
- attr_reader :lines
-
- def self.parse(ruby_backtrace, opts = {})
- ruby_lines = split_multiline_backtrace(ruby_backtrace)
-
- filters = opts[:filters] || []
- filtered_lines = ruby_lines.to_a.map do |line|
- filters.inject(line) do |line, proc|
- proc.call(line)
- end
- end.compact
-
- lines = filtered_lines.collect do |unparsed_line|
- Line.parse(unparsed_line)
- end
-
- instance = new(lines)
- end
-
- def initialize(lines)
- self.lines = lines
- end
-
- def inspect
- "<Backtrace: " + lines.collect { |line| line.inspect }.join(", ") + ">"
- end
-
- def ==(other)
- if other.respond_to?(:lines)
- lines == other.lines
- else
- false
- end
- end
-
- private
-
- attr_writer :lines
-
- def self.split_multiline_backtrace(backtrace)
- if backtrace.to_a.size == 1
- backtrace.to_a.first.split(/\n\s*/)
- else
- backtrace
- end
- end
- end
-
- # Your hoptoad API key
- @api_key = nil
- attr_accessor :api_key
-
- def handle_exception( exception )
- headers = {
- 'Content-type' => 'text/xml',
- 'Accept' => 'text/xml, application/xml'
- }
-
- http = Net::HTTP.new( url.host, url.port )
- data = format_exception( exception )
- DaemonKit.logger.debug("Sending to Hoptoad: #{data}")
-
- response = begin
- http.post( url.path, data, headers )
- rescue TimeoutError => e
- DaemonKit.logger.error("Timeout while contacting the Hoptoad server.")
- nil
- end
- case response
- when Net::HTTPSuccess then
- DaemonKit.logger.info "Hoptoad Success: #{response.class}"
- else
- DaemonKit.logger.error "Hoptoad Failure: #{response.class}\n#{response.body if response.respond_to? :body}"
- end
- end
-
- def url
- URI.parse("http://hoptoadapp.com/notifier_api/v2/notices")
- end
-
- def format_exception( exception )
- lines = Backtrace.parse( exception.backtrace )
- exception_message= exception.message
- exception_message.gsub!("\"","&quot;")
- exception_message.gsub!("'","&apos;")
- exception_message.gsub!("&","&amp;")
- exception_message.gsub!("<","&lt;")
- exception_message.gsub!(">","&gt;")
-
- <<-EOF
-<?xml version="1.0" encoding="UTF-8"?>
-<notice version="2.0">
- <api-key>#{self.api_key}</api-key>
- <notifier>
- <name>daemon-kit</name>
- <version>#{DaemonKit::VERSION}</version>
- <url>http://github.com/kennethkalmer/daemon-kit</url>
- </notifier>
- <error>
- <class>#{exception.class.name}</class>
- <message>#{exception_message}</message>
- <backtrace>
- #{Backtrace.parse( exception.backtrace ).lines.inject('') { |string,line| string << line.to_xml }}
- </backtrace>
- </error>
- <server-environment>
- <project-root>#{DaemonKit.root}</project-root>
- <environment-name>#{DaemonKit.env}</environment-name>
- </server-environment>
-</notice>
- EOF
- end
- end
-
- end
-end
@@ -8,6 +8,7 @@
$LOAD_PATH.include?( File.expand_path('../', __FILE__).to_absolute_path )
require 'daemon_kit'
+require 'safely'
module DaemonKit
@@ -74,7 +75,7 @@ def self.shutdown( clean = false, do_exit = false )
end
end
- log_exceptions if DaemonKit.configuration.backtraces && !clean
+ Safely::Backtrace.safe_shutdown! if DaemonKit.configuration.backtraces && clean
DaemonKit.logger.warn "Shutting down #{DaemonKit.configuration.daemon_name}"
@@ -203,37 +204,16 @@ def include_core_lib
end
def configure_backtraces
- Thread.abort_on_exception = configuration.backtraces
+ Thread.abort_on_exception = true
+
+ Safely::Backtrace.trace_directory = File.join( DAEMON_ROOT, "log" )
+ Safely::Backtrace.enable!
end
def set_process_name
$0 = configuration.daemon_name
end
- def self.log_exceptions
- trace_file = File.join( DaemonKit.root, 'log', "backtrace-#{Time.now.strftime('%Y%m%d%H%M%S')}-#{Process.pid}.log" )
- trace_log = Logger.new( trace_file )
-
- # Find the last exception
- e = nil
- ObjectSpace.each_object {|o|
- if ::Exception === o
- e = o
- end
- }
-
- trace_log.info "*** Below you'll find the most recent exception thrown, this will likely (but not certainly) be the exception that made #{DaemonKit.configuration.daemon_name} exit abnormally ***"
- trace_log.error e
-
- trace_log.info "*** Below you'll find all the exception objects in memory, some of them may have been thrown in your application, others may just be in memory because they are standard exceptions ***"
- ObjectSpace.each_object {|o|
- if ::Exception === o
- trace_log.error o
- end
- }
-
- trace_log.close
- end
end
# Holds our various configuration values
@@ -268,8 +248,8 @@ class Configuration
# Use the force kill patch? Give the number of seconds
configurable :force_kill_wait
- # Should be log backtraces
- configurable :backtraces, false
+ # Should we log backtraces
+ configurable :backtraces, true
# Configurable umask
configurable :umask, 0022
@@ -283,9 +263,6 @@ class Configuration
# Collection of signal traps
attr_reader :signal_traps
- # Our safety net (#Safety) instance
- attr_accessor :safety_net
-
# :nodoc: Shutdown hooks
attr_reader :shutdown_hooks
@@ -301,8 +278,6 @@ def initialize
self.force_kill_wait = false
- self.safety_net = DaemonKit::Safety.instance
-
@signal_traps = {}
@shutdown_hooks = []
end
Oops, something went wrong.

0 comments on commit b189804

Please sign in to comment.