class Resque::Failure::Exceptional

A Resque failure backend that sends exception data to getexceptional.com

Constants

Version

Attributes

api_key[RW]
deliver[RW]
http_open_timeout[RW]

HTTP client option

http_read_timeout[RW]

HTTP client option

proxy_host[RW]

HTTP proxy option

proxy_pass[RW]

HTTP proxy option

proxy_port[RW]

HTTP proxy option

proxy_user[RW]

HTTP proxy option

use_ssl[RW]

Public Class Methods

configure() { |self| ... } click to toggle source

Configures the failure backend. At a minimum you will need to set an api_key.

@example Setting your API Key and enabling SSL:

Resque::Failure::Exceptional.configure do |config|
  config.api_key = '505f2518c41866bb0be7ba434bb2b079'
  config.use_ssl = true
end
# File lib/resque/failure/exceptional.rb, line 29
def self.configure
  yield self
end

Public Instance Methods

api_request() click to toggle source

API request data structure.

@return [Hash] data structure expected by the api.

# File lib/resque/failure/exceptional.rb, line 152
def api_request
  {
    'request' => {
      'parameters' => {
        'queue' => queue.to_s,
        'job_class' => payload['class'].to_s,
        'job_args' => payload['args'],
        'worker' => worker.to_s
      }
    },
    'application_environment' => {
      'env' => ENV.to_hash,
      'application_root_directory' => ENV['PWD']
    },
    'exception' => {
      'occurred_at' => Time.now.iso8601,
      'message' => "#{exception.class.name}: #{exception.message}",
      'backtrace' => Array(exception.backtrace),
      'exception_class' => exception.class.name
    },
    'rescue_block' => {
      'name' => 'Resque Failure'
    },
    'client' => {
      'name' => 'resque-exceptional',
      'version' => Resque::Failure::Exceptional::Version,
      'protocol_version' => 5
    }
  }
end
compressed_request() click to toggle source

Returns the compressed request data.

# File lib/resque/failure/exceptional.rb, line 77
def compressed_request
  Zlib::Deflate.deflate(MultiJson.dump(api_request), Zlib::BEST_SPEED)
end
deliver?() click to toggle source

Helper method to check if errors should be submitted to exceptional API.

@return [Boolean] true if deliver is enabled.

# File lib/resque/failure/exceptional.rb, line 138
def deliver?
  self.class.deliver.nil? || self.class.deliver
end
http_client() click to toggle source

Configures a HTTP client.

@return [Net::HTTP] http client.

# File lib/resque/failure/exceptional.rb, line 106
def http_client
  # pass any proxy settings.
  proxy = Net::HTTP::Proxy(self.class.proxy_host, self.class.proxy_port,
                           self.class.proxy_user, self.class.proxy_pass)
  http = proxy.new('api.exceptional.io', http_port)

  # set http client options.
  http.read_timeout = self.class.http_read_timeout || 5
  http.open_timeout = self.class.http_open_timeout || 2
  http.use_ssl = use_ssl?

  http
end
http_headers() click to toggle source

HTTP headers to send.

@return [Hash] http headers.

# File lib/resque/failure/exceptional.rb, line 68
def http_headers
  {
    'Content-Type' => 'application/json',
    'Accept'       => 'application/json',
    'User-Agent'   => "resque-exceptional/#{Version}"
  }
end
http_path_query() click to toggle source

Path & query options used by the HTTP Post.

@raise [APIKeyError] if the api_key is not set. @return [String] http path & query options.

# File lib/resque/failure/exceptional.rb, line 85
def http_path_query
  raise APIKeyError, 'api key must be set.' unless self.class.api_key
  hash_param = uniqueness_hash.nil? ? nil : "&hash=#{uniqueness_hash}"
  "/api/errors?api_key=#{self.class.api_key}&protocol_version=5#{hash_param}"
end
http_port() click to toggle source

Helper method to return the correct HTTP port number, depending on if were using SSL or not.

@return [Fixnum] HTTP port number.

# File lib/resque/failure/exceptional.rb, line 124
def http_port
  use_ssl? ? 443 : 80
end
http_post_request() click to toggle source

Sends a HTTP Post to the exceptional api.

@return [Net::HTTPResponse] http response data. @return [nil] if something went wrong.

# File lib/resque/failure/exceptional.rb, line 52
def http_post_request
  begin
    return http_client.post(http_path_query, compressed_request, http_headers)
  rescue APIKeyError
    log 'error - you must set your api_key.'
  rescue TimeoutError
    log 'fail - timeout while contacting the api server.'
  rescue Exception => e
    log "fail - exception raised during http post. (#{e.class.name}: #{e.message})"
  end
  nil
end
log(msg) click to toggle source

Adds a prefix to log messages.

@param [String] msg your log message.

Calls superclass method
# File lib/resque/failure/exceptional.rb, line 145
def log(msg)
  super("resque-exception - #{msg}")
end
save() click to toggle source

Sends the exception data to the exceptional api.

When a job fails, a new instance is created and save is called.

# File lib/resque/failure/exceptional.rb, line 36
def save
  return unless deliver?
  return unless response = http_post_request

  if response.code == '200'
    log "success - api accepted the exception data."
  else
    body = response.body if response.respond_to? :body
    log "fail - expected: 200 OK, received: #{response.code} #{response.message}"
  end
end
uniqueness_hash() click to toggle source

Calculates a uniqueness md5sum of the exception backtrace if available.

nb. this isn’t documented in the public api… not sure if we should use it or not…

@return [String] md5sum of the backtrace. @return [nil] if we don’t have a backtrace available.

# File lib/resque/failure/exceptional.rb, line 98
def uniqueness_hash
  return nil if (exception.backtrace.nil? || exception.backtrace.empty?)
  Digest::MD5.hexdigest(exception.backtrace.join)
end
use_ssl?() click to toggle source

Helper method to check if were using SSL or not.

@return [Boolean] true if ssl is enabled.

# File lib/resque/failure/exceptional.rb, line 131
def use_ssl?
  self.class.use_ssl || false
end