honeybadger 1.10.3 → 1.11.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +10 -0
  3. data/CHANGELOG.md +17 -10
  4. data/Gemfile.lock +1 -1
  5. data/features/rails.feature +6 -4
  6. data/features/step_definitions/rails_steps.rb +8 -0
  7. data/features/support/rails.rb +5 -0
  8. data/gemfiles/rack.gemfile.lock +1 -1
  9. data/gemfiles/rails2.3.gemfile.lock +1 -1
  10. data/gemfiles/rails3.0.gemfile.lock +1 -1
  11. data/gemfiles/rails3.1.gemfile.lock +1 -1
  12. data/gemfiles/rails3.2.gemfile.lock +1 -1
  13. data/gemfiles/rails4.gemfile.lock +1 -1
  14. data/gemfiles/rails4_cap3.gemfile +13 -0
  15. data/gemfiles/rails4_cap3.gemfile.lock +204 -0
  16. data/gemfiles/rake.gemfile.lock +1 -1
  17. data/gemfiles/sinatra.gemfile.lock +1 -1
  18. data/honeybadger.gemspec +7 -4
  19. data/lib/honeybadger.rb +14 -1
  20. data/lib/honeybadger/capistrano.rb +4 -45
  21. data/lib/honeybadger/capistrano/legacy.rb +45 -0
  22. data/lib/honeybadger/capistrano/tasks.rake +67 -0
  23. data/lib/honeybadger/configuration.rb +2 -2
  24. data/lib/honeybadger/monitor/worker.rb +1 -1
  25. data/lib/honeybadger/notice.rb +10 -1
  26. data/lib/honeybadger/rack.rb +1 -0
  27. data/lib/honeybadger/rails.rb +8 -0
  28. data/lib/honeybadger/railtie.rb +1 -7
  29. data/lib/honeybadger/stats.rb +1 -1
  30. data/lib/honeybadger/templates/{feedback_form.html.erb → feedback_form.erb} +12 -9
  31. data/lib/honeybadger/user_feedback.rb +47 -17
  32. data/lib/honeybadger_tasks.rb +3 -3
  33. data/lib/rails/generators/honeybadger/honeybadger_generator.rb +1 -2
  34. data/spec/honeybadger/capistrano_spec.rb +26 -23
  35. data/spec/honeybadger/configuration_spec.rb +25 -21
  36. data/spec/honeybadger/notice_spec.rb +30 -37
  37. data/spec/honeybadger/notifier_spec.rb +60 -4
  38. data/spec/honeybadger/rack_spec.rb +1 -0
  39. data/spec/honeybadger/user_feedback_spec.rb +29 -4
  40. data/spec/honeybadger_tasks_spec.rb +13 -4
  41. metadata +9 -6
  42. data/spec/honeybadger/stats_spec.rb +0 -57
data/honeybadger.gemspec CHANGED
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
4
4
  s.rubygems_version = '1.3.5'
5
5
 
6
6
  s.name = 'honeybadger'
7
- s.version = '1.10.3'
8
- s.date = '2014-02-05'
7
+ s.version = '1.11.0.beta1'
8
+ s.date = '2014-01-17'
9
9
 
10
10
  s.summary = 'Error reports you can be happy about.'
11
11
  s.description = 'Make managing application errors a more pleasant experience.'
@@ -74,6 +74,8 @@ Gem::Specification.new do |s|
74
74
  gemfiles/rails3.2.gemfile.lock
75
75
  gemfiles/rails4.gemfile
76
76
  gemfiles/rails4.gemfile.lock
77
+ gemfiles/rails4_cap3.gemfile
78
+ gemfiles/rails4_cap3.gemfile.lock
77
79
  gemfiles/rake.gemfile
78
80
  gemfiles/rake.gemfile.lock
79
81
  gemfiles/sinatra.gemfile
@@ -89,6 +91,8 @@ Gem::Specification.new do |s|
89
91
  lib/honeybadger/array.rb
