cloudtrapper 0.0.2.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/CHANGELOG +823 -0
  2. data/Gemfile +12 -0
  3. data/Guardfile +6 -0
  4. data/INSTALL +20 -0
  5. data/MIT-LICENSE +22 -0
  6. data/README.md +465 -0
  7. data/README_FOR_HEROKU_ADDON.md +94 -0
  8. data/Rakefile +223 -0
  9. data/SUPPORTED_RAILS_VERSIONS +23 -0
  10. data/TESTING.md +33 -0
  11. data/cloudtrapper.gemspec +35 -0
  12. data/features/metal.feature +18 -0
  13. data/features/rack.feature +56 -0
  14. data/features/rails.feature +211 -0
  15. data/features/rails_with_js_notifier.feature +97 -0
  16. data/features/rake.feature +27 -0
  17. data/features/sinatra.feature +29 -0
  18. data/features/step_definitions/file_steps.rb +10 -0
  19. data/features/step_definitions/metal_steps.rb +23 -0
  20. data/features/step_definitions/rack_steps.rb +23 -0
  21. data/features/step_definitions/rails_application_steps.rb +433 -0
  22. data/features/step_definitions/rake_steps.rb +17 -0
  23. data/features/support/airbrake_shim.rb.template +11 -0
  24. data/features/support/env.rb +18 -0
  25. data/features/support/matchers.rb +35 -0
  26. data/features/support/rails.rb +201 -0
  27. data/features/support/rake/Rakefile +68 -0
  28. data/features/support/terminal.rb +107 -0
  29. data/features/user_informer.feature +63 -0
  30. data/generators/cloudtrapper/airbrake_generator.rb +94 -0
  31. data/generators/cloudtrapper/lib/insert_commands.rb +34 -0
  32. data/generators/cloudtrapper/lib/rake_commands.rb +24 -0
  33. data/generators/cloudtrapper/templates/capistrano_hook.rb +6 -0
  34. data/generators/cloudtrapper/templates/cloudtrapper_tasks.rake +25 -0
  35. data/generators/cloudtrapper/templates/initializer.rb +6 -0
  36. data/install.rb +1 -0
  37. data/lib/cloudtrapper/backtrace.rb +100 -0
  38. data/lib/cloudtrapper/capistrano.rb +44 -0
  39. data/lib/cloudtrapper/configuration.rb +281 -0
  40. data/lib/cloudtrapper/notice.rb +348 -0
  41. data/lib/cloudtrapper/rack.rb +55 -0
  42. data/lib/cloudtrapper/rails/action_controller_catcher.rb +30 -0
  43. data/lib/cloudtrapper/rails/controller_methods.rb +74 -0
  44. data/lib/cloudtrapper/rails/error_lookup.rb +33 -0
  45. data/lib/cloudtrapper/rails/javascript_notifier.rb +48 -0
  46. data/lib/cloudtrapper/rails/middleware/exceptions_catcher.rb +29 -0
  47. data/lib/cloudtrapper/rails.rb +40 -0
  48. data/lib/cloudtrapper/rails3_tasks.rb +85 -0
  49. data/lib/cloudtrapper/railtie.rb +48 -0
  50. data/lib/cloudtrapper/rake_handler.rb +66 -0
  51. data/lib/cloudtrapper/sender.rb +116 -0
  52. data/lib/cloudtrapper/shared_tasks.rb +36 -0
  53. data/lib/cloudtrapper/tasks.rb +83 -0
  54. data/lib/cloudtrapper/user_informer.rb +27 -0
  55. data/lib/cloudtrapper/version.rb +3 -0
  56. data/lib/cloudtrapper.rb +155 -0
  57. data/lib/cloudtrapper_tasks.rb +65 -0
  58. data/lib/rails/generators/cloudtrapper/cloudtrapper_generator.rb +100 -0
  59. data/lib/templates/javascript_notifier.erb +15 -0
  60. data/lib/templates/rescue.erb +91 -0
  61. data/rails/init.rb +1 -0
  62. data/resources/README.md +34 -0
  63. data/resources/ca-bundle.crt +3376 -0
  64. data/script/integration_test.rb +38 -0
  65. data/test/backtrace_test.rb +162 -0
  66. data/test/capistrano_test.rb +34 -0
  67. data/test/catcher_test.rb +333 -0
  68. data/test/cloudtrapper_2_2.xsd +78 -0
  69. data/test/cloudtrapper_tasks_test.rb +170 -0
  70. data/test/configuration_test.rb +221 -0
  71. data/test/helper.rb +263 -0
  72. data/test/javascript_notifier_test.rb +52 -0
  73. data/test/logger_test.rb +73 -0
  74. data/test/notice_test.rb +468 -0
  75. data/test/notifier_test.rb +246 -0
  76. data/test/rack_test.rb +58 -0
  77. data/test/rails_initializer_test.rb +36 -0
  78. data/test/recursion_test.rb +10 -0
  79. data/test/sender_test.rb +261 -0
  80. data/test/user_informer_test.rb +29 -0
  81. metadata +301 -0
