honeybadger 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/Gemfile +13 -0
  2. data/Gemfile.lock +114 -0
  3. data/Guardfile +5 -0
  4. data/MIT-LICENSE +22 -0
  5. data/README.md +271 -0
  6. data/Rakefile +261 -0
  7. data/SUPPORTED_RAILS_VERSIONS +26 -0
  8. data/TESTING.md +33 -0
  9. data/features/metal.feature +18 -0
  10. data/features/rack.feature +56 -0
  11. data/features/rails.feature +211 -0
  12. data/features/rake.feature +27 -0
  13. data/features/sinatra.feature +29 -0
  14. data/features/step_definitions/file_steps.rb +10 -0
  15. data/features/step_definitions/metal_steps.rb +23 -0
  16. data/features/step_definitions/rack_steps.rb +23 -0
  17. data/features/step_definitions/rails_application_steps.rb +394 -0
  18. data/features/step_definitions/rake_steps.rb +17 -0
  19. data/features/support/env.rb +17 -0
  20. data/features/support/honeybadger_shim.rb.template +8 -0
  21. data/features/support/rails.rb +201 -0
  22. data/features/support/rake/Rakefile +68 -0
  23. data/features/support/terminal.rb +107 -0
  24. data/generators/honeybadger/honeybadger_generator.rb +94 -0
  25. data/generators/honeybadger/lib/insert_commands.rb +34 -0
  26. data/generators/honeybadger/lib/rake_commands.rb +24 -0
  27. data/generators/honeybadger/templates/capistrano_hook.rb +6 -0
  28. data/generators/honeybadger/templates/honeybadger_tasks.rake +25 -0
  29. data/generators/honeybadger/templates/initializer.rb +6 -0
  30. data/honeybadger.gemspec +109 -0
  31. data/lib/honeybadger.rb +162 -0
  32. data/lib/honeybadger/backtrace.rb +123 -0
  33. data/lib/honeybadger/capistrano.rb +43 -0
  34. data/lib/honeybadger/configuration.rb +273 -0
  35. data/lib/honeybadger/notice.rb +314 -0
  36. data/lib/honeybadger/rack.rb +55 -0
  37. data/lib/honeybadger/rails.rb +34 -0
  38. data/lib/honeybadger/rails/action_controller_catcher.rb +30 -0
  39. data/lib/honeybadger/rails/controller_methods.rb +69 -0
  40. data/lib/honeybadger/rails/middleware/exceptions_catcher.rb +29 -0
  41. data/lib/honeybadger/rails3_tasks.rb +84 -0
  42. data/lib/honeybadger/railtie.rb +45 -0
  43. data/lib/honeybadger/rake_handler.rb +65 -0
  44. data/lib/honeybadger/sender.rb +120 -0
  45. data/lib/honeybadger/shared_tasks.rb +36 -0
  46. data/lib/honeybadger/tasks.rb +82 -0
  47. data/lib/honeybadger_tasks.rb +65 -0
  48. data/lib/rails/generators/honeybadger/honeybadger_generator.rb +99 -0
  49. data/rails/init.rb +1 -0
  50. data/resources/README.md +34 -0
  51. data/resources/ca-bundle.crt +3376 -0
  52. data/script/integration_test.rb +38 -0
  53. data/test/test_helper.rb +143 -0
  54. data/test/unit/backtrace_test.rb +180 -0
  55. data/test/unit/capistrano_test.rb +34 -0
  56. data/test/unit/configuration_test.rb +201 -0
  57. data/test/unit/honeybadger_tasks_test.rb +163 -0
  58. data/test/unit/logger_test.rb +72 -0
  59. data/test/unit/notice_test.rb +406 -0
  60. data/test/unit/notifier_test.rb +245 -0
  61. data/test/unit/rack_test.rb +56 -0
  62. data/test/unit/rails/action_controller_catcher_test.rb +300 -0
  63. data/test/unit/rails_test.rb +35 -0
  64. data/test/unit/sender_test.rb +257 -0
  65. metadata +315 -0