90
92
  lib/honeybadger/backtrace.rb
91
93
  lib/honeybadger/capistrano.rb
94
+ lib/honeybadger/capistrano/legacy.rb
95
+ lib/honeybadger/capistrano/tasks.rake
92
96
  lib/honeybadger/configuration.rb
93
97
  lib/honeybadger/monitor.rb
94
98
  lib/honeybadger/monitor/railtie.rb
@@ -107,7 +111,7 @@ Gem::Specification.new do |s|
107
111
  lib/honeybadger/shared_tasks.rb
108
112
  lib/honeybadger/stats.rb
109
113
  lib/honeybadger/tasks.rb
110
- lib/honeybadger/templates/feedback_form.html.erb
114
+ lib/honeybadger/templates/feedback_form.erb
111
115
  lib/honeybadger/user_feedback.rb
112
116
  lib/honeybadger/user_informer.rb
113
117
  lib/honeybadger_tasks.rb
@@ -127,7 +131,6 @@ Gem::Specification.new do |s|
127
131
  spec/honeybadger/rails/action_controller_spec.rb
128
132
  spec/honeybadger/rails_spec.rb
129
133
  spec/honeybadger/sender_spec.rb
130
- spec/honeybadger/stats_spec.rb
131
134
  spec/honeybadger/user_feedback_spec.rb
132
135
  spec/honeybadger/user_informer_spec.rb
133
136
  spec/honeybadger_tasks_spec.rb
data/lib/honeybadger.rb CHANGED
@@ -16,7 +16,7 @@ require 'honeybadger/user_feedback'
16
16
  require 'honeybadger/railtie' if defined?(Rails::Railtie)
17
17
 
18
18
  module Honeybadger
19
- VERSION = '1.10.3'
19
+ VERSION = '1.11.0.beta1'
20
20
  LOG_PREFIX = "** [Honeybadger] "
21
21
 
