Skip to content
This repository has been archived by the owner on Jun 8, 2019. It is now read-only.

Commit

Permalink
Merge branch 'development-error-lookup'
Browse files Browse the repository at this point in the history
  • Loading branch information
tristandunn committed Nov 11, 2009
2 parents 3963e93 + 2f1fed2 commit 94f25c9
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 6 deletions.
17 changes: 17 additions & 0 deletions lib/hoptoad_notifier.rb
Expand Up @@ -101,6 +101,23 @@ def notify_or_ignore(exception, opts = {})
send_notice(notice) unless notice.ignore?
end

def build_lookup_hash_for(exception, options = {})
notice = build_notice_for(exception, options)

result = {}
result[:action] = notice.action rescue nil
result[:component] = notice.component rescue nil
result[:error_class] = notice.error_class if notice.error_class
result[:environment_name] = 'production'

unless notice.backtrace.lines.empty?
result[:file] = notice.backtrace.lines.first.file
result[:line_number] = notice.backtrace.lines.first.number
end

result
end

private

def send_notice(notice)
Expand Down
19 changes: 19 additions & 0 deletions lib/hoptoad_notifier/catcher.rb
Expand Up @@ -7,6 +7,8 @@ def self.included(base) #:nodoc:
if base.instance_methods.map(&:to_s).include? 'rescue_action_in_public' and !base.instance_methods.map(&:to_s).include? 'rescue_action_in_public_without_hoptoad'
base.send(:alias_method, :rescue_action_in_public_without_hoptoad, :rescue_action_in_public)
base.send(:alias_method, :rescue_action_in_public, :rescue_action_in_public_with_hoptoad)
base.send(:alias_method, :rescue_action_locally_without_hoptoad, :rescue_action_locally)
base.send(:alias_method, :rescue_action_locally, :rescue_action_locally_with_hoptoad)
end
end

Expand All @@ -21,6 +23,23 @@ def rescue_action_in_public_with_hoptoad(exception)
rescue_action_in_public_without_hoptoad(exception)
end

def rescue_action_locally_with_hoptoad(exception)
result = rescue_action_locally_without_hoptoad(exception)

if HoptoadNotifier.configuration.development_lookup
path = "#{File.dirname(File.dirname(__FILE__))}/templates/rescue.erb"
notice = HoptoadNotifier.build_lookup_hash_for(exception, request_data_for_hoptoad)

result << @template.render(
:file => path,
:locals => { :host => HoptoadNotifier.configuration.host,
:api_key => HoptoadNotifier.configuration.api_key,
:notice => notice })
end

result
end

# This method should be used for sending manual notifications while you are still
# inside the controller. Otherwise it works like HoptoadNotifier.notify.
def notify_hoptoad(hash_or_exception)
Expand Down
14 changes: 9 additions & 5 deletions lib/hoptoad_notifier/configuration.rb
Expand Up @@ -3,11 +3,11 @@ module HoptoadNotifier
class Configuration

OPTIONS = [:api_key, :backtrace_filters, :development_environments,
:environment_filters, :environment_name, :host, :http_open_timeout,
:http_read_timeout, :ignore, :ignore_by_filters, :ignore_user_agent,
:notifier_name, :notifier_url, :notifier_version, :params_filters,
:project_root, :port, :protocol, :proxy_host, :proxy_pass, :proxy_port,
:proxy_user, :secure].freeze
:development_lookup, :environment_filters, :environment_name, :host,
:http_open_timeout, :http_read_timeout, :ignore, :ignore_by_filters,
:ignore_user_agent, :notifier_name, :notifier_url, :notifier_version,
:params_filters, :project_root, :port, :protocol, :proxy_host,
:proxy_pass, :proxy_port, :proxy_user, :secure].freeze

# The API key for your project, found on the project edit form.
attr_accessor :api_key
Expand Down Expand Up @@ -63,6 +63,9 @@ class Configuration
# A list of environments in which notifications should not be sent.
attr_accessor :development_environments

# +true+ if you want to check for production errors matching development errors, +false+ otherwise.
attr_accessor :development_lookup

# The name of the environment the application is running in
attr_accessor :environment_name