@@ -0,0 +1,23 @@
1
+ Given /^the following Rack app:$/ do |definition|
2
+ File.open(RACK_FILE, 'w') { |file| file.write(definition) }
3
+ end
4
+
5
+ When /^I perform a Rack request to "([^\"]*)"$/ do |url|
6
+ shim_file = File.join(PROJECT_ROOT, 'features', 'support', 'honeybadger_shim.rb.template')
7
+ request_file = File.join(TEMP_DIR, 'rack_request.rb')
8
+ File.open(request_file, 'w') do |file|
9
+ file.puts "require 'rubygems'"
10
+ file.puts IO.read(shim_file)
11
+ file.puts IO.read(RACK_FILE)
12
+ file.puts "env = Rack::MockRequest.env_for(#{url.inspect})"
13
+ file.puts "status, headers, body = app.call(env)"
14
+ file.puts %{puts "HTTP \#{status}"}
15
+ file.puts %{headers.each { |key, value| puts "\#{key}: \#{value}"}}
16
+ file.puts "body.each { |part| print part }"
17
+ end
18
+ @terminal.run("ruby #{request_file}")
19
+ end
20
+
21
+ Then /^I should receive a Honeybadger notification for rack$/ do
22
+ Then %{I should see "You have accessed a deleted account."}
23
+ end
@@ -0,0 +1,394 @@
1
+ require 'uri'
2
+ require 'active_support/core_ext/string/inflections'
3
+
4
+ Given /^I have built and installed the "([^\"]*)" gem$/ do |gem_name|
5
+ @terminal.build_and_install_gem(File.join(PROJECT_ROOT, "#{gem_name}.gemspec"))
6
+ end
7
+
8
+ When /^I generate a new Rails application$/ do
9
+ @terminal.cd(TEMP_DIR)
10
+
11
+ rails3 = version_string =~ /^3/
12
+
13
+ if rails3
14
+ rails_create_command = 'new'
15
+ else
16
+ rails_create_command = ''
17
+ end
18
+
19
+ load_rails = <<-RUBY
20
+ gem 'rails', '#{version_string}'; \
21
+ load Gem.bin_path('#{version_string >= "3.2.0" ? "railties" : "rails"}', 'rails', '#{version_string}')
22
+ RUBY
23
+
24
+ @terminal.run(%{ruby -rrubygems -rthread -e "#{load_rails.strip!}" #{rails_create_command} rails_root})
25
+ if rails_root_exists?
26
+ @terminal.echo("Generated a Rails #{version_string} application")
27
+ else
28
+ raise "Unable to generate a Rails application:\n#{@terminal.output}"
29
+ end
30
+ require_thread
31
+ if version_string >= "3.1.0"
32
+ When %{I configure my application to require the "therubyracer" gem with version "0.10.1"}
33
+ elsif version_string == "2.3.14"
34
+ monkeypatch_old_version
35
+ end
36
+ config_gem_dependencies unless rails3
37
+ end
38
+
39
+ When /^I run the honeybadger generator with "([^\"]*)"$/ do |generator_args|
40
+ if rails3?
41
+ When %{I run "./script/rails generate honeybadger #{generator_args}"}
42
+ else
43
+ When %{I run "./script/generate honeybadger #{generator_args}"}
44
+ end
45
+ end
46
+
47
+ When /^I print the console output$/ do
48
+ puts @terminal.output
49
+ end
50
+
51
+ Given /^I have installed the "([^\"]*)" gem$/ do |gem_name|
52
+ @terminal.install_gem(gem_name)
53
+ end
54
+
55
+
56
+ When /^I configure my application to require the "capistrano" gem if necessary$/ do
57
+ When %{I configure my application to require the "capistrano" gem} if version_string >= "3.0.0"
58
+ end
59
+
60
+ When /^I configure my application to require the "([^\"]*)" gem(?: with version "(.+)")?$/ do |gem_name, version|
61
+ if rails_manages_gems?
62
+ config_gem(gem_name, version)
63
+ elsif bundler_manages_gems?
64
+ bundle_gem(gem_name, version)
65
+ else
66
+ File.open(environment_path, 'a') do |file|
67
+ file.puts
68
+ file.puts("require 'honeybadger'")
69
+ file.puts("require 'honeybadger/rails'")
70
+ end
71
+
72
+ unless rails_finds_generators_in_gems?
73
+ FileUtils.cp_r(File.join(PROJECT_ROOT, 'generators'), File.join(rails_root, 'lib'))
74
+ end
75
+ end
76
+ end
77
+
78
+ When /^I run "([^\"]*)"$/ do |command|
79
+ @terminal.cd(rails_root)
80
+ @terminal.run(command)
81
+ end
82
+
83
+ Then /^I should receive a Honeybadger notification$/ do
84
+ Then %{I should see "** [Honeybadger] Response from Honeybadger:"}
85
+ And %{I should see "123456789"}
86
+ end
87
+
88
+ Then /^I should receive two Honeybadger notifications$/ do
89
+ @terminal.output.scan(/\[Honeybadger\] Response from Honeybadger:/).size.should == 2
90
+ end
91
+
92
+ When /^I configure the Honeybadger shim$/ do
93
+ if bundler_manages_gems?
94
+ bundle_gem("sham_rack")
95
+ end
96
+
97
+ shim_file = File.join(PROJECT_ROOT, 'features', 'support', 'honeybadger_shim.rb.template')
98
+ if rails_supports_initializers?
99
+ target = File.join(rails_root, 'config', 'initializers', 'honeybadger_shim.rb')
100
+ FileUtils.cp(shim_file, target)
101
+ else
102
+ File.open(environment_path, 'a') do |file|
103
+ file.puts
104
+ file.write IO.read(shim_file)
105
+ end
106
+ end
107
+ end
108
+
109
+ When /^I configure the notifier to use "([^\"]*)" as an API key$/ do |api_key|
110
+ steps %{
111
+ When I configure the notifier to use the following configuration lines:
112
+ """
113
+ config.api_key = #{api_key.inspect}
114
+ """
115
+ }
116
+ end
117
+
118
+ When /^I configure the notifier to use the following configuration lines:$/ do |configuration_lines|
119
+ if rails_manages_gems?
120
+ requires = ''
121
+ else
122
+ requires = "require 'honeybadger'"
123
+ end
124
+
125
+ initializer_code = <<-EOF
126
+ #{requires}
127
+ Honeybadger.configure do |config|
128
+ #{configuration_lines}
129
+ end
130
+ EOF
131
+
132
+ if rails_supports_initializers?
133
+ File.open(rails_initializer_file, 'w') { |file| file.write(initializer_code) }
134
+ else
135
+ File.open(environment_path, 'a') do |file|
136
+ file.puts
137
+ file.puts initializer_code
138
+ end
139
+ end
140
+
141
+ end
142
+
143
+ def rails_initializer_file
144
+ File.join(rails_root, 'config', 'initializers', 'honeybadger.rb')
145
+ end
146
+
147
+ def rails_non_initializer_honeybadger_config_file
148
+ File.join(rails_root, 'config', 'honeybadger.rb')
149
+ end
150
+
151
+ Then /^I should see "([^\"]*)"$/ do |expected_text|
152
+ unless @terminal.output.include?(expected_text)
153
+ raise("Got terminal output:\n#{@terminal.output}\n\nExpected output:\n#{expected_text}")
154
+ end
155
+ end
156
+
157
+ Then /^I should not see "([^\"]*)"$/ do |unexpected_text|
158
+ if @terminal.output.include?(unexpected_text)
159
+ raise("Got terminal output:\n#{@terminal.output}\n\nDid not expect the following output:\n#{unexpected_text}")
160
+ end
161
+ end
162
+
163
+ When /^I uninstall the "([^\"]*)" gem$/ do |gem_name|
164
+ @terminal.uninstall_gem(gem_name)
165
+ end
166
+
167
+ When /^I unpack the "([^\"]*)" gem$/ do |gem_name|
168
+ if bundler_manages_gems?
169
+ @terminal.cd(rails_root)
170
+ @terminal.run("bundle pack")
171
+ elsif rails_manages_gems?
172
+ @terminal.cd(rails_root)
173
+ @terminal.run("rake gems:unpack GEM=#{gem_name}")
174
+ else
175
+ vendor_dir = File.join(rails_root, 'vendor', 'gems')
176
+ FileUtils.mkdir_p(vendor_dir)
177
+ @terminal.cd(vendor_dir)
178
+ @terminal.run("gem unpack #{gem_name}")
179
+ gem_path =
180
+ Dir.glob(File.join(rails_root, 'vendor', 'gems', "#{gem_name}-*", 'lib')).first
181
+ File.open(environment_path, 'a') do |file|
182
+ file.puts
183
+ file.puts("$: << #{gem_path.inspect}")
184
+ end
185
+ end
186
+ end
187
+
188
+ When /^I install cached gems$/ do
189
+ if bundler_manages_gems?
190
+ Then %{I run "bundle install"}
191
+ end
192
+ end
193
+
194
+ When /^I install the "([^\"]*)" plugin$/ do |plugin_name|
195
+ FileUtils.mkdir_p("#{rails_root}/vendor/plugins/#{plugin_name}")
196
+ end
197
+
198
+ When /^I define a response for "([^\"]*)":$/ do |controller_and_action, definition|
199
+ controller_class_name, action = controller_and_action.split('#')
200
+ controller_name = controller_class_name.underscore
201
+ controller_file_name = File.join(rails_root, 'app', 'controllers', "#{controller_name}.rb")
202
+ File.open(controller_file_name, "w") do |file|
203
+ file.puts "class #{controller_class_name} < ApplicationController"
204
+ file.puts "def consider_all_requests_local; false; end"
205
+ file.puts "def local_request?; false; end"
206
+ file.puts "def #{action}"
207
+ file.puts definition
208
+ file.puts "end"
209
+ file.puts "end"
210
+ end
211
+ end
212
+
213
+ When /^I perform a request to "([^\"]*)"$/ do |uri|
214
+ perform_request(uri)
215
+ end
216
+
217
+ When /^I perform a request to "([^\"]*)" in the "([^\"]*)" environment$/ do |uri, environment|
218
+ perform_request(uri, environment)
219
+ end
220
+
221
+ Given /^the response page for a "([^\"]*)" error is$/ do |error, html|
222
+ File.open(File.join(rails_root, "public", "#{error}.html"), "w") do |file|
223
+ file.write(html)
224
+ end
225
+ end
226
+
227
+ Then /^I should receive the following Honeybadger notification:$/ do |table|
228
+ exceptions = @terminal.output.scan(%r{Recieved the following exception:\n([^\n]*)\n}m)
229
+ exceptions.should_not be_empty
230
+
231
+ xml = exceptions.last[0]
232
+ doc = Nokogiri::XML.parse(xml)
233
+
234
+ hash = table.transpose.hashes.first
235
+
236
+ doc.should have_content('//error/message', hash['error message'])
237
+ doc.should have_content('//error/class', hash['error class'])
238
+ doc.should have_content('//request/url', hash['url'])
239
+
240
+ doc.should have_content('//component', hash['component']) if hash['component']
241
+ doc.should have_content('//action', hash['action']) if hash['action']
242
+ doc.should have_content('//server-environment/project-root', hash['project-root']) if hash['project-root']
243
+
244
+ if hash['session']
245
+ session_key, session_value = hash['session'].split(': ')
246
+ doc.should have_content('//request/session/var/@key', session_key)
247
+ doc.should have_content('//request/session/var', session_value)
248
+ end
249
+
250
+ if hash['parameters']
251
+ param_key, param_value = hash['parameters'].split(': ')
252
+ doc.should have_content('//request/params/var/@key', param_key)
253
+ doc.should have_content('//request/params/var', param_value)
254
+ end
255
+ end
256
+
257
+ Then /^I should see the Rails version$/ do
258
+ Then %{I should see "[Rails: #{rails_version}]"}
259
+ end
260
+
261
+ Then /^I should see that "([^\"]*)" is not considered a framework gem$/ do |gem_name|
262
+ Then %{I should not see "[R] #{gem_name}"}
263
+ end
264
+
265
+ Then /^the command should have run successfully$/ do
266
+ @terminal.status.exitstatus.should == 0
267
+ end
268
+
269
+ When /^I route "([^\"]*)" to "([^\"]*)"$/ do |path, controller_action_pair|
270
+ route = if rails3?
271
+ %(match "#{path}", :to => "#{controller_action_pair}")
272
+ else
273
+ controller, action = controller_action_pair.split('#')
274
+ %(map.connect "#{path}", :controller => "#{controller}", :action => "#{action}")
275
+ end
276
+ routes_file = File.join(rails_root, "config", "routes.rb")
277
+ File.open(routes_file, "r+") do |file|
278
+ content = file.read
279
+ content.gsub!(/^end$/, " #{route}\nend")
280
+ file.rewind
281
+ file.write(content)
282
+ end
283
+ end
284
+
285
+ Then /^"([^\"]*)" should not contain "([^\"]*)"$/ do |file_path, text|
286
+ actual_text = IO.read(File.join(rails_root, file_path))
287
+ if actual_text.include?(text)
288
+ raise "Didn't expect text:\n#{actual_text}\nTo include:\n#{text}"
289
+ end
290
+ end
291
+
292
+ Then /^my Honeybadger configuration should contain the following line:$/ do |line|
293
+ configuration_file = if rails_supports_initializers?
294
+ rails_initializer_file
295
+ else
296
+ rails_non_initializer_honeybadger_config_file
297
+ # environment_path
298
+ end
299
+
300
+ configuration = File.read(configuration_file)
301
+ if ! configuration.include?(line.strip)
302
+ raise "Expected text:\n#{configuration}\nTo include:\n#{line}\nBut it didn't."
303
+ end
304
+ end
305
+
306
+ When /^I set the environment variable "([^\"]*)" to "([^\"]*)"$/ do |environment_variable, value|
307
+ @terminal.environment_variables[environment_variable] = value
308
+ end
309
+
310
+ When /^I configure the Heroku rake shim$/ do
311
+ @terminal.invoke_heroku_rake_tasks_locally = true
312
+ end
313
+
314
+ When /^I configure the Heroku gem shim with "([^\"]*)"( and multiple app support)?$/ do |api_key, multi_app|
315
+ heroku_script_bin = File.join(TEMP_DIR, "bin")
316
+ FileUtils.mkdir_p(heroku_script_bin)
317
+ heroku_script = File.join(heroku_script_bin, "heroku")
318
+ heroku_env_vars = <<-VARS
319
+ HONEYBADGER_API_KEY => myapikey
320
+ APP_NAME => cold-moon-2929
321
+ BUNDLE_WITHOUT => development:test
322
+ COMMIT_HASH => lj32j42ss9332jfa2
323
+ DATABASE_URL => postgres://fchovwjcyb:QLPVWmBBbf4hCG_YMrtV@ec3-107-28-193-23.compute-1.amazonaws.com/fhcvojwwcyb
324
+ LANG => en_US.UTF-8
325
+ LAST_GIT_BY => kensa
326
+ RACK_ENV => production
327
+ SHARED_DATABASE_URL => postgres://fchovwjcyb:QLPVwMbbbF8Hcg_yMrtV@ec2-94-29-181-224.compute-1.amazonaws.com/fhcvojcwwyb
328
+ STACK => bamboo-mri-1.9.2
329
+ URL => cold-moon-2929.heroku.com
330
+ VARS
331
+ single_app_script = <<-SINGLE
332
+ #!/bin/bash
333
+ if [ $1 == 'config' ]
334
+ then
335
+ echo "#{heroku_env_vars}"
336
+ fi
337
+ SINGLE
338
+
339
+ multi_app_script = <<-MULTI
340
+ #!/bin/bash
341
+ if [[ $1 == 'config' && $2 == '--app' ]]
342
+ then
343
+ echo "#{heroku_env_vars}"
344
+ fi
345
+ MULTI
346
+
347
+ File.open(heroku_script, "w") do |f|
348
+ if multi_app
349
+ f.puts multi_app_script
350
+ else
351
+ f.puts single_app_script
352
+ end
353
+ end
354
+ FileUtils.chmod(0755, heroku_script)
355
+ @terminal.prepend_path(heroku_script_bin)
356
+ end
357
+
358
+ When /^I configure the application to filter parameter "([^\"]*)"$/ do |parameter|
359
+ if rails3?
360
+ application_filename = File.join(rails_root, 'config', 'application.rb')
361
+ application_lines = File.open(application_filename).readlines
362
+
363
+ application_definition_line = application_lines.detect { |line| line =~ /Application/ }
364
+ application_definition_line_index = application_lines.index(application_definition_line)
365
+
366
+ application_lines.insert(application_definition_line_index + 1,
367
+ " config.filter_parameters += [#{parameter.inspect}]")
368
+
369
+ File.open(application_filename, "w") do |file|
370
+ file.puts application_lines.join("\n")
371
+ end
372
+ else
373
+ controller_filename = application_controller_filename
374
+ controller_lines = File.open(controller_filename).readlines
375
+
376
+ controller_definition_line = controller_lines.detect { |line| line =~ /ApplicationController/ }
377
+ controller_definition_line_index = controller_lines.index(controller_definition_line)
378
+
379
+ controller_lines.insert(controller_definition_line_index + 1,
380
+ " filter_parameter_logging #{parameter.inspect}")
381
+
382
+ File.open(controller_filename, "w") do |file|
383
+ file.puts controller_lines.join("\n")
384
+ end
385
+ end
386
+ end
387
+
388
+ When /^I configure usage of Honeybadger$/ do
389
+ When %{I configure my application to require the "honeybadger" gem}
390
+ When %{I run the honeybadger generator with "-k myapikey"}
391
+
392
+ # flush the results of setting up Honeybadger (generates notification)
393
+ @terminal.flush!
394
+ end
@@ -0,0 +1,17 @@
1
+ When /I run rake with (.+)/ do |command|
2
+ @rake_command = "rake #{command.gsub(' ','_')}"
3
+ @rake_result = `cd features/support/rake && GEM_HOME=#{BUILT_GEM_ROOT} #{@rake_command} 2>&1`
4
+ end
5
+
6
+ Then /Honeybadger should (|not) ?catch the exception/ do |condition|
7
+ if condition=='not'
8
+ @rake_result.should_not =~ /^honeybadger/
9
+ else
10
+ @rake_result.should =~ /^honeybadger/
11
+ end
12
+ end
13
+
14
+ Then /Honeybadger should send the rake command line as the component name/ do
15
+ component = @rake_result.match(/^honeybadger (.*)$/)[1]
16
+ component.should == @rake_command
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'active_support'
2
+ require 'rspec'
3
+
4
+ PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
5
+ TEMP_DIR = File.join(PROJECT_ROOT, 'tmp').freeze
6
+ LOCAL_RAILS_ROOT = File.join(TEMP_DIR, 'rails_root').freeze
7
+ BUILT_GEM_ROOT = File.join(TEMP_DIR, 'built_gems').freeze
8
+ LOCAL_GEM_ROOT = File.join(TEMP_DIR, 'local_gems').freeze
9
+ RACK_FILE = File.join(TEMP_DIR, 'rack_app.rb').freeze
10
+
11
+ Before do
12
+ FileUtils.mkdir_p(TEMP_DIR)
13
+ FileUtils.rm_rf(BUILT_GEM_ROOT)
14
+ FileUtils.rm_rf(LOCAL_RAILS_ROOT)
15
+ FileUtils.rm_f(RACK_FILE)
16
+ FileUtils.mkdir_p(BUILT_GEM_ROOT)
17
+ end