exception_hub 0.0.1

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.
Files changed (82) hide show
  1. data/.gitignore +19 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/Gemfile +16 -0
  5. data/Guardfile +24 -0
  6. data/LICENSE +22 -0
  7. data/README.md +43 -0
  8. data/Rakefile +10 -0
  9. data/exception_hub.gemspec +23 -0
  10. data/lib/exception_hub/client/authorization.rb +26 -0
  11. data/lib/exception_hub/client.rb +26 -0
  12. data/lib/exception_hub/configuration.rb +81 -0
  13. data/lib/exception_hub/interceptor.rb +34 -0
  14. data/lib/exception_hub/issue.rb +25 -0
  15. data/lib/exception_hub/notifier.rb +64 -0
  16. data/lib/exception_hub/rack.rb +27 -0
  17. data/lib/exception_hub/rails/controller_interceptor.rb +21 -0
  18. data/lib/exception_hub/rails/middleware/exceptions_interceptor.rb +22 -0
  19. data/lib/exception_hub/railtie.rb +24 -0
  20. data/lib/exception_hub/rake_task.rb +27 -0
  21. data/lib/exception_hub/version.rb +3 -0
  22. data/lib/exception_hub.rb +20 -0
  23. data/lib/tasks/exception_hub.rake +3 -0
  24. data/spec/integration/exception_hub_integration/.gitignore +17 -0
  25. data/spec/integration/exception_hub_integration/Gemfile +40 -0
  26. data/spec/integration/exception_hub_integration/README.rdoc +261 -0
  27. data/spec/integration/exception_hub_integration/Rakefile +7 -0
  28. data/spec/integration/exception_hub_integration/app/assets/images/rails.png +0 -0
  29. data/spec/integration/exception_hub_integration/app/assets/javascripts/application.js +15 -0
  30. data/spec/integration/exception_hub_integration/app/assets/stylesheets/application.css +13 -0
  31. data/spec/integration/exception_hub_integration/app/controllers/application_controller.rb +3 -0
  32. data/spec/integration/exception_hub_integration/app/controllers/errors_controller.rb +5 -0
  33. data/spec/integration/exception_hub_integration/app/helpers/application_helper.rb +2 -0
  34. data/spec/integration/exception_hub_integration/app/mailers/.gitkeep +0 -0
  35. data/spec/integration/exception_hub_integration/app/models/.gitkeep +0 -0
  36. data/spec/integration/exception_hub_integration/app/views/layouts/application.html.erb +14 -0
  37. data/spec/integration/exception_hub_integration/config/application.rb +62 -0
  38. data/spec/integration/exception_hub_integration/config/boot.rb +6 -0
  39. data/spec/integration/exception_hub_integration/config/database.yml +25 -0
  40. data/spec/integration/exception_hub_integration/config/environment.rb +5 -0
  41. data/spec/integration/exception_hub_integration/config/environments/development.rb +37 -0
  42. data/spec/integration/exception_hub_integration/config/environments/production.rb +67 -0
  43. data/spec/integration/exception_hub_integration/config/environments/test.rb +37 -0
  44. data/spec/integration/exception_hub_integration/config/initializers/backtrace_silencers.rb +7 -0
  45. data/spec/integration/exception_hub_integration/config/initializers/inflections.rb +15 -0
  46. data/spec/integration/exception_hub_integration/config/initializers/mime_types.rb +5 -0
  47. data/spec/integration/exception_hub_integration/config/initializers/secret_token.rb +7 -0
  48. data/spec/integration/exception_hub_integration/config/initializers/session_store.rb +8 -0
  49. data/spec/integration/exception_hub_integration/config/initializers/wrap_parameters.rb +14 -0
  50. data/spec/integration/exception_hub_integration/config/locales/en.yml +5 -0
  51. data/spec/integration/exception_hub_integration/config/routes.rb +59 -0
  52. data/spec/integration/exception_hub_integration/config.ru +4 -0
  53. data/spec/integration/exception_hub_integration/db/seeds.rb +7 -0
  54. data/spec/integration/exception_hub_integration/lib/assets/.gitkeep +0 -0
  55. data/spec/integration/exception_hub_integration/lib/tasks/.gitkeep +0 -0
  56. data/spec/integration/exception_hub_integration/log/.gitkeep +0 -0
  57. data/spec/integration/exception_hub_integration/public/404.html +26 -0
  58. data/spec/integration/exception_hub_integration/public/422.html +26 -0
  59. data/spec/integration/exception_hub_integration/public/500.html +25 -0
  60. data/spec/integration/exception_hub_integration/public/favicon.ico +0 -0
  61. data/spec/integration/exception_hub_integration/public/index.html +241 -0
  62. data/spec/integration/exception_hub_integration/public/robots.txt +5 -0
  63. data/spec/integration/exception_hub_integration/script/rails +6 -0
  64. data/spec/integration/exception_hub_integration/test/fixtures/.gitkeep +0 -0
  65. data/spec/integration/exception_hub_integration/test/functional/.gitkeep +0 -0
  66. data/spec/integration/exception_hub_integration/test/integration/.gitkeep +0 -0
  67. data/spec/integration/exception_hub_integration/test/performance/browsing_test.rb +12 -0
  68. data/spec/integration/exception_hub_integration/test/test_helper.rb +13 -0
  69. data/spec/integration/exception_hub_integration/test/unit/.gitkeep +0 -0
  70. data/spec/integration/exception_hub_integration/vendor/assets/javascripts/.gitkeep +0 -0
  71. data/spec/integration/exception_hub_integration/vendor/assets/stylesheets/.gitkeep +0 -0
  72. data/spec/integration/exception_hub_integration/vendor/plugins/.gitkeep +0 -0
  73. data/spec/integration/rake_task_spec.rb +9 -0
  74. data/spec/lib/exception_hub/client/authorization_spec.rb +22 -0
  75. data/spec/lib/exception_hub/client_spec.rb +28 -0
  76. data/spec/lib/exception_hub/configuration_spec.rb +35 -0
  77. data/spec/lib/interceptor_spec.rb +112 -0
  78. data/spec/lib/issue_spec.rb +26 -0
  79. data/spec/lib/notifier_spec.rb +31 -0
  80. data/spec/lib/rack_spec.rb +22 -0
  81. data/spec/spec_helper.rb +16 -0
  82. metadata +249 -0
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
19
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use @exception_hub --create
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in exception_hub.gemspec
4
+ gemspec
5
+
6
+ gem 'guard'
7
+ gem 'guard-rspec'
8
+ group :osx do
9
+ gem 'growl'
10
+ end
11
+ gem 'yard'
12
+ gem 'octokit'
13
+ gem 'rails', '~> 3.2.6'
14
+ group :test do
15
+ gem 'simplecov', :require => false
16
+ end
data/Guardfile ADDED
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara request specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jesse Dearing
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # ExceptionHub
2
+
3
+ ExceptionHub will take your applications exceptions as they are thrown
4
+ and will log them in Github issues.
5
+
6
+ Currently this gem is in alpha and not ready for production use.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'exception_hub'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install exception_hub
21
+
22
+ ## Usage
23
+
24
+ ### Rails
25
+
26
+ In Rails 3, you can run the rake task to enter in the information needed
27
+ for the initializer and it will fetch the Github token for you.
28
+
29
+ `rake exception_hub:generate_initializer`
30
+
31
+ The initializer needs the following fields:
32
+ * `github_api_token`
33
+ * `github_user_name`
34
+ * `repo_name`
35
+ * `repo_owner`
36
+
37
+ ## Contributing
38
+
39
+ 1. Fork it
40
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
41
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
42
+ 4. Push to the branch (`git push origin my-new-feature`)
43
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+ require 'yard'
5
+
6
+ desc "Run specs"
7
+ RSpec::Core::RakeTask.new
8
+ YARD::Rake::YardocTask.new
9
+
10
+ task :default => :spec
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/exception_hub/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Jesse Dearing"]
6
+ gem.email = ["jesse.dearing@gmail.com"]
7
+ gem.description = %q{exception_hub logs exceptions in your Rails application to Github issues}
8
+ gem.summary = %q{Logs exceptions in your application to Github issues}
9
+ gem.homepage = "https://github.com/jessedearing/exception_hub"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "exception_hub"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = ExceptionHub::VERSION
17
+
18
+ gem.add_dependency('octokit', '~> 1.8.1')
19
+ gem.add_dependency('faraday')
20
+ gem.add_dependency('faraday_middleware')
21
+
22
+ gem.add_development_dependency('rspec', '~> 2.10.0')
23
+ end
@@ -0,0 +1,26 @@
1
+ require 'erb'
2
+
3
+ module ExceptionHub
4
+ module Client
5
+ module Authorization
6
+ INITIALIZER_TEMPLATE = File.read(__FILE__).split("__END__\n").last
7
+
8
+ def get_api_token(user, password, note = 'ExceptionHub', url = 'http://github.com/jessedearing/exception_hub')
9
+ o = Octokit::Client.new(:login => user, :password => password)
10
+ o.create_authorization(:scopes => [:repo], :note => note, :note_url => url)
11
+ end
12
+
13
+ def generate_initializer(user, api_token, auth_id)
14
+ t = ERB.new(INITIALIZER_TEMPLATE)
15
+ t.result binding
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ __END__
22
+ ExceptionHub.configure do |config|
23
+ # Github Authorization #<%= auth_id %>
24
+ config.github_user_name = '<%= user %>'
25
+ config.github_api_token = '<%= api_token %>'
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'exception_hub/client/authorization'
2
+
3
+ module ExceptionHub
4
+ module Client
5
+ include Authorization
6
+
7
+ # @returns [Octokit::Client] Returns an Octokit client singleton
8
+ def current_octokit
9
+ @current_octokit ||= get_octokit_client
10
+ end
11
+
12
+ # @returns [Octokit::Client] Creates new instance of the Octokit client singleton
13
+ def reload_octokit!
14
+ @current_octokit = get_octokit_client
15
+ end
16
+
17
+ protected
18
+ def get_octokit_client
19
+ if ExceptionHub.github_user_name && ExceptionHub.github_api_token
20
+ Octokit::Client.new(:login => ExceptionHub.github_user_name, :oauth_token => ExceptionHub.github_api_token)
21
+ else
22
+ Octokit::Client.new
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,81 @@
1
+ module ExceptionHub
2
+ module Configuration
3
+ IGNORED_EXCEPTIONS_DEFAULT = ['ActiveRecord::RecordNotFound',
4
+ 'ActionController::RoutingError',
5
+ 'ActionController::InvalidAuthenticityToken',
6
+ 'CGI::Session::CookieStore::TamperedWithCookie',
7
+ 'ActionController::UnknownAction',
8
+ 'AbstractController::ActionNotFound',
9
+ 'Mongoid::Errors::DocumentNotFound']
10
+ # @!attribute [rw]
11
+ # @return [String] Name of the Github repository
12
+ attr_accessor :repo_name
13
+
14
+ # @!attribute [rw]
15
+ # @return [String] Github username for the user account that will make the API calls
16
+ attr_accessor :github_user_name
17
+
18
+ # @!attribute [rw]
19
+ # @return [String] Name of the user or organization that hosts the repository
20
+ attr_accessor :repo_owner
21
+
22
+ # @!attribute [rw]
23
+ # @return [Boolean] If true, sends all exceptions to Github including duplicates.
24
+ attr_accessor :send_all_exceptions
25
+
26
+ # @!attribute [rw]
27
+ # @return [String] Github token to make API calls with
28
+ attr_accessor :github_api_token
29
+
30
+ # @!attribute [r]
31
+ # @return [Array<Proc>] Callbacks after the exception is created
32
+ attr_reader :after_create_exception_callbacks
33
+
34
+ # @!attribute [r]
35
+ # @return [Array<Proc>] Callbacks before the exception is created
36
+ attr_reader :before_create_exception_callbacks
37
+
38
+ # @!attribute [rw]
39
+ # @return [Array<String>] Exception types as strings of the message to ignore
40
+ attr_accessor :ignored_exceptions
41
+
42
+ # @!attribute [rw]
43
+ # @return [Array<Symbol>] Environments to send exceptions from
44
+ attr_accessor :reporting_environments
45
+
46
+ # @!attribute [rw]
47
+ # @return [Logger] Logger to send output messages to
48
+ attr_accessor :logger
49
+
50
+ # Provides configuration block for ExceptionHub
51
+ #
52
+ # @example
53
+ # ExceptionHub.configure do |config|
54
+ # config.repo_name = 'exception_hub'
55
+ # # ...
56
+ # end
57
+ # @yield [config] Current instance of ExceptionHub::Configuration
58
+ def configure
59
+ define_defaults
60
+ yield(self) if block_given?
61
+ true
62
+ end
63
+ alias_method :config, :configure
64
+
65
+ def define_defaults
66
+ @after_create_exception_callbacks ||= []
67
+ @before_create_exception_callbacks ||= []
68
+ @ignored_exceptions ||= IGNORED_EXCEPTIONS_DEFAULT.dup
69
+ @reporting_environments ||= [:production]
70
+ @logger ||= defined?(::Rails) && ::Rails.logger || Logger.new(STDOUT)
71
+ end
72
+
73
+ def after_create_exception(&block)
74
+ @after_create_exception_callbacks << block if block
75
+ end
76
+
77
+ def before_create_exception(&block)
78
+ @before_create_exception_callbacks << block if block
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,34 @@
1
+ module ExceptionHub
2
+ class Interceptor
3
+ def initialize(exception, rack_env)
4
+ @exception = exception
5
+ @env = rack_env
6
+ end
7
+
8
+ def intercept!
9
+ if should_create_issue?
10
+ n = ExceptionHub::Notifier.new(@exception, @env)
11
+ ExceptionHub.before_create_exception_callbacks.each do |callback|
12
+ callback.call(n, @env)
13
+ end
14
+
15
+ n.notify!
16
+
17
+ ExceptionHub.after_create_exception_callbacks.each do |callback|
18
+ callback.call(n, @env)
19
+ end
20
+ end
21
+ self
22
+ end
23
+
24
+ def should_create_issue?
25
+ return false if ExceptionHub.ignored_exceptions.include? @exception.class.name
26
+
27
+ return true if defined?(::Rails) && ExceptionHub.reporting_environments.include?(::Rails.env.to_sym)
28
+ return true if defined?(Sinatra::Base) && ExceptionHub.reporting_environments.include?(Sinatra::Base.environment)
29
+ return true if ENV['RACK_ENV'] && ExceptionHub.reporting_environments.include?(ENV['RACK_ENV'].to_sym)
30
+ #TODO Compare exception to YAML cache here
31
+ false
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,25 @@
1
+ module ExceptionHub
2
+ # Issue marshals exception information
3
+ class Issue
4
+ # !@attribute [rw]
5
+ # @return [Integer] The issue ID in Github
6
+ attr_accessor :github_issue_id
7
+
8
+ # !@attribute [rw]
9
+ # @return [String] Title of the Github issue
10
+ attr_accessor :title
11
+
12
+ # !@attribute [rw]
13
+ # @return [String] Description to be displayed in the body of the Github issue
14
+ attr_accessor :description
15
+
16
+ # Creates the current Issue in Github
17
+ def send_to_github
18
+ ExceptionHub.current_octokit.create_issue("#{ExceptionHub.repo_owner}/#{ExceptionHub.repo_name}", self.title, self.description, :open_timeout => 5)
19
+ end
20
+
21
+ def to_yaml_properties
22
+ ['@github_issue_id', '@title']
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,64 @@
1
+ require 'json'
2
+
3
+ module ExceptionHub
4
+ class Notifier
5
+ def initialize(exception, env)
6
+ @exception = exception
7
+ @env = env
8
+ end
9
+
10
+ def notify!
11
+ begin
12
+ issue = Issue.new
13
+ issue.description = build_description
14
+ issue.title = "#{@exception.class.name}: #{@exception.message}"
15
+
16
+ issue.send_to_github
17
+ rescue Exception => ex
18
+ ExceptionHub.logger.error("ExceptionHub: #{ex.class.name}: #{ex.message}")
19
+ ExceptionHub.logger.error(ex.backtrace.reduce("") {|memo, line| memo << line << "\n"})
20
+ end
21
+ end
22
+
23
+ private
24
+ def build_description
25
+ backtrace = if @exception.backtrace
26
+ @exception.backtrace.reduce("") {|memo, line| memo << line << "\n"}
27
+ else
28
+ ""
29
+ end
30
+ description = <<-DESC
31
+ ## Exception Message
32
+ #{@exception.message}
33
+
34
+ ## Data
35
+ ### Backtrace
36
+ ```
37
+ #{backtrace}
38
+ ```
39
+
40
+ ### Rack Env
41
+ ```
42
+ #{pretty_jsonify(@env)}
43
+ ```
44
+ DESC
45
+ end
46
+
47
+ def pretty_jsonify(env)
48
+ json = env_to_hash(env)
49
+ JSON.pretty_generate(JSON.parse(json.to_json))
50
+ end
51
+
52
+ def env_to_hash(env)
53
+ hash = {}
54
+ env.keys do |key|
55
+ if env[key].is_a?(Hash)
56
+ hash[key] = env_to_hash(env[key])
57
+ else
58
+ hash[key] = env[key].to_s
59
+ end
60
+ end
61
+ hash
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,27 @@
1
+ module ExceptionHub
2
+ # Rack middleware to intercept exceptions
3
+ class Rack
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def handle_exception(exception, env)
9
+ ExceptionHub.handle_exception(exception, env)
10
+ end
11
+
12
+ def call(env)
13
+ begin
14
+ response = @app.call(env)
15
+ rescue Exception => ex
16
+ env['exception_hub.issue_id'] = handle_exception(ex, env)
17
+ raise
18
+ end
19
+
20
+ if env['rack.exception']
21
+ env['exception_hub.issue_id'] = handle_exception(ex, env)
22
+ end
23
+
24
+ response
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ module ExceptionHub
2
+ module Rails
3
+ module ContollerInterceptor
4
+ def self.included(base)
5
+ base.send(:alias_method, :rescue_action_in_public_without_exception_hub, :rescue_action_in_public)
6
+ base.send(:alias_method, :rescue_action_in_public, :rescue_action_in_public_with_exception_hub)
7
+ end
8
+
9
+ private
10
+
11
+ def rescue_action_in_public_with_exception_hub(exception)
12
+ begin
13
+ ExceptionHub.handle_exception(exception, {})
14
+ rescue Exception => ex
15
+ ExceptionHub.logger.error("ExceptionHub: #{ex.class.name}: #{ex.message}")
16
+ ExceptionHub.logger.error(ex.backtrace.reduce("") {|memo, line| memo << line << "\n"})
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ module ExceptionHub
2
+ module Rails
3
+ module Middleware
4
+ module ExceptionsInterceptor
5
+ def self.included(base)
6
+ base.send(:alias_method_chain, :render_exception, :exception_hub_intercept)
7
+ end
8
+
9
+ private
10
+ def render_exception_with_exception_hub_intercept(env, exception)
11
+ begin
12
+ ExceptionHub.handle_exception(exception, env)
13
+ render_exception_without_exception_hub_intercept(env, exception)
14
+ rescue Exception => ex
15
+ ExceptionHub.logger.error("ExceptionHub: #{ex.class.name}: #{ex.message}")
16
+ ExceptionHub.logger.error(ex.backtrace.reduce("") {|memo, line| memo << line << "\n"})
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require 'exception_hub'
2
+ require 'rails'
3
+
4
+ module ExceptionHub
5
+ class Railtie < Rails::Railtie
6
+ railtie_name :exception_hub
7
+
8
+ initializer "exception_hub rack middleware" do |app|
9
+ app.config.middleware.insert 0, "ExceptionHub::Rack"
10
+ end
11
+
12
+ if defined?(::ActionDispatch::DebugExceptions)
13
+ require 'exception_hub/rails/middleware/exceptions_interceptor'
14
+ ::ActionDispatch::DebugExceptions.send(:include, ExceptionHub::Rails::Middleware::ExceptionsInterceptor)
15
+ elsif defined(::ActionDispatch::ShowExceptions)
16
+ require 'exception_hub/rails/controller_interceptor'
17
+ ::ActionDispatch::ShowExceptions.send(:include, ExceptionHub::Rails::ControllerInterceptor)
18
+ end
19
+
20
+ rake_tasks do
21
+ load 'tasks/exception_hub.rake'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ require 'exception_hub'
2
+
3
+ module ExceptionHub
4
+ class RakeTask < ::Rake::TaskLib
5
+ include ::Rake::DSL if defined?(::Rake::DSL)
6
+
7
+ def initialize(*args)
8
+ namespace :exception_hub do
9
+ desc "Generate ExceptionHub initializer"
10
+ task :generate_initializer do
11
+ puts "Github username:"
12
+ username = STDIN.gets.chomp
13
+ puts "Github password:"
14
+ system('stty -echo')
15
+ password = STDIN.gets.chomp
16
+ system('stty echo')
17
+
18
+ puts "Getting authorization from Github"
19
+ auth = ExceptionHub.get_api_token(username, password)
20
+
21
+ puts "Generating initializer"
22
+ File.write('./config/initializers/exception_hub.rb', ExceptionHub.generate_initializer(username, auth.token, auth.id))
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module ExceptionHub
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,20 @@
1
+ require 'exception_hub/version'
2
+ require 'exception_hub/configuration'
3
+ require 'exception_hub/issue'
4
+ require 'exception_hub/client'
5
+ require 'exception_hub/rack'
6
+ require 'exception_hub/notifier'
7
+ require 'exception_hub/interceptor'
8
+ require 'octokit'
9
+
10
+ require 'exception_hub/railtie' if defined?(Rails)
11
+
12
+ # @author Jesse Dearing <jesse.dearing@gmail.com>
13
+ module ExceptionHub
14
+ extend Configuration
15
+ extend Client
16
+
17
+ def self.handle_exception(exception, env)
18
+ Interceptor.new(exception, env).intercept!
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ require 'exception_hub/rake_task'
2
+
3
+ ExceptionHub::RakeTask.new
@@ -0,0 +1,17 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+
13
+ # Ignore all logfiles and tempfiles.
14
+ /log/*.log
15
+ /tmp
16
+
17
+ config/initializers/exception_hub.rb
@@ -0,0 +1,40 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rails', '3.2.6'
4
+
5
+ # Bundle edge Rails instead:
6
+ # gem 'rails', :git => 'git://github.com/rails/rails.git'
7
+
8
+ gem 'sqlite3'
9
+
10
+
11
+ # Gems used only for assets and not required
12
+ # in production environments by default.
13
+ group :assets do
14
+ gem 'sass-rails', '~> 3.2.3'
15
+ gem 'coffee-rails', '~> 3.2.1'
16
+
17
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
18
+ # gem 'therubyracer', :platforms => :ruby
19
+
20
+ gem 'uglifier', '>= 1.0.3'
21
+ end
22
+
23
+ gem 'jquery-rails'
24
+
25
+ gem 'exception_hub', :path => File.expand_path('../../../', File.dirname(__FILE__))
26
+
27
+ # To use ActiveModel has_secure_password
28
+ # gem 'bcrypt-ruby', '~> 3.0.0'
29
+
30
+ # To use Jbuilder templates for JSON
31
+ # gem 'jbuilder'
32
+
33
+ # Use unicorn as the app server
34
+ # gem 'unicorn'
35
+
36
+ # Deploy with Capistrano
37
+ # gem 'capistrano'
38
+
39
+ # To use debugger
40
+ # gem 'debugger'