Expand Down Expand Up @@ -123,6 +126,7 @@ def initialize
@ignore = IGNORE_DEFAULT.dup
@ignore_user_agent = []
@development_environments = %w(development test)
@development_lookup = true
@notifier_name = 'Hoptoad Notifier'
@notifier_version = VERSION
@notifier_url = 'http://hoptoadapp.com'
Expand Down
91 changes: 91 additions & 0 deletions lib/templates/rescue.erb
@@ -0,0 +1,91 @@
<script type="text/javascript">
var Hoptoad = {
host : <%= host.to_json %>,
api_key : <%= api_key.to_json %>,
notice : <%= notice.to_json %>,
message : 'This error exists in production!',

initialize: function() {
if (this.initialized) {
return;
} else {
this.initialized = true;
}

var data = [];

for (var key in this.notice) {
data[data.length] = 'notice[' + key + ']=' + this.notice[key];
}

data[data.length] = 'notice[api_key]=' + this.api_key;
data[data.length] = 'callback=Hoptoad.onSuccess';
data[data.length] = '_=' + (new Date()).getTime();

var head = document.getElementsByTagName('head')[0];
var done = false;

var
script = document.createElement('script');
script.src = 'http://' + this.host + '/notices_api/v1/notices/exist?' +
data.join('&');
script.type = 'text/javascript';
script.onload = script.onreadystatechange = function(){
if (!done && (!this.readyState ||
this.readyState == 'loaded' || this.readyState == 'complete')) {

done = true;

// Handle memory leak in IE. (via jQuery)
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
};

head.appendChild(script);
},

onSuccess: function(error) {
var body = document.getElementsByTagName('body')[0];
var text = document.createTextNode(this.message);
var element = document.createElement('a');

element.id = 'hoptoad';
element.href = 'http://' + error.subdomain + '.' + this.host +
'/projects/' + error.project_id + '/errors/' + error.id;
element.appendChild(text);

body.insertBefore(element, body.firstChild);

var h1 = document.getElementsByTagName('h1')[0];
var pre = document.getElementsByTagName('pre')[0];
var wrapper = document.createElement('div');

wrapper.id = 'wrapper';
wrapper.appendChild(h1);
wrapper.appendChild(pre);

body.insertBefore(wrapper, body.children[1]);
}
};

window.onload = function() {
Hoptoad.initialize.apply(Hoptoad);
};
</script>

<style type="text/css">
#hoptoad {
background: #FFF url(http://hoptoadapp.com/images/fell-off-the-toad.gif) no-repeat top right;
color: #F00;
padding: 45px 101px 45px 12px;
font-size: 14px;
font-weight: bold;
display: block;
float: right;
}

#wrapper {
padding-right: 360px;
}
</style>
35 changes: 35 additions & 0 deletions test/catcher_test.rb
Expand Up @@ -219,4 +219,39 @@ def process_action_with_automatic_notification(args = {})
assert_sent_hash filtered_cgi, '/notice/request/cgi-data'
end

context "for a local error with development lookup enabled" do
setup do
HoptoadNotifier.configuration.development_lookup = true
HoptoadNotifier.stubs(:build_lookup_hash_for).returns({ :awesome => 2 })

@controller = process_action_with_automatic_notification(:local => true)
@response = @controller.response
end

should "append custom CSS and JS to response body for a local error" do
assert_match /text\/css/, @response.body
assert_match /text\/javascript/, @response.body
end

should "contain host, API key and notice JSON" do
assert_match HoptoadNotifier.configuration.host.to_json, @response.body
assert_match HoptoadNotifier.configuration.api_key.to_json, @response.body
assert_match ({ :awesome => 2 }).to_json, @response.body
end
end

context "for a local error with development lookup disabled" do
setup do
HoptoadNotifier.configuration.development_lookup = false

@controller = process_action_with_automatic_notification(:local => true)
@response = @controller.response
end

should "not append custom CSS and JS to response for a local error" do
assert_no_match /text\/css/, @response.body
assert_no_match /text\/javascript/, @response.body
end
end

end
4 changes: 3 additions & 1 deletion test/configuration_test.rb
Expand Up @@ -27,6 +27,7 @@ class ConfigurationTest < Test::Unit::TestCase
HoptoadNotifier::Configuration::DEFAULT_BACKTRACE_FILTERS
assert_config_default :ignore,
HoptoadNotifier::Configuration::IGNORE_DEFAULT
assert_config_default :development_lookup, true
end

should "provide default values for secure connections" do
Expand Down Expand Up @@ -66,6 +67,7 @@ class ConfigurationTest < Test::Unit::TestCase
assert_config_overridable :notifier_name
assert_config_overridable :notifier_url
assert_config_overridable :environment_name
assert_config_overridable :development_lookup
end

should "have an api key" do
Expand All @@ -80,7 +82,7 @@ class ConfigurationTest < Test::Unit::TestCase
:http_read_timeout, :ignore, :ignore_by_filters, :ignore_user_agent,
:notifier_name, :notifier_url, :notifier_version, :params_filters,
:project_root, :port, :protocol, :proxy_host, :proxy_pass, :proxy_port,
:proxy_user, :secure].each do |option|
:proxy_user, :secure, :development_lookup].each do |option|
assert_equal config[option], hash[option], "Wrong value for #{option}"
end
end
Expand Down
47 changes: 47 additions & 0 deletions test/notifier_test.rb
Expand Up @@ -136,4 +136,51 @@ def set_development_env
end
end

context "building notice JSON for an exception" do
setup do
@params = { :controller => "users", :action => "create" }
@exception = build_exception
@hash = HoptoadNotifier.build_lookup_hash_for(@exception, @params)
end

should "set action" do
assert_equal @params[:action], @hash[:action]
end

should "set controller" do
assert_equal @params[:controller], @hash[:component]
end

should "set line number" do
assert @hash[:line_number] =~ /\d+/
end

should "set file" do
assert_equal './test/helper.rb', @hash[:file]
end

should "set rails_env to production" do
assert_equal 'production', @hash[:environment_name]
end

should "set error class" do
assert_equal 'RuntimeError', @hash[:error_class]
end

should "not set file or line number with no backtrace" do
@exception.stubs(:backtrace).returns([])

@hash = HoptoadNotifier.build_lookup_hash_for(@exception)

assert_nil @hash[:line_number]
assert_nil @hash[:file]
end

should "not set action or controller when not provided" do
@hash = HoptoadNotifier.build_lookup_hash_for(@exception)

assert_nil @hash[:action]
assert_nil @hash[:controller]
end
end
end

0 comments on commit 94f25c9

Please sign in to comment.