module Hoptoad class Notifier def self.send_error(exception, params, env) data = { 'api_key' => ENV['HOPTOAD_API_KEY'], 'error_class' => exception.class.name, 'error_message' => "#{exception.class.name}: #{exception.message}", 'backtrace' => exception.backtrace, 'environment' => env, 'request' => { 'params' => params, 'path' => env['REQUEST_PATH'] }, 'session' => { 'key' => env['rack.session'], 'data' => env['rack.session'] } } data = { 'notice' => clean_non_serializable_data(data) } url = URI.parse( 'http://hoptoadapp.com:80/notices/' ) Net::HTTP.start( url.host, url.port ) do |http| headers = { 'Content-type' => 'application/x-yaml', 'Accept' => 'text/xml, application/xml' } http.read_timeout = 5 # seconds http.open_timeout = 2 # seconds # http.use_ssl = HoptoadNotifier.secure response = begin http.post( url.path, data.to_yaml, headers ) rescue TimeoutError => e puts "Timeout while contacting the Hoptoad server." nil end case response when Net::HTTPSuccess puts "Hoptoad notification sent." else puts "Hoptoad notification failure: #{response.class}" if response.respond_to? :body puts response.body end end end end def self.serializable?(value) #:nodoc: value.is_a?(Fixnum) || value.is_a?(Array) || value.is_a?(String) || value.is_a?(Hash) || value.is_a?(Bignum) end def self.clean_non_serializable_data(data) #:nodoc: data.select{|k,v| serializable?(v) }.inject({}) do |h, pair| h[pair.first] = pair.last.is_a?(Hash) ? clean_non_serializable_data(pair.last) : pair.last h end end end end