@@ -0,0 +1,100 @@
1
+ require 'rails/generators'
2
+
3
+ class CloudtrapperGenerator < Rails::Generators::Base
4
+
5
+ class_option :api_key, :aliases => "-k", :type => :string, :desc => "Your Cloudtrapper API key"
6
+ class_option :heroku, :type => :boolean, :desc => "Use the Heroku addon to provide your Cloudtrapper API key"
7
+ class_option :app, :aliases => "-a", :type => :string, :desc => "Your Heroku app name (only required if deploying to >1 Heroku app)"
8
+
9
+ def self.source_root
10
+ @_cloudtrapper_source_root ||= File.expand_path("../../../../../generators/cloudtrapper/templates", __FILE__)
11
+ end
12
+
13
+ def install
14
+ ensure_api_key_was_configured
15
+ ensure_plugin_is_not_present
16
+ append_capistrano_hook
17
+ generate_initializer unless api_key_configured?
18
+ determine_api_key if heroku?
19
+ test_cloudtrapper
20
+ end
21
+
22
+ private
23
+
24
+ def ensure_api_key_was_configured
25
+ if !options[:api_key] && !options[:heroku] && !api_key_configured?
26
+ puts "Must pass --api-key or --heroku or create config/initializers/cloudtrapper.rb"
27
+ exit
28
+ end
29
+ end
30
+
31
+ def ensure_plugin_is_not_present
32
+ if plugin_is_present?
33
+ puts "You must first remove the cloudtrapper plugin. Please run: script/plugin remove cloudtrapper"
34
+ exit
35
+ end
36
+ end
37
+
38
+ def append_capistrano_hook
39
+ if File.exists?('config/deploy.rb') && File.exists?('Capfile')
40
+ append_file('config/deploy.rb', <<-HOOK)
41
+
42
+ require './config/boot'
43
+ require 'cloudtrapper/capistrano'
44
+ HOOK
45
+ end
46
+ end
47
+
48
+ def api_key_expression
49
+ s = if options[:api_key]
50
+ "'#{options[:api_key]}'"
51
+ elsif options[:heroku]
52
+ "ENV['HOPTOAD_API_KEY']"
53
+ end
54
+ end
55
+
56
+ def generate_initializer
57
+ template 'initializer.rb', 'config/initializers/cloudtrapper.rb'
58
+ end
59
+
60
+ def determine_api_key
61
+ puts "Attempting to determine your API Key from Heroku..."
62
+ ENV['HOPTOAD_API_KEY'] = heroku_api_key
63
+ if ENV['HOPTOAD_API_KEY'].blank?
64
+ puts "... Failed."
65
+ puts "WARNING: We were unable to detect the Cloudtrapper API Key from your Heroku environment."
66
+ puts "Your Heroku application environment may not be configured correctly."
67
+ exit 1
68
+ else
69
+ puts "... Done."
70
+ puts "Heroku's Cloudtrapper API Key is '#{ENV['HOPTOAD_API_KEY']}'"
71
+ end
72
+ end
73
+
74
+ def heroku_var(var,app_name = nil)
75
+ app = app_name ? "--app #{app_name}" : ''
76
+ `heroku config #{app} | grep -E "#{var.upcase}" | awk '{ print $3; }'`.strip
77
+ end
78
+
79
+ def heroku_api_key
80
+ heroku_var("(hoptoad|cloudtrapper)_api_key",options[:app]).split.find {|x| x unless x.blank?}
81
+ end
82
+
83
+ def heroku?
84
+ options[:heroku] ||
85
+ system("grep HOPTOAD_API_KEY config/initializers/cloudtrapper.rb") ||
86
+ system("grep HOPTOAD_API_KEY config/environment.rb")
87
+ end
88
+
89
+ def api_key_configured?
90
+ File.exists?('config/initializers/cloudtrapper.rb')
91
+ end
92
+
93
+ def test_cloudtrapper
94
+ puts run("rake cloudtrapper:test --trace")
95
+ end
96
+
97
+ def plugin_is_present?
98
+ File.exists?('vendor/plugins/cloudtrapper')
99
+ end
100
+ end
@@ -0,0 +1,15 @@
1
+ <%= javascript_tag %Q{
2
+ (function(){
3
+ var notifierJsScheme = (("https:" == document.location.protocol) ? "https://" : "http://");
4
+ document.write(unescape("%3Cscript src='" + notifierJsScheme + "#{host}/javascripts/notifier.js' type='text/javascript'%3E%3C/script%3E"));
5
+ })();
6
+ }%>
7
+
8
+ <%= javascript_tag %Q{
9
+ window.Cloudtrapper = (typeof(Cloudtrapper) == 'undefined' && typeof(Hoptoad) != 'undefined') ? Hoptoad : Cloudtrapper
10
+ Cloudtrapper.setKey('#{api_key}');
11
+ Cloudtrapper.setHost('#{host}');
12
+ Cloudtrapper.setEnvironment('#{environment}');
13
+ Cloudtrapper.setErrorDefaults({ url: "#{escape_javascript url}", component: "#{controller_name}", action: "#{action_name}" });
14
+ }
15
+ %>
@@ -0,0 +1,91 @@
1
+ <script type="text/javascript">
2
+ var Cloudtrapper = {
3
+ host : <%= host.to_json %>,
4
+ api_key : <%= api_key.to_json %>,
5
+ notice : <%= notice.to_json %>,
6
+ message : 'This error exists in production!',
7
+
8
+ initialize: function() {
9
+ if (this.initialized) {
10
+ return;
11
+ } else {
12
+ this.initialized = true;
13
+ }
14
+
15
+ var data = [];
16
+
17
+ for (var key in this.notice) {
18
+ data[data.length] = 'notice[' + key + ']=' + this.notice[key];
19
+ }
20
+
21
+ data[data.length] = 'notice[api_key]=' + this.api_key;
22
+ data[data.length] = 'callback=Cloudtrapper.onSuccess';
23
+ data[data.length] = '_=' + (new Date()).getTime();
24
+
25
+ var head = document.getElementsByTagName('head')[0];
26
+ var done = false;
27
+
28
+ var
29
+ script = document.createElement('script');
30
+ script.src = 'http://' + this.host + '/notices_api/v1/notices/exist?' +
31
+ data.join('&');
32
+ script.type = 'text/javascript';
33
+ script.onload = script.onreadystatechange = function(){
34
+ if (!done && (!this.readyState ||
35
+ this.readyState == 'loaded' || this.readyState == 'complete')) {
36
+
37
+ done = true;
38
+
39
+ // Handle memory leak in IE. (via jQuery)
40
+ script.onload = script.onreadystatechange = null;
41
+ head.removeChild(script);
42
+ }
43
+ };
44
+
45
+ head.appendChild(script);
46
+ },
47
+
48
+ onSuccess: function(error) {
49
+ var body = document.getElementsByTagName('body')[0];
50
+ var text = document.createTextNode(this.message);
51
+ var element = document.createElement('a');
52
+
53
+ element.id = 'cloudtrapper';
54
+ element.href = 'http://' + error.subdomain + '.' + this.host +
55
+ '/projects/' + error.project_id + '/errors/' + error.id;
56
+ element.appendChild(text);
57
+
58
+ body.insertBefore(element, body.firstChild);
59
+
60
+ var h1 = document.getElementsByTagName('h1')[0];
61
+ var pre = document.getElementsByTagName('pre')[0];
62
+ var wrapper = document.createElement('div');
63
+
64
+ wrapper.id = 'wrapper';
65
+ wrapper.appendChild(h1);
66
+ wrapper.appendChild(pre);
67
+
68
+ body.insertBefore(wrapper, body.children[1]);
69
+ }
70
+ };
71
+
72
+ window.onload = function() {
73
+ Cloudtrapper.initialize.apply(Cloudtrapper);
74
+ };
75
+ </script>
76
+
77
+ <style type="text/css">
78
+ #cloudtrapper {
79
+ background: #FFF url(http://cloudtrapper.io/images/fell-off-the-toad.gif) no-repeat top right;
80
+ color: #F00;
81
+ padding: 45px 101px 45px 12px;
82
+ font-size: 14px;
83
+ font-weight: bold;
84
+ display: block;
85
+ float: right;
86
+ }
87
+
88
+ #wrapper {
89
+ padding-right: 360px;
90
+ }
91
+ </style>
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'cloudtrapper/rails'
@@ -0,0 +1,34 @@
1
+ Cloudtrapper Resources
2
+ ==================
3
+
4
+ Cloudtrapper has an SSL mode available to paying plans. SSL Certificate Authority (CA) certificates are not kept current by default on many environments. When CA certs are stale, Cloudtrapper cannot verify Cloudtrapper's production SSL cert and error reports fail. To avoid this, we now package local CA certs. The production of these certs is detailed here.
5
+
6
+ Building ca-bundle.crt
7
+ ----------------------
8
+
9
+ From https://gist.github.com/996292.
10
+
11
+ If you want to use curl or net-http/open-uri to access https resources, you will often (always?) get an error, because they don't have the large number of root certificates installed that web browsers have.
12
+
13
+ You can manually install the root certs, but first you have to get them from somewhere. [This article](http://notetoself.vrensk.com/2008/09/verified-https-in-ruby/) gives a nice description of how to do that. The [source of the cert files](http://curl.haxx.se/ca/cacert.pem) it points to is hosted by the curl project, who kindly provide it in the .pem format.
14
+
15
+ **problem:** Sadly, ironically, and comically, it's not possible to access that file via https! Luckily, the awesome curl project does provide us with the script that they use to produce the file, so we can do it securely ourselves. Here's how.
16
+
17
+ 1. `git clone https://github.com/bagder/curl.git`
18
+ 2. `cd curl/lib`
19
+ 3. edit `mk-ca-bundle.pl` and change:
20
+
21
+ ```perl
22
+ my $url = 'http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1';
23
+ ```
24
+
25
+ to
26
+
27
+ ```perl
28
+ my $url = 'https://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1';
29
+ ```
30
+
31
+ (change `http` to `https`)
32
+ 4. `./mk-ca-bundle.pl`
33
+
34
+ Ta da!