Class: Resque::Failure::Exceptional

Inherits:
Base
  • Object
show all
Defined in:
lib/resque/failure/exceptional.rb

Overview

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

Defined Under Namespace

Classes: APIKeyError

Constant Summary collapse

Version =

Failure backend version number.

'0.2.2'

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.api_keyObject

your getexceptional api key.



12
13
14
# File 'lib/resque/failure/exceptional.rb', line 12

def api_key
  @api_key
end

.deliverObject

whether or not to submit exceptions to Exceptional



14
15
16
# File 'lib/resque/failure/exceptional.rb', line 14

def deliver
  @deliver
end

.http_open_timeoutObject

HTTP client option



18
19
20
# File 'lib/resque/failure/exceptional.rb', line 18

def http_open_timeout
  @http_open_timeout
end

.http_read_timeoutObject

HTTP client option



18
19
20
# File 'lib/resque/failure/exceptional.rb', line 18

def http_read_timeout
  @http_read_timeout
end

.proxy_hostObject

HTTP proxy option



16
17
18
# File 'lib/resque/failure/exceptional.rb', line 16

def proxy_host
  @proxy_host
end

.proxy_passObject

HTTP proxy option



16
17
18
# File 'lib/resque/failure/exceptional.rb', line 16

def proxy_pass
  @proxy_pass
end

.proxy_portObject

HTTP proxy option



16
17
18
# File 'lib/resque/failure/exceptional.rb', line 16

def proxy_port
  @proxy_port
end

.proxy_userObject

HTTP proxy option



16
17
18
# File 'lib/resque/failure/exceptional.rb', line 16

def proxy_user
  @proxy_user
end

.use_sslObject

enable/disable SSL.



13
14
15
# File 'lib/resque/failure/exceptional.rb', line 13

def use_ssl
  @use_ssl
end

Class Method Details

.configure {|_self| ... } ⇒ Object

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

Examples:

Setting your API Key and enabling SSL:

Resque::Failure::Exceptional.configure do |config|
  config.api_key = '505f2518c41866bb0be7ba434bb2b079'
  config.use_ssl = true
end

Yields:

  • (_self)

Yield Parameters:



29
30
31
# File 'lib/resque/failure/exceptional.rb', line 29

def self.configure
  yield self
end

Instance Method Details

#api_requestHash

API request data structure.

Returns:

  • (Hash)

    data structure expected by the api.



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# 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_requestObject

Returns the compressed request data.



77
78
79
# File 'lib/resque/failure/exceptional.rb', line 77

def compressed_request
  Zlib::Deflate.deflate(MultiJson.dump(api_request), Zlib::BEST_SPEED)
end

#deliver?Boolean

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

Returns:

  • (Boolean)

    true if deliver is enabled.



138
139
140
# File 'lib/resque/failure/exceptional.rb', line 138

def deliver?
  self.class.deliver.nil? || self.class.deliver
end

#http_clientNet::HTTP

Configures a HTTP client.

Returns:

  • (Net::HTTP)

    http client.



106
107
108
109
110
111
112
113
114
115
116
117
118
# 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_headersHash

HTTP headers to send.

Returns:

  • (Hash)

    http headers.



68
69
70
71
72
73
74
# 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_queryString

Path & query options used by the HTTP Post.

Returns:

  • (String)

    http path & query options.

Raises:



85
86
87
88
89
# 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_portFixnum

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

Returns:

  • (Fixnum)

    HTTP port number.



124
125
126
# File 'lib/resque/failure/exceptional.rb', line 124

def http_port
  use_ssl? ? 443 : 80
end

#http_post_requestNet::HTTPResponse?

Sends a HTTP Post to the exceptional api.

Returns:

  • (Net::HTTPResponse)

    http response data.

  • (nil)

    if something went wrong.



52
53
54
55
56
57
58
59
60
61
62
63
# 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) ⇒ Object

Adds a prefix to log messages.

Parameters:

  • msg (String)

    your log message.



145
146
147
# File 'lib/resque/failure/exceptional.rb', line 145

def log(msg)
  super("resque-exception - #{msg}")
end

#saveObject

Sends the exception data to the exceptional api.

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



36
37
38
39
40
41
42
43
44
45
46
# 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_hashString?

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…

Returns:

  • (String)

    md5sum of the backtrace.

  • (nil)

    if we don’t have a backtrace available.



98
99
100
101
# 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?Boolean

Helper method to check if were using SSL or not.

Returns:

  • (Boolean)

    true if ssl is enabled.



131
132
133
# File 'lib/resque/failure/exceptional.rb', line 131

def use_ssl?
  self.class.use_ssl || false
end