square-hoptoad_notifier 2.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +427 -0
- data/INSTALL +25 -0
- data/MIT-LICENSE +22 -0
- data/README.md +435 -0
- data/README_FOR_HEROKU_ADDON.md +93 -0
- data/Rakefile +227 -0
- data/SUPPORTED_RAILS_VERSIONS +10 -0
- data/TESTING.rdoc +8 -0
- data/generators/hoptoad/hoptoad_generator.rb +88 -0
- data/generators/hoptoad/lib/insert_commands.rb +34 -0
- data/generators/hoptoad/lib/rake_commands.rb +24 -0
- data/generators/hoptoad/templates/capistrano_hook.rb +6 -0
- data/generators/hoptoad/templates/hoptoad_notifier_tasks.rake +25 -0
- data/generators/hoptoad/templates/initializer.rb +6 -0
- data/lib/hoptoad_notifier.rb +153 -0
- data/lib/hoptoad_notifier/backtrace.rb +99 -0
- data/lib/hoptoad_notifier/capistrano.rb +20 -0
- data/lib/hoptoad_notifier/configuration.rb +242 -0
- data/lib/hoptoad_notifier/notice.rb +337 -0
- data/lib/hoptoad_notifier/rack.rb +42 -0
- data/lib/hoptoad_notifier/rails.rb +41 -0
- data/lib/hoptoad_notifier/rails/action_controller_catcher.rb +30 -0
- data/lib/hoptoad_notifier/rails/controller_methods.rb +68 -0
- data/lib/hoptoad_notifier/rails/error_lookup.rb +33 -0
- data/lib/hoptoad_notifier/rails/javascript_notifier.rb +42 -0
- data/lib/hoptoad_notifier/rails3_tasks.rb +82 -0
- data/lib/hoptoad_notifier/railtie.rb +32 -0
- data/lib/hoptoad_notifier/sender.rb +83 -0
- data/lib/hoptoad_notifier/shared_tasks.rb +29 -0
- data/lib/hoptoad_notifier/tasks.rb +83 -0
- data/lib/hoptoad_notifier/user_informer.rb +23 -0
- data/lib/hoptoad_notifier/version.rb +3 -0
- data/lib/hoptoad_tasks.rb +44 -0
- data/lib/rails/generators/hoptoad/hoptoad_generator.rb +94 -0
- data/lib/templates/javascript_notifier.erb +13 -0
- data/lib/templates/rescue.erb +91 -0
- data/rails/init.rb +1 -0
- data/script/integration_test.rb +38 -0
- data/test/backtrace_test.rb +118 -0
- data/test/catcher_test.rb +331 -0
- data/test/configuration_test.rb +216 -0
- data/test/helper.rb +248 -0
- data/test/hoptoad_tasks_test.rb +152 -0
- data/test/javascript_notifier_test.rb +52 -0
- data/test/logger_test.rb +85 -0
- data/test/notice_test.rb +448 -0
- data/test/notifier_test.rb +222 -0
- data/test/rack_test.rb +58 -0
- data/test/rails_initializer_test.rb +36 -0
- data/test/sender_test.rb +161 -0
- data/test/user_informer_test.rb +29 -0
- metadata +225 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Rails::Generator::Commands::Create.class_eval do
|
|
2
|
+
def rake(cmd, opts = {})
|
|
3
|
+
logger.rake "rake #{cmd}"
|
|
4
|
+
unless system("rake #{cmd}")
|
|
5
|
+
logger.rake "#{cmd} failed. Rolling back"
|
|
6
|
+
command(:destroy).invoke!
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Rails::Generator::Commands::Destroy.class_eval do
|
|
12
|
+
def rake(cmd, opts = {})
|
|
13
|
+
unless opts[:generate_only]
|
|
14
|
+
logger.rake "rake #{cmd}"
|
|
15
|
+
system "rake #{cmd}"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Rails::Generator::Commands::List.class_eval do
|
|
21
|
+
def rake(cmd, opts = {})
|
|
22
|
+
logger.rake "rake #{cmd}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Don't load anything when running the gems:* tasks.
|
|
2
|
+
# Otherwise, hoptoad_notifier will be considered a framework gem.
|
|
3
|
+
# https://thoughtbot.lighthouseapp.com/projects/14221/tickets/629
|
|
4
|
+
unless ARGV.any? {|a| a =~ /^gems/}
|
|
5
|
+
|
|
6
|
+
Dir[File.join(RAILS_ROOT, 'vendor', 'gems', 'hoptoad_notifier-*')].each do |vendored_notifier|
|
|
7
|
+
$: << File.join(vendored_notifier, 'lib')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
begin
|
|
11
|
+
require 'hoptoad_notifier/tasks'
|
|
12
|
+
rescue LoadError => exception
|
|
13
|
+
namespace :hoptoad do
|
|
14
|
+
%w(deploy test log_stdout).each do |task_name|
|
|
15
|
+
desc "Missing dependency for hoptoad:#{task_name}"
|
|
16
|
+
task task_name do
|
|
17
|
+
$stderr.puts "Failed to run hoptoad:#{task_name} because of missing dependency."
|
|
18
|
+
$stderr.puts "You probably need to run `rake gems:install` to install the hoptoad_notifier gem"
|
|
19
|
+
abort exception.inspect
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'net/https'
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
begin
|
|
5
|
+
require 'active_support'
|
|
6
|
+
rescue LoadError
|
|
7
|
+
require 'activesupport'
|
|
8
|
+
end
|
|
9
|
+
require 'hoptoad_notifier/version'
|
|
10
|
+
require 'hoptoad_notifier/configuration'
|
|
11
|
+
require 'hoptoad_notifier/notice'
|
|
12
|
+
require 'hoptoad_notifier/sender'
|
|
13
|
+
require 'hoptoad_notifier/backtrace'
|
|
14
|
+
require 'hoptoad_notifier/rack'
|
|
15
|
+
require 'hoptoad_notifier/user_informer'
|
|
16
|
+
|
|
17
|
+
require 'hoptoad_notifier/railtie' if defined?(Rails::Railtie)
|
|
18
|
+
|
|
19
|
+
# Gem for applications to automatically post errors to the Hoptoad of their choice.
|
|
20
|
+
module HoptoadNotifier
|
|
21
|
+
|
|
22
|
+
API_VERSION = "2.0"
|
|
23
|
+
LOG_PREFIX = "** [Hoptoad] "
|
|
24
|
+
|
|
25
|
+
HEADERS = {
|
|
26
|
+
'Content-type' => 'text/xml',
|
|
27
|
+
'Accept' => 'text/xml, application/xml'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class << self
|
|
31
|
+
# The sender object is responsible for delivering formatted data to the Hoptoad server.
|
|
32
|
+
# Must respond to #send_to_hoptoad. See HoptoadNotifier::Sender.
|
|
33
|
+
attr_accessor :sender
|
|
34
|
+
|
|
35
|
+
# A Hoptoad configuration object. Must act like a hash and return sensible
|
|
36
|
+
# values for all Hoptoad configuration options. See HoptoadNotifier::Configuration.
|
|
37
|
+
attr_accessor :configuration
|
|
38
|
+
|
|
39
|
+
# Tell the log that the Notifier is good to go
|
|
40
|
+
def report_ready
|
|
41
|
+
write_verbose_log("Notifier #{VERSION} ready to catch errors")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Prints out the environment info to the log for debugging help
|
|
45
|
+
def report_environment_info
|
|
46
|
+
write_verbose_log("Environment Info: #{environment_info}")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Prints out the response body from Hoptoad for debugging help
|
|
50
|
+
def report_response_body(response)
|
|
51
|
+
write_verbose_log("Response from Hoptoad: \n#{response}")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Returns the Ruby version, Rails version, and current Rails environment
|
|
55
|
+
def environment_info
|
|
56
|
+
info = "[Ruby: #{RUBY_VERSION}]"
|
|
57
|
+
info << " [#{configuration.framework}]"
|
|
58
|
+
info << " [Env: #{configuration.environment_name}]"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Writes out the given message to the #logger
|
|
62
|
+
def write_verbose_log(message)
|
|
63
|
+
logger.info LOG_PREFIX + message if logger
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Look for the Rails logger currently defined
|
|
67
|
+
def logger
|
|
68
|
+
self.configuration.logger
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Call this method to modify defaults in your initializers.
|
|
72
|
+
#
|
|
73
|
+
# @example
|
|
74
|
+
# HoptoadNotifier.configure do |config|
|
|
75
|
+
# config.api_key = '1234567890abcdef'
|
|
76
|
+
# config.secure = false
|
|
77
|
+
# end
|
|
78
|
+
def configure(silent = false)
|
|
79
|
+
self.configuration ||= Configuration.new
|
|
80
|
+
yield(configuration)
|
|
81
|
+
self.sender = Sender.new(configuration)
|
|
82
|
+
report_ready unless silent
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Sends an exception manually using this method, even when you are not in a controller.
|
|
86
|
+
#
|
|
87
|
+
# @param [Exception] exception The exception you want to notify Hoptoad about.
|
|
88
|
+
# @param [Hash] opts Data that will be sent to Hoptoad.
|
|
89
|
+
#
|
|
90
|
+
# @option opts [String] :api_key The API key for this project. The API key is a unique identifier that Hoptoad uses for identification.
|
|
91
|
+
# @option opts [String] :error_message The error returned by the exception (or the message you want to log).
|
|
92
|
+
# @option opts [String] :backtrace A backtrace, usually obtained with +caller+.
|
|
93
|
+
# @option opts [String] :request The controller's request object.
|
|
94
|
+
# @option opts [String] :session The contents of the user's session.
|
|
95
|
+
# @option opts [String] :environment ENV merged with the contents of the request's environment.
|
|
96
|
+
def notify(exception, opts = {})
|
|
97
|
+
send_notice(build_notice_for(exception, opts))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Sends the notice unless it is one of the default ignored exceptions
|
|
101
|
+
# @see HoptoadNotifier.notify
|
|
102
|
+
def notify_or_ignore(exception, opts = {})
|
|
103
|
+
notice = build_notice_for(exception, opts)
|
|
104
|
+
send_notice(notice) unless notice.ignore?
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def build_lookup_hash_for(exception, options = {})
|
|
108
|
+
notice = build_notice_for(exception, options)
|
|
109
|
+
|
|
110
|
+
result = {}
|
|
111
|
+
result[:action] = notice.action rescue nil
|
|
112
|
+
result[:component] = notice.component rescue nil
|
|
113
|
+
result[:error_class] = notice.error_class if notice.error_class
|
|
114
|
+
result[:environment_name] = 'production'
|
|
115
|
+
|
|
116
|
+
unless notice.backtrace.lines.empty?
|
|
117
|
+
result[:file] = notice.backtrace.lines.first.file
|
|
118
|
+
result[:line_number] = notice.backtrace.lines.first.number
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
result
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
private
|
|
125
|
+
|
|
126
|
+
def send_notice(notice)
|
|
127
|
+
if configuration.public?
|
|
128
|
+
sender.send_to_hoptoad(notice.to_xml)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def build_notice_for(exception, opts = {})
|
|
133
|
+
exception = unwrap_exception(exception)
|
|
134
|
+
if exception.respond_to?(:to_hash)
|
|
135
|
+
opts = opts.merge(exception.to_hash)
|
|
136
|
+
else
|
|
137
|
+
opts = opts.merge(:exception => exception)
|
|
138
|
+
end
|
|
139
|
+
Notice.new(configuration.merge(opts))
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def unwrap_exception(exception)
|
|
143
|
+
if exception.respond_to?(:original_exception)
|
|
144
|
+
exception.original_exception
|
|
145
|
+
elsif exception.respond_to?(:continued_exception)
|
|
146
|
+
exception.continued_exception
|
|
147
|
+
else
|
|
148
|
+
exception
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module HoptoadNotifier
|
|
2
|
+
# Front end to parsing the backtrace for each notice
|
|
3
|
+
class Backtrace
|
|
4
|
+
|
|
5
|
+
# Handles backtrace parsing line by line
|
|
6
|
+
class Line
|
|
7
|
+
|
|
8
|
+
INPUT_FORMAT = %r{^([^:]+):(\d+)(?::in `([^']+)')?$}.freeze
|
|
9
|
+
|
|
10
|
+
# The file portion of the line (such as app/models/user.rb)
|
|
11
|
+
attr_reader :file
|
|
12
|
+
|
|
13
|
+
# The line number portion of the line
|
|
14
|
+
attr_reader :number
|
|
15
|
+
|
|
16
|
+
# The method of the line (such as index)
|
|
17
|
+
attr_reader :method
|
|
18
|
+
|
|
19
|
+
# Parses a single line of a given backtrace
|
|
20
|
+
# @param [String] unparsed_line The raw line from +caller+ or some backtrace
|
|
21
|
+
# @return [Line] The parsed backtrace line
|
|
22
|
+
def self.parse(unparsed_line)
|
|
23
|
+
_, file, number, method = unparsed_line.match(INPUT_FORMAT).to_a
|
|
24
|
+
new(file, number, method)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def initialize(file, number, method)
|
|
28
|
+
self.file = file
|
|
29
|
+
self.number = number
|
|
30
|
+
self.method = method
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Reconstructs the line in a readable fashion
|
|
34
|
+
def to_s
|
|
35
|
+
"#{file}:#{number}:in `#{method}'"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ==(other)
|
|
39
|
+
to_s == other.to_s
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def inspect
|
|
43
|
+
"<Line:#{to_s}>"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
attr_writer :file, :number, :method
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# holder for an Array of Backtrace::Line instances
|
|
52
|
+
attr_reader :lines
|
|
53
|
+
|
|
54
|
+
def self.parse(ruby_backtrace, opts = {})
|
|
55
|
+
ruby_lines = split_multiline_backtrace(ruby_backtrace)
|
|
56
|
+
|
|
57
|
+
filters = opts[:filters] || []
|
|
58
|
+
filtered_lines = ruby_lines.to_a.map do |line|
|
|
59
|
+
filters.inject(line) do |line, proc|
|
|
60
|
+
proc.call(line)
|
|
61
|
+
end
|
|
62
|
+
end.compact
|
|
63
|
+
|
|
64
|
+
lines = filtered_lines.collect do |unparsed_line|
|
|
65
|
+
Line.parse(unparsed_line)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
instance = new(lines)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def initialize(lines)
|
|
72
|
+
self.lines = lines
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def inspect
|
|
76
|
+
"<Backtrace: " + lines.collect { |line| line.inspect }.join(", ") + ">"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def ==(other)
|
|
80
|
+
if other.respond_to?(:lines)
|
|
81
|
+
lines == other.lines
|
|
82
|
+
else
|
|
83
|
+
false
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
attr_writer :lines
|
|
90
|
+
|
|
91
|
+
def self.split_multiline_backtrace(backtrace)
|
|
92
|
+
if backtrace.to_a.size == 1
|
|
93
|
+
backtrace.to_a.first.split(/\n\s*/)
|
|
94
|
+
else
|
|
95
|
+
backtrace
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Defines deploy:notify_hoptoad which will send information about the deploy to Hoptoad.
|
|
2
|
+
|
|
3
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
|
4
|
+
after "deploy", "deploy:notify_hoptoad"
|
|
5
|
+
after "deploy:migrations", "deploy:notify_hoptoad"
|
|
6
|
+
|
|
7
|
+
namespace :deploy do
|
|
8
|
+
desc "Notify Hoptoad of the deployment"
|
|
9
|
+
task :notify_hoptoad, :except => { :no_release => true } do
|
|
10
|
+
rails_env = fetch(:hoptoad_env, fetch(:rails_env, "production"))
|
|
11
|
+
local_user = ENV['USER'] || ENV['USERNAME']
|
|
12
|
+
executable = RUBY_PLATFORM.downcase.include?('mswin') ? 'rake.bat' : 'rake'
|
|
13
|
+
notify_command = "#{executable} hoptoad:deploy TO=#{rails_env} REVISION=#{current_revision} REPO=#{repository} USER=#{local_user}"
|
|
14
|
+
notify_command << " API_KEY=#{ENV['API_KEY']}" if ENV['API_KEY']
|
|
15
|
+
puts "Notifying Hoptoad of Deploy (#{notify_command})"
|
|
16
|
+
`#{notify_command}`
|
|
17
|
+
puts "Hoptoad Notification Complete."
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
module HoptoadNotifier
|
|
2
|
+
# Used to set up and modify settings for the notifier.
|
|
3
|
+
class Configuration
|
|
4
|
+
|
|
5
|
+
OPTIONS = [:api_key, :backtrace_filters, :development_environments,
|
|
6
|
+
:development_lookup, :environment_name, :host,
|
|
7
|
+
:http_open_timeout, :http_read_timeout, :ignore, :ignore_by_filters,
|
|
8
|
+
:ignore_user_agent, :notifier_name, :notifier_url, :notifier_version,
|
|
9
|
+
:params_filters, :project_root, :port, :protocol, :proxy_host,
|
|
10
|
+
:proxy_pass, :proxy_port, :proxy_user, :secure, :framework,
|
|
11
|
+
:user_information].freeze
|
|
12
|
+
|
|
13
|
+
# The API key for your project, found on the project edit form.
|
|
14
|
+
attr_accessor :api_key
|
|
15
|
+
|
|
16
|
+
# The host to connect to (defaults to hoptoadapp.com).
|
|
17
|
+
attr_accessor :host
|
|
18
|
+
|
|
19
|
+
# The port on which your Hoptoad server runs (defaults to 443 for secure
|
|
20
|
+
# connections, 80 for insecure connections).
|
|
21
|
+
attr_accessor :port
|
|
22
|
+
|
|
23
|
+
# +true+ for https connections, +false+ for http connections.
|
|
24
|
+
attr_accessor :secure
|
|
25
|
+
|
|
26
|
+
# The HTTP open timeout in seconds (defaults to 2).
|
|
27
|
+
attr_accessor :http_open_timeout
|
|
28
|
+
|
|
29
|
+
# The HTTP read timeout in seconds (defaults to 5).
|
|
30
|
+
attr_accessor :http_read_timeout
|
|
31
|
+
|
|
32
|
+
# The hostname of your proxy server (if using a proxy)
|
|
33
|
+
attr_accessor :proxy_host
|
|
34
|
+
|
|
35
|
+
# The port of your proxy server (if using a proxy)
|
|
36
|
+
attr_accessor :proxy_port
|
|
37
|
+
|
|
38
|
+
# The username to use when logging into your proxy server (if using a proxy)
|
|
39
|
+
attr_accessor :proxy_user
|
|
40
|
+
|
|
41
|
+
# The password to use when logging into your proxy server (if using a proxy)
|
|
42
|
+
attr_accessor :proxy_pass
|
|
43
|
+
|
|
44
|
+
# A list of parameters that should be filtered out of what is sent to Hoptoad.
|
|
45
|
+
# By default, all "password" attributes will have their contents replaced.
|
|
46
|
+
attr_reader :params_filters
|
|
47
|
+
|
|
48
|
+
# A list of filters for cleaning and pruning the backtrace. See #filter_backtrace.
|
|
49
|
+
attr_reader :backtrace_filters
|
|
50
|
+
|
|
51
|
+
# A list of filters for ignoring exceptions. See #ignore_by_filter.
|
|
52
|
+
attr_reader :ignore_by_filters
|
|
53
|
+
|
|
54
|
+
# A list of exception classes to ignore. The array can be appended to.
|
|
55
|
+
attr_reader :ignore
|
|
56
|
+
|
|
57
|
+
# A list of user agents that are being ignored. The array can be appended to.
|
|
58
|
+
attr_reader :ignore_user_agent
|
|
59
|
+
|
|
60
|
+
# A list of environments in which notifications should not be sent.
|
|
61
|
+
attr_accessor :development_environments
|
|
62
|
+
|
|
63
|
+
# +true+ if you want to check for production errors matching development errors, +false+ otherwise.
|
|
64
|
+
attr_accessor :development_lookup
|
|
65
|
+
|
|
66
|
+
# The name of the environment the application is running in
|
|
67
|
+
attr_accessor :environment_name
|
|
68
|
+
|
|
69
|
+
# The path to the project in which the error occurred, such as the RAILS_ROOT
|
|
70
|
+
attr_accessor :project_root
|
|
71
|
+
|
|
72
|
+
# The name of the notifier library being used to send notifications (such as "Hoptoad Notifier")
|
|
73
|
+
attr_accessor :notifier_name
|
|
74
|
+
|
|
75
|
+
# The version of the notifier library being used to send notifications (such as "1.0.2")
|
|
76
|
+
attr_accessor :notifier_version
|
|
77
|
+
|
|
78
|
+
# The url of the notifier library being used to send notifications
|
|
79
|
+
attr_accessor :notifier_url
|
|
80
|
+
|
|
81
|
+
# The logger used by HoptoadNotifier
|
|
82
|
+
attr_accessor :logger
|
|
83
|
+
|
|
84
|
+
# The text that the placeholder is replaced with. {{error_id}} is the actual error number.
|
|
85
|
+
attr_accessor :user_information
|
|
86
|
+
|
|
87
|
+
# The framework HoptoadNotifier is configured to use
|
|
88
|
+
attr_accessor :framework
|
|
89
|
+
|
|
90
|
+
DEFAULT_PARAMS_FILTERS = %w(password password_confirmation).freeze
|
|
91
|
+
|
|
92
|
+
DEFAULT_BACKTRACE_FILTERS = [
|
|
93
|
+
lambda { |line|
|
|
94
|
+
if defined?(HoptoadNotifier.configuration.project_root) && HoptoadNotifier.configuration.project_root.to_s != ''
|
|
95
|
+
line.gsub(/#{HoptoadNotifier.configuration.project_root}/, "[PROJECT_ROOT]")
|
|
96
|
+
else
|
|
97
|
+
line
|
|
98
|
+
end
|
|
99
|
+
},
|
|
100
|
+
lambda { |line| line.gsub(/^\.\//, "") },
|
|
101
|
+
lambda { |line|
|
|
102
|
+
if defined?(Gem)
|
|
103
|
+
Gem.path.inject(line) do |line, path|
|
|
104
|
+
line.gsub(/#{path}/, "[GEM_ROOT]")
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
},
|
|
108
|
+
lambda { |line| line if line !~ %r{lib/hoptoad_notifier} }
|
|
109
|
+
].freeze
|
|
110
|
+
|
|
111
|
+
IGNORE_DEFAULT = ['ActiveRecord::RecordNotFound',
|
|
112
|
+
'ActionController::RoutingError',
|
|
113
|
+
'ActionController::InvalidAuthenticityToken',
|
|
114
|
+
'CGI::Session::CookieStore::TamperedWithCookie',
|
|
115
|
+
'ActionController::UnknownAction',
|
|
116
|
+
'AbstractController::ActionNotFound']
|
|
117
|
+
|
|
118
|
+
alias_method :secure?, :secure
|
|
119
|
+
|
|
120
|
+
def initialize
|
|
121
|
+
@secure = false
|
|
122
|
+
@host = 'hoptoadapp.com'
|
|
123
|
+
@http_open_timeout = 2
|
|
124
|
+
@http_read_timeout = 5
|
|
125
|
+
@params_filters = DEFAULT_PARAMS_FILTERS.dup
|
|
126
|
+
@backtrace_filters = DEFAULT_BACKTRACE_FILTERS.dup
|
|
127
|
+
@ignore_by_filters = []
|
|
128
|
+
@ignore = IGNORE_DEFAULT.dup
|
|
129
|
+
@ignore_user_agent = []
|
|
130
|
+
@development_environments = %w(development test cucumber)
|
|
131
|
+
@development_lookup = true
|
|
132
|
+
@notifier_name = 'Hoptoad Notifier'
|
|
133
|
+
@notifier_version = VERSION
|
|
134
|
+
@notifier_url = 'http://hoptoadapp.com'
|
|
135
|
+
@framework = 'Standalone'
|
|
136
|
+
@user_information = 'Hoptoad Error {{error_id}}'
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Takes a block and adds it to the list of backtrace filters. When the filters
|
|
140
|
+
# run, the block will be handed each line of the backtrace and can modify
|
|
141
|
+
# it as necessary.
|
|
142
|
+
#
|
|
143
|
+
# @example
|
|
144
|
+
# config.filter_bracktrace do |line|
|
|
145
|
+
# line.gsub(/^#{Rails.root}/, "[RAILS_ROOT]")
|
|
146
|
+
# end
|
|
147
|
+
#
|
|
148
|
+
# @param [Proc] block The new backtrace filter.
|
|
149
|
+
# @yieldparam [String] line A line in the backtrace.
|
|
150
|
+
def filter_backtrace(&block)
|
|
151
|
+
self.backtrace_filters << block
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Takes a block and adds it to the list of ignore filters.
|
|
155
|
+
# When the filters run, the block will be handed the exception.
|
|
156
|
+
# @example
|
|
157
|
+
# config.ignore_by_filter do |exception_data|
|
|
158
|
+
# true if exception_data[:error_class] == "RuntimeError"
|
|
159
|
+
# end
|
|
160
|
+
#
|
|
161
|
+
# @param [Proc] block The new ignore filter
|
|
162
|
+
# @yieldparam [Hash] data The exception data given to +HoptoadNotifier.notify+
|
|
163
|
+
# @yieldreturn [Boolean] If the block returns true the exception will be ignored, otherwise it will be processed by hoptoad.
|
|
164
|
+
def ignore_by_filter(&block)
|
|
165
|
+
self.ignore_by_filters << block
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Overrides the list of default ignored errors.
|
|
169
|
+
#
|
|
170
|
+
# @param [Array<Exception>] names A list of exceptions to ignore.
|
|
171
|
+
def ignore_only=(names)
|
|
172
|
+
@ignore = [names].flatten
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Overrides the list of default ignored user agents
|
|
176
|
+
#
|
|
177
|
+
# @param [Array<String>] A list of user agents to ignore
|
|
178
|
+
def ignore_user_agent_only=(names)
|
|
179
|
+
@ignore_user_agent = [names].flatten
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Allows config options to be read like a hash
|
|
183
|
+
#
|
|
184
|
+
# @param [Symbol] option Key for a given attribute
|
|
185
|
+
def [](option)
|
|
186
|
+
send(option)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Returns a hash of all configurable options
|
|
190
|
+
def to_hash
|
|
191
|
+
OPTIONS.inject({}) do |hash, option|
|
|
192
|
+
hash.merge(option.to_sym => send(option))
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Returns a hash of all configurable options merged with +hash+
|
|
197
|
+
#
|
|
198
|
+
# @param [Hash] hash A set of configuration options that will take precedence over the defaults
|
|
199
|
+
def merge(hash)
|
|
200
|
+
to_hash.merge(hash)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Determines if the notifier will send notices.
|
|
204
|
+
# @return [Boolean] Returns +false+ if in a development environment, +true+ otherwise.
|
|
205
|
+
def public?
|
|
206
|
+
!development_environments.include?(environment_name)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def port
|
|
210
|
+
@port || default_port
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def protocol
|
|
214
|
+
if secure?
|
|
215
|
+
'https'
|
|
216
|
+
else
|
|
217
|
+
'http'
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def js_notifier=(*args)
|
|
222
|
+
warn '[HOPTOAD] config.js_notifier has been deprecated and has no effect. You should use <%= hoptoad_javascript_notifier %> directly at the top of your layouts. Be sure to place it before all other javascript.'
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def environment_filters
|
|
226
|
+
warn 'config.environment_filters has been deprecated and has no effect.'
|
|
227
|
+
[]
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
private
|
|
231
|
+
|
|
232
|
+
def default_port
|
|
233
|
+
if secure?
|
|
234
|
+
443
|
|
235
|
+
else
|
|
236
|
+
80
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
end
|