22
22
  HEADERS = {
@@ -90,6 +90,19 @@ module Honeybadger
90
90
  @configuration ||= Configuration.new
91
91
  end
92
92
 
93
+ # Internal: Contacts the Honeybadger service and configures features
94
+ #
95
+ # configuration - the Configuration object to use
96
+ #
97
+ # Returns Hash features on success, NilClass on failure
98
+ def ping(configuration)
99
+ if configuration.public?
100
+ if result = sender.ping({ :version => Honeybadger::VERSION, :framework => configuration.framework, :environment => configuration.environment_name, :hostname => configuration.hostname })
101
+ configuration.features = result['features'] if result['features']
102
+ end
103
+ end
104
+ end
105
+
93
106
  # Public: Sends an exception manually using this method, even when you are not in a controller.
94
107
  #
95
108
  # exception - The exception you want to notify Honeybadger about.
@@ -1,48 +1,7 @@
1
- # Defines deploy:notify_honeybadger which will send information about the deploy to Honeybadger.
2
1
  require 'capistrano'
3
2
 
4
- module Honeybadger
5
- module Capistrano
6
- def self.load_into(configuration)
7
- configuration.load do
8
- after "deploy", "honeybadger:deploy"
9
- after "deploy:migrations", "honeybadger:deploy"
10
-
11
- namespace :honeybadger do
12
- desc <<-DESC
13
- Notify Honeybadger of the deployment by running the notification on the REMOTE machine.
14
- - Run remotely so we use remote API keys, environment, etc.
15
- DESC
16
- task :deploy, :except => { :no_release => true } do
17
- rails_env = fetch(:rails_env, "production")
18
- honeybadger_env = fetch(:honeybadger_env, fetch(:rails_env, "production"))
19
- rake_task = fetch(:honeybadger_deploy_task, 'honeybadger:deploy')
20
- local_user = ENV['USER'] || ENV['USERNAME']
21
- executable = RUBY_PLATFORM.downcase.include?('mswin') ? fetch(:rake, 'rake.bat') : fetch(:rake, 'rake')
22
- async_notify = fetch(:honeybadger_async_notify, false)
23
- directory = configuration.current_release
24
- notify_command = "cd #{directory};"
25
- notify_command << " nohup" if async_notify
26
- notify_command << " #{executable} RAILS_ENV=#{rails_env} #{rake_task} TO=#{honeybadger_env} REVISION=#{current_revision} REPO=#{repository} USER=#{local_user}"
27
- notify_command << " DRY_RUN=true" if dry_run
28
- notify_command << " API_KEY=#{ENV['API_KEY']}" if ENV['API_KEY']
29
- notify_command << " >> /dev/null 2>&1 &" if async_notify
30
- logger.info "Notifying Honeybadger of Deploy (#{notify_command})"
31
- if configuration.dry_run
32
- logger.info "DRY RUN: Notification not actually run."
33
- else
34
- result = ""
35
- run(notify_command, :once => true, :pty => false) { |ch, stream, data| result << data }
36
- # TODO: Check if SSL is active on account via result content.
37
- end
38
- logger.info "Honeybadger Notification Complete."
39
- end
40
- end
41
- end
42
- end
43
- end
44
- end
45
-
46
- if Capistrano::Configuration.instance
47
- Honeybadger::Capistrano.load_into(Capistrano::Configuration.instance)
3
+ if defined?(Capistrano::Configuration.instance)
4
+ require 'honeybadger/capistrano/legacy'
5
+ else
6
+ load File.expand_path('../capistrano/tasks.rake', __FILE__)
48
7
  end
@@ -0,0 +1,45 @@
1
+ module Honeybadger
2
+ module Capistrano
3
+ def self.load_into(configuration)
4
+ configuration.load do
5
+ after "deploy", "honeybadger:deploy"
6
+ after "deploy:migrations", "honeybadger:deploy"
7
+
8
+ namespace :honeybadger do
9
+ desc <<-DESC
10
+ Notify Honeybadger of the deployment by running the notification on the REMOTE machine.
11
+ - Run remotely so we use remote API keys, environment, etc.
12
+ DESC
13
+ task :deploy, :except => { :no_release => true } do
14
+ rails_env = fetch(:rails_env, "production")
15
+ honeybadger_env = fetch(:honeybadger_env, fetch(:rails_env, "production"))
16
+ rake_task = fetch(:honeybadger_deploy_task, 'honeybadger:deploy')
17
+ local_user = ENV['USER'] || ENV['USERNAME']
18
+ executable = RUBY_PLATFORM.downcase.include?('mswin') ? fetch(:rake, 'rake.bat') : fetch(:rake, 'rake')
19
+ async_notify = fetch(:honeybadger_async_notify, false)
20
+ directory = configuration.current_release
21
+ notify_options = "cd #{directory};"
22
+ notify_options << " nohup" if async_notify
23
+ notify_options << " #{executable} RAILS_ENV=#{rails_env} #{rake_task} TO=#{honeybadger_env} REVISION=#{current_revision} REPO=#{repository} USER=#{local_user}"
24
+ notify_options << " DRY_RUN=true" if dry_run
25
+ notify_options << " API_KEY=#{ENV['API_KEY']}" if ENV['API_KEY']
26
+ notify_options << " >> /dev/null 2>&1 &" if async_notify
27
+ logger.info "Notifying Honeybadger of Deploy (#{notify_options})"
28
+ if configuration.dry_run
29
+ logger.info "DRY RUN: Notification not actually run."
30
+ else
31
+ result = ""
32
+ run(notify_options, :once => true, :pty => false) { |ch, stream, data| result << data }
33
+ # TODO: Check if SSL is active on account via result content.
34
+ end
35
+ logger.info "Honeybadger Notification Complete."
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ if Capistrano::Configuration.instance
44
+ Honeybadger::Capistrano.load_into(Capistrano::Configuration.instance)
45
+ end
@@ -0,0 +1,67 @@
1
+ after 'deploy:finishing', 'honeybadger:deploy'
2
+
3
+ namespace :honeybadger do
4
+ def sshkit_outdated?
5
+ !::SSHKit.config.command_map.respond_to?(:prefix)
6
+ end
7
+
8
+ desc 'Notify Honeybadger of the deployment.'
9
+ task :deploy => :env do
10
+ next if sshkit_outdated?
11
+ if server = fetch(:honeybadger_server)
12
+ on server do |host|
13
+ info 'Notifying Honeybadger of deploy.'
14
+
15
+ executable = RUBY_PLATFORM.downcase.include?('mswin') ? fetch(:rake, :'rake.bat') : fetch(:rake, :rake)
16
+ rake_task = fetch(:honeybadger_deploy_task, 'honeybadger:deploy')
17
+
18
+ options = [rake_task]
19
+
20
+ if fetch(:honeybadger_async_notify, false)
21
+ ::SSHKit.config.command_map.prefix[:rake].push(:nohup)
22
+ options << '>> /dev/null 2>&1 &'
23
+ end
24
+
25
+ within release_path do
26
+ execute executable, options
27
+ end
28
+
29
+ info 'Honeybadger notification complete.'
30
+ end
31
+ end
32
+ end
33
+
34
+ desc 'Setup ENV for Honeybadger deploy rake task.'
35
+ task :env do
36
+ if sshkit_outdated?
37
+ run_locally do
38
+ warn 'Unable to notify Honeybadger: you are using an outdated version of SSHKIT. Please upgrade to >= 1.2.0.'
39
+ end
40
+ next
41
+ end
42
+
43
+ server = fetch(:honeybadger_server) do
44
+ s = primary(:app)
45
+ set(:honeybadger_server, s.select?({ :exclude => :no_release }) ? s : nil)
46
+ end
47
+
48
+ if server
49
+ on server do |host|
50
+ rails_env = fetch(:rails_env, "production")
51
+ honeybadger_env = fetch(:honeybadger_env, rails_env)
52
+ repository = fetch(:repo_url)
53
+ local_user = fetch(:honeybadger_user, ENV['USER'] || ENV['USERNAME'])
54
+ api_key = fetch(:honeybadger_api_key, ENV['HONEYBADGER_API_KEY'] || ENV['API_KEY'])
55
+ revision = fetch(:current_revision) do
56
+ within(repo_path) do
57
+ capture("cd #{repo_path} && git rev-parse --short HEAD")
58
+ end
59
+ end
60
+
61
+ env = ["RAILS_ENV=#{rails_env}", "TO=#{honeybadger_env}", "REVISION=#{revision}", "REPO=#{repository}", "USER=#{local_user}"]
62
+ env << "API_KEY=#{api_key}" if api_key
63
+ ::SSHKit.config.command_map.prefix[:rake].unshift(*env)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -261,9 +261,9 @@ module Honeybadger
261
261
 
262
262
  # Public: Determines if the notifier will send notices.
263
263
  #
264
- # Returns false if in a development environment, true otherwise.
264
+ # Returns true if allowed to talk to API, false otherwise.
265
265
  def public?
266
- !development_environments.include?(environment_name) && features['notices']
266
+ !development_environments.include?(environment_name)
267
267
  end
268
268
 
269
269
  # Public: Determines whether to send metrics
@@ -72,7 +72,7 @@ module Honeybadger
72
72
  end
73
73
  end.each_slice(@per_request) do |mm|
74
74
  begin
75
- @sender.send_metrics({ :metrics => mm.compact, :environment => Honeybadger.configuration.environment_name, :hostname => Honeybadger.configuration.hostname })
75
+ @sender.send_metrics({ :metrics => mm, :environment => Honeybadger.configuration.environment_name, :hostname => Honeybadger.configuration.hostname })
76
76
  rescue Exception => e
77
77
  log(:error, "[Honeybadger::Monitor::Worker#send_metrics] Failed to send #{mm.count} metrics: #{e.class} - #{e.message}\nBacktrace:\n#{e.backtrace.join("\n\t")}")
78
78
  end
@@ -305,7 +305,7 @@ module Honeybadger
305
305
  return nil unless url =~ /\S/
306
306
 
307
307
  url = url.dup
308
- url.scan(/&([^=]+)=([^&]+)/).each do |m|
308
+ url.scan(/(?:^|&|\?)([^=?&]+)=([^&]+)/).each do |m|
309
309
  next unless filter_key?(m[0])
310
310
  url.gsub!(/#{m[1]}/, '[FILTERED]')
311
311
  end
@@ -321,6 +321,7 @@ module Honeybadger
321
321
  if cgi_data
322
322
  clean_unserializable_data_from(:cgi_data)
323
323
  filter(cgi_data)
324
+ filter_cgi_data_params(cgi_data)
324
325
  end
325
326
  if session_data
326
327
  clean_unserializable_data_from(:session_data)
@@ -328,9 +329,17 @@ module Honeybadger
328
329
  end
329
330
  end
330
331
 
332
+ def filter_cgi_data_params(cgi_data)
333
+ cgi_data.each_pair do |key, value|
334
+ next unless value.kind_of?(String) && key =~ /\A[A-Z_]+\Z/
335
+ cgi_data[key] = filter_url(value)
336
+ end
337
+ end
338
+
331
339
  def clean_rack_request_data
332
340
  if cgi_data
333
341
  cgi_data.delete("rack.request.form_vars")
342
+ cgi_data.delete("rack.request.query_string")
334
343
  end
335
344
  end
336
345
 
@@ -22,6 +22,7 @@ module Honeybadger
22
22
  class Rack
23
23
  def initialize(app)
24
24
  @app = app
25
+ Honeybadger.configuration.framework = "Rack: #{::Rack.release}"
25
26
  end
26
27
 
27
28
  def ignored_user_agent?(env)
@@ -21,6 +21,8 @@ module Honeybadger
21
21
  Honeybadger::Rack
22
22
  ::Rails.configuration.middleware.insert_after 'Rack::Lock',
23
23
  Honeybadger::UserInformer
24
+ ::Rails.configuration.middleware.insert_after Honeybadger::UserInformer,
25
+ Honeybadger::UserFeedback
24
26
  end
25
27
 
26
28
  Honeybadger.configure(true) do |config|
@@ -29,6 +31,12 @@ module Honeybadger
29
31
  config.project_root = defined?(::Rails.root) && ::Rails.root || defined?(RAILS_ROOT) && RAILS_ROOT
30
32
  config.framework = defined?(::Rails.version) && "Rails: #{::Rails.version}" || defined?(::Rails::VERSION::STRING) && "Rails: #{::Rails::VERSION::STRING}"
31
33
  end
34
+
35
+ if defined?(::Rails.configuration) && ::Rails.configuration.respond_to?(:after_initialize)
36
+ ::Rails.configuration.after_initialize do
37
+ Honeybadger.ping(Honeybadger.configuration)
38
+ end
39
+ end
32
40
  end
33
41
  end
34
42
  end
@@ -44,13 +44,7 @@ module Honeybadger
44
44
  ::ActionDispatch::ShowExceptions.send(:include,Honeybadger::Rails::Middleware::ExceptionsCatcher)
45
45
  end
46
46
 
47
- if Honeybadger.configuration.public?
48
- if result = Honeybadger.sender.ping({ :version => Honeybadger::VERSION, :framework => Honeybadger.configuration.framework, :environment => Honeybadger.configuration.environment_name, :hostname => Honeybadger.configuration.hostname })
49
- Honeybadger.configure(true) do |config|
50
- config.features = result['features'] if result['features']
51
- end
52
- end
53
- end
47
+ Honeybadger.ping(Honeybadger.configuration)
54
48
  end
55
49
  end
56
50
  end
@@ -12,7 +12,7 @@ module Honeybadger
12
12
  def memory
13
13
  out = {}
14
14
  if HAS_MEM
15
- out[:total], out[:free], out[:buffers], out[:cached] = IO.readlines("/proc/meminfo")[0..4].map { |l| l =~ /^.*?\: +(.*?) kB$/; ($1.to_i / 1024.0).to_f }
15
+ out[:total], out[:free], out[:buffers], out[:cached] = IO.readlines("/proc/meminfo")[0..4].map { |l| l =~ /^.*?\: +(.*?) kB$/; $1.to_i / 1024.0 }
16
16
  out[:free_total] = out[:free] + out[:buffers] + out[:cached]
17
17
  end
18
18
  out
@@ -6,6 +6,7 @@
6
6
  #honeybadger_feedback_comment { height: 10em; }
7
7
  #honeybadger_feedback_submit { height: 1em; }
8
8
  #honeybadger_feedback_form .honeybadger-feedback-phone { display: none; }
9
+ #honeybadger_feedback_link { font-size: 90%; }
9
10
  </style>
10
11
 
11
12
  <script>
@@ -22,7 +23,7 @@ function honeybadgerFeedbackResponse(data) {
22
23
  if (data['error']) {
23
24
  message = data['error'];
24
25
  } else {
25
- message = "An unknown error occurred. Please try again.";
26
+ message = 'An unknown error occurred. Please try again.';
26
27
  }
27
28
 
28
29
  alert(message);
@@ -47,36 +48,38 @@ function sendHoneybadgerFeedback() {
47
48
  </script>
48
49
 
49
50
  <div id="honeybadger_feedback_success" style="display:none;">
50
- <p><strong>Thanks for the feedback!</strong></p>
51
+ <p><strong><%= I18n.t('honeybadger.feedback.thanks', :default => 'Thanks for the feedback!') %></strong></p>
51
52
  </div>
52
53
 
53
54
  <form action="<%= action %>" method="POST" id="honeybadger_feedback_form" onsubmit="return sendHoneybadgerFeedback();">
54
55
  <input type="hidden" name="token" id="honeybadger_feedback_token" value="<%= error_id %>">
55
56
 
56
- <h2>Care to help us fix this?</h2>
57
- <p>Any information you can provide will help our technical team get to the bottom of this issue.</p>
57
+ <h2><%= I18n.t('honeybadger.feedback.heading', :default => 'Care to help us fix this?') %></h2>
58
+ <p><%= I18n.t('honeybadger.feedback.explanation', :default => 'Any information you can provide will help our technical team get to the bottom of this issue.') %></p>
58
59
 
59
60
  <p class="honeybadger-feedback-name">
60
- <label for="honeybadger_feedback_name">Your name</label><br>
61
+ <label for="honeybadger_feedback_name"><%= I18n.t('honeybadger.feedback.labels.name', :default => 'Your name') %></label><br>
61
62
  <input type="text" name="name" id="honeybadger_feedback_name" size="60">
62
63
  </p>
63
64
 
64
65
  <p class="honeybadger-feedback-phone">
65
- <label for="honeybadger_feedback_phone">Your phone number</label><br>
66
+ <label for="honeybadger_feedback_phone"><%= I18n.t('honeybadger.feedback.labels.phone', :default => 'Your phone number') %></label><br>
66
67
  <input type="text" name="phone" id="honeybadger_feedback_phone" size="60">
67
68
  </p>
68
69
 
69
70
  <p class="honeybadger-feedback-email">
70
- <label for="honeybadger_feedback_email">Your email address</label><br>
71
+ <label for="honeybadger_feedback_email"><%= I18n.t('honeybadger.feedback.labels.email', :default => 'Your email address') %></label><br>
71
72
  <input type="email" name="email" id="honeybadger_feedback_email" size="60">
72
73
  </p>
73
74
 
74
75
  <p class="honeybadger-feedback-comment">
75
- <label for="honeybadger_feedback_comment">Comment (required)</label><br>
76
+ <label for="honeybadger_feedback_comment"><%= I18n.t('honeybadger.feedback.labels.comment', :default => 'Comment (required)') %></label><br>
76
77
  <textarea name="comment" id="honeybadger_feedback_comment" cols="50" rows="6" required></textarea>
77
78
  </p>
78
79
 
79
80
  <p class="honeybadger-feedback-submit">
80
- <input type="submit" id="honeybadger_feedback_submit" value="Send">
81
+ <input type="submit" id="honeybadger_feedback_submit" value="<%= I18n.t('honeybadger.feedback.submit', :default => 'Send') %>">
81
82
  </p>
82
83
  </form>
84
+
85
+ <p><a id="honeybadger_feedback_link" href="https://www.honeybadger.io/" target="_blank" title="Exception, uptime, and performance monitoring for Ruby.">Powered by Honeybadger</a></p>
@@ -1,16 +1,47 @@
1
1
  require 'erb'
2
2
  require 'uri'
3
3
 
4
+ begin
5
+ require 'i18n'
6
+ rescue LoadError
7
+ module Honeybadger
8
+ module I18n
9
+ def self.t(key, options={})
10
+ options[:default]
11
+ end
12
+ end
13
+ end
14
+ end
15
+
4
16
  module Honeybadger
5
17
  class UserFeedback
6
- TEMPLATE = File.read(File.expand_path('../templates/feedback_form.html.erb', __FILE__)).freeze
7
-
8
18
  def initialize(app)
9
19
  @app = app
10
20
  end
11
21
 
22
+ def call(env)
23
+ status, headers, body = @app.call(env)
24
+ if enabled? && env['honeybadger.error_id'] && form = render_form(env['honeybadger.error_id'])
25
+ new_body = []
26
+ body.each do |chunk|
27
+ new_body << chunk.gsub("<!-- HONEYBADGER FEEDBACK -->", form)
28
+ end
29
+ body.close if body.respond_to?(:close)
30
+ headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s
31
+ body = new_body
32
+ end
33
+ [status, headers, body]
34
+ end
35
+
36
+ def config
37
+ Honeybadger.configuration
38
+ end
39
+
40
+ def enabled?
41
+ config.feedback && config.features['feedback']
42
+ end
43
+
12
44
  def action
13
- config = Honeybadger.configuration
14
45
  URI.parse("#{config.protocol}://#{config.host}:#{config.port}/v1/feedback/").to_s
15
46
  rescue URI::InvalidURIError
16
47
  nil
@@ -18,25 +49,24 @@ module Honeybadger
18
49
 
19
50
  def render_form(error_id, action = action)
20
51
  return unless action
21
- ERB.new(TEMPLATE).result(binding)
52
+ ERB.new(@template ||= File.read(template_file)).result(binding)
22
53
  end
23
54
 
24
- def enabled?
25
- Honeybadger.configuration.feedback && Honeybadger.configuration.features['feedback']
55
+ def custom_template_file
56
+ @custom_template_file ||= config.project_root &&
57
+ File.join(config.project_root, 'lib', 'honeybadger', 'templates', 'feedback_form.erb')
26
58
  end
27
59
 
28
- def call(env)
29
- status, headers, body = @app.call(env)
30
- if enabled? && env['honeybadger.error_id'] && form = render_form(env['honeybadger.error_id'])
31
- new_body = []
32
- body.each do |chunk|
33
- new_body << chunk.gsub("<!-- HONEYBADGER FEEDBACK -->", form)
34
- end
35
- body.close if body.respond_to?(:close)
36
- headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s
37
- body = new_body
60
+ def custom_template_file?
61
+ custom_template_file && File.exists?(custom_template_file)
62
+ end
63
+
64
+ def template_file
65
+ if custom_template_file?
66
+ custom_template_file
67
+ else
68
+ File.expand_path('../templates/feedback_form.erb', __FILE__)
38
69
  end
39
- [status, headers, body]
40
70
  end
41
71
  end
42
72
  end