relevance-chatterbox 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.treasure_map.rb +22 -0
- data/LICENSE +20 -0
- data/README.markdown +54 -0
- data/Rakefile +32 -0
- data/examples/chatterbox_example.rb +73 -0
- data/examples/example_helper.rb +23 -0
- data/examples/lib/chatterbox/notification_example.rb +138 -0
- data/examples/lib/chatterbox/rails_catcher_example.rb +54 -0
- data/init.rb +2 -0
- data/lib/chatterbox.rb +52 -0
- data/lib/chatterbox/notification.rb +84 -0
- data/lib/chatterbox/rails_catcher.rb +24 -0
- data/lib/consumers.rb +2 -0
- data/lib/consumers/email_consumer.rb +55 -0
- data/rails/init.rb +2 -0
- data/version.yml +4 -0
- data/views/chatterbox/mailer/exception_notification.erb +11 -0
- metadata +74 -0
data/.gitignore
ADDED
data/.treasure_map.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
map_for(:chatterbox) do |map|
|
2
|
+
|
3
|
+
map.keep_a_watchful_eye_for 'lib', 'examples', 'rails'
|
4
|
+
|
5
|
+
# map.add_mapping %r%examples/(.*)_example\.rb% do |match|
|
6
|
+
# ["examples/#{match[1]}_example.rb"]
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# map.add_mapping %r%examples/example_helper\.rb% do |match|
|
10
|
+
# Dir["examples/**/*_example.rb"]
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# map.add_mapping %r%lib/(.*)\.rb% do |match|
|
14
|
+
# Dir["examples/#{match[1]}_example.rb"]
|
15
|
+
# end
|
16
|
+
|
17
|
+
map.add_mapping %r%rails/(.*)\.rb% do |match|
|
18
|
+
["examples/#{match[1]}_example.rb"]
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Rob Sanheim
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
Chatterbox
|
2
|
+
==========================================
|
3
|
+
|
4
|
+
TODO summary
|
5
|
+
|
6
|
+
Installing and Running
|
7
|
+
---------------------------------------
|
8
|
+
|
9
|
+
To install within a Rails app:
|
10
|
+
|
11
|
+
Add the following to your environment.rb file:
|
12
|
+
|
13
|
+
config.gem "relevance-chatterbox"
|
14
|
+
|
15
|
+
Then run:
|
16
|
+
|
17
|
+
rake gems:install
|
18
|
+
|
19
|
+
To enable standard Rails exception catching for your controllers, add the following to `application_controller`
|
20
|
+
|
21
|
+
class ApplicationController < ActionController::Base
|
22
|
+
include Chatterbox::RailsCatcher
|
23
|
+
# ...
|
24
|
+
end
|
25
|
+
|
26
|
+
Then, wire up a producer
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
Rails Exception Integration
|
34
|
+
---------------------------------------
|
35
|
+
|
36
|
+
Example 1
|
37
|
+
---------------------------------------
|
38
|
+
|
39
|
+
Example 2
|
40
|
+
---------------------------------------
|
41
|
+
|
42
|
+
Bugs & Patches
|
43
|
+
--------------
|
44
|
+
|
45
|
+
Links
|
46
|
+
-------------
|
47
|
+
|
48
|
+
Contributors
|
49
|
+
------------
|
50
|
+
* Rob Sanheim
|
51
|
+
|
52
|
+
Copyrights
|
53
|
+
------------
|
54
|
+
* Copyright © 2008-2009 [Relevance, Inc.](http://www.thinkrelevance.com/), under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "chatterbox"
|
8
|
+
gem.summary = %Q{TODO}
|
9
|
+
gem.email = "rsanheim@gmail.com"
|
10
|
+
gem.homepage = "http://github.com/relevance/chatterbox"
|
11
|
+
gem.authors = ["Rob Sanheim"]
|
12
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
13
|
+
end
|
14
|
+
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'micronaut/rake_task'
|
20
|
+
Micronaut::RakeTask.new(:examples) do |examples|
|
21
|
+
examples.pattern = 'examples/**/*_example.rb'
|
22
|
+
examples.ruby_opts << '-Ilib -Iexamples'
|
23
|
+
end
|
24
|
+
|
25
|
+
Micronaut::RakeTask.new(:rcov) do |examples|
|
26
|
+
examples.pattern = 'examples/**/*_example.rb'
|
27
|
+
examples.rcov_opts = '-Ilib -Iexamples'
|
28
|
+
examples.rcov = true
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
task :default => :examples
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[example_helper])
|
2
|
+
|
3
|
+
describe Chatterbox do
|
4
|
+
|
5
|
+
before do
|
6
|
+
Chatterbox.logger = Logger.new(nil)
|
7
|
+
Chatterbox::Publishers.clear!
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
Chatterbox.logger = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "handle_notice" do
|
15
|
+
include Chatterbox
|
16
|
+
|
17
|
+
it "should create Notification and return the notice" do
|
18
|
+
notification = mock(:notice => {:hash => 'of awesomeness'})
|
19
|
+
Chatterbox::Notification.expects(:new).returns(notification)
|
20
|
+
handle_notice("message")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should publish the notice" do
|
24
|
+
notification = stub(:notice => {:hash => 'of awesomeness'})
|
25
|
+
Chatterbox::Notification.stubs(:new).returns(notification)
|
26
|
+
expects(:publish_notice).with({:hash => 'of awesomeness'})
|
27
|
+
handle_notice("message")
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "logger" do
|
33
|
+
|
34
|
+
it "uses STDOUT logger if Rails not available" do
|
35
|
+
Chatterbox.logger = nil
|
36
|
+
|
37
|
+
Logger.expects(:new).with(STDOUT).returns("logger")
|
38
|
+
Chatterbox.stubs(:rails_default_logger).returns(nil)
|
39
|
+
Chatterbox.logger.should == "logger"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "publish" do
|
44
|
+
|
45
|
+
include Chatterbox
|
46
|
+
|
47
|
+
it "should call each publisher with the notice" do
|
48
|
+
notice = stub
|
49
|
+
publisher = Chatterbox::Publishers.register { "i'm in your block" }
|
50
|
+
publisher.expects(:call).with(notice)
|
51
|
+
|
52
|
+
publish_notice(notice)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "publishers" do
|
58
|
+
|
59
|
+
it "should allow clearing all publishers" do
|
60
|
+
Chatterbox::Publishers.register { "sending your messages" }
|
61
|
+
Chatterbox::Publishers.publishers.size.should == 1
|
62
|
+
Chatterbox::Publishers.clear!
|
63
|
+
Chatterbox::Publishers.publishers.size.should == 0
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should allow registering with a block" do
|
67
|
+
pub1 = Chatterbox::Publishers.register { "sending your messages" }
|
68
|
+
pub2 = Chatterbox::Publishers.register { "announcing your news" }
|
69
|
+
Chatterbox::Publishers.publishers.should == [pub1, pub2]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'action_controller'
|
3
|
+
require 'micronaut'
|
4
|
+
require 'micronaut-rails'
|
5
|
+
require 'mocha'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
9
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
10
|
+
|
11
|
+
require 'chatterbox'
|
12
|
+
|
13
|
+
def not_in_editor?
|
14
|
+
!(ENV.has_key?('TM_MODE') || ENV.has_key?('EMACS') || ENV.has_key?('VIM'))
|
15
|
+
end
|
16
|
+
|
17
|
+
Micronaut.configure do |c|
|
18
|
+
c.mock_with :mocha
|
19
|
+
c.color_enabled = not_in_editor?
|
20
|
+
c.filter_run :focused => true
|
21
|
+
c.alias_example_to :fit, :focused => true
|
22
|
+
c.enable_controller_support :behaviour => { :describes => lambda { |dt| dt < ::ActionController::Base } }
|
23
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. example_helper]))
|
2
|
+
|
3
|
+
describe Chatterbox::Notification do
|
4
|
+
|
5
|
+
before do
|
6
|
+
Chatterbox.logger = Logger.new(nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "creating the notice" do
|
10
|
+
|
11
|
+
it "should safely handle nil" do
|
12
|
+
lambda {
|
13
|
+
Chatterbox::Notification.new(nil).notice
|
14
|
+
}.should_not raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should convert exception to notice" do
|
18
|
+
exception = RuntimeError.new
|
19
|
+
notification = Chatterbox::Notification.new(exception)
|
20
|
+
notification.expects(:exception_to_notice).with(exception).returns({})
|
21
|
+
notification.notice
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should use to_hash if message is not an exception and it responds_to possible" do
|
25
|
+
some_object = mock(:to_hash => {:foo => "bar"})
|
26
|
+
Chatterbox::Notification.new(some_object).notice.should include({:foo => "bar"})
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should call to_s on anything that responds to it, as a last resort" do
|
30
|
+
some_object = mock(:to_s => "my to_s")
|
31
|
+
Chatterbox::Notification.new(some_object).notice.should include({:summary => "my to_s"})
|
32
|
+
end
|
33
|
+
|
34
|
+
it "merges hash passed in with default info" do
|
35
|
+
hash = {:message => "hey!"}
|
36
|
+
default_info = mock()
|
37
|
+
default_info.expects(:merge).with(hash)
|
38
|
+
notification = Chatterbox::Notification.new(hash)
|
39
|
+
notification.expects(:default_info).returns(default_info)
|
40
|
+
notification.notice
|
41
|
+
end
|
42
|
+
|
43
|
+
it "turns string notice into a hash keyed by notice" do
|
44
|
+
notification = Chatterbox::Notification.new("You have been placed on alert")
|
45
|
+
notification.notice.should include({:summary => "You have been placed on alert"})
|
46
|
+
end
|
47
|
+
|
48
|
+
it "always includes a summary" do
|
49
|
+
Chatterbox::Notification.new().notice.should include(:summary)
|
50
|
+
Chatterbox::Notification.new({}).notice.should include(:summary)
|
51
|
+
Chatterbox::Notification.new(RuntimeError.new).notice.should include(:summary)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should set summary to N/A if nothing provided" do
|
55
|
+
Chatterbox::Notification.new({}).notice.should include(:summary => "N/A")
|
56
|
+
Chatterbox::Notification.new({:foo => 'baz'}).notice.should include(:summary => "N/A")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "exceptions" do
|
61
|
+
|
62
|
+
def raised_exception
|
63
|
+
raise RuntimeError, "Your zing bats got mixed up with the snosh frazzles."
|
64
|
+
rescue => e
|
65
|
+
e
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should extract exception info" do
|
69
|
+
exception = raised_exception
|
70
|
+
data = Chatterbox::Notification.new(exception).notice
|
71
|
+
data[:summary].should == "RuntimeError: Your zing bats got mixed up with the snosh frazzles."
|
72
|
+
data[:error_class].should == "RuntimeError"
|
73
|
+
data[:error_message].should == "Your zing bats got mixed up with the snosh frazzles."
|
74
|
+
data[:backtrace].should == exception.backtrace
|
75
|
+
end
|
76
|
+
|
77
|
+
it "merges rails info and ruby info into the exception info" do
|
78
|
+
notification = Chatterbox::Notification.new(raised_exception)
|
79
|
+
rails = stub_everything(:version => "2.0", :root => "/rails/root", :env => "production")
|
80
|
+
notification.stubs(:rails_configuration).returns(rails)
|
81
|
+
notification.notice.should include(:rails_version => "2.0")
|
82
|
+
notification.notice.should include(:rails_root => "/rails/root")
|
83
|
+
notification.notice.should include(:rails_env => "production")
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "hashes" do
|
89
|
+
|
90
|
+
it "merges rails info and ruby info into the notification" do
|
91
|
+
notification = Chatterbox::Notification.new({})
|
92
|
+
rails = stub_everything(:version => "2.0", :root => "/rails/root", :env => "production")
|
93
|
+
notification.stubs(:rails_configuration).returns(rails)
|
94
|
+
notification.notice.should include(:rails_version => "2.0")
|
95
|
+
notification.notice.should include(:rails_root => "/rails/root")
|
96
|
+
notification.notice.should include(:rails_env => "production")
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "default info to be included with every notification" do
|
102
|
+
|
103
|
+
it "should return full ENV" do
|
104
|
+
environment = { "USER" => "jdoe", "PATH" => "/usr/bin", "HOME" => "/usr/home/jdoe" }
|
105
|
+
notification = Chatterbox::Notification.new
|
106
|
+
notification.stubs(:env).returns(environment)
|
107
|
+
notification.default_info.should include(:environment => environment)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should return Ruby version and platform" do
|
111
|
+
notification = Chatterbox::Notification.new
|
112
|
+
notification.stubs(:ruby_version).returns("1.8.6")
|
113
|
+
notification.stubs(:ruby_platform).returns("Mac OS X blah")
|
114
|
+
data = notification.default_info
|
115
|
+
data.should include(:ruby_version => "1.8.6")
|
116
|
+
data.should include(:ruby_platform => "Mac OS X blah")
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "when Rails is defined" do
|
120
|
+
|
121
|
+
it "should return Rails info" do
|
122
|
+
notification = Chatterbox::Notification.new
|
123
|
+
rails = stub
|
124
|
+
rails.stubs(:root).returns("/some/path")
|
125
|
+
rails.stubs(:env).returns("production")
|
126
|
+
rails.stubs(:version).returns("2.1.2")
|
127
|
+
notification.stubs(:rails_configuration).returns(rails)
|
128
|
+
|
129
|
+
notification.default_info.should include(:rails_root => "/some/path")
|
130
|
+
notification.default_info.should include(:rails_env => "production")
|
131
|
+
notification.default_info.should include(:rails_version => "2.1.2")
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. example_helper]))
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. .. rails init]))
|
3
|
+
|
4
|
+
ActionController::Routing::Routes.draw { |map| map.connect ':controller/:action/:id' }
|
5
|
+
|
6
|
+
class WidgetException < RuntimeError; end
|
7
|
+
class WidgetsController < ActionController::Base
|
8
|
+
include Chatterbox::RailsCatcher
|
9
|
+
|
10
|
+
def rescue_action e
|
11
|
+
rescue_action_in_public e
|
12
|
+
end
|
13
|
+
|
14
|
+
def rescue_action_in_public_without_chatterbox e
|
15
|
+
raise e
|
16
|
+
end
|
17
|
+
|
18
|
+
def index
|
19
|
+
raise_exception
|
20
|
+
render :text => "hi"
|
21
|
+
end
|
22
|
+
|
23
|
+
def raise_exception
|
24
|
+
raise WidgetException, "Bad dog!"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe WidgetsController do
|
29
|
+
|
30
|
+
describe "rescue aliasing" do
|
31
|
+
|
32
|
+
it "should alias method chain" do
|
33
|
+
exception = RuntimeError.new
|
34
|
+
@controller.expects(:rescue_action_in_public_without_chatterbox).with(exception)
|
35
|
+
@controller.rescue_action_in_public(exception)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "exception handling" do
|
40
|
+
|
41
|
+
it "should raise on index" do
|
42
|
+
lambda {
|
43
|
+
get :index
|
44
|
+
}.should raise_error(WidgetException, "Bad dog!")
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should send exception to handle_notice" do
|
48
|
+
Chatterbox.expects(:handle_notice).with(instance_of(WidgetException))
|
49
|
+
get :index rescue nil
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/init.rb
ADDED
data/lib/chatterbox.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[chatterbox notification])
|
2
|
+
require File.join(File.dirname(__FILE__), *%w[consumers])
|
3
|
+
|
4
|
+
module Chatterbox
|
5
|
+
|
6
|
+
def handle_notice(message)
|
7
|
+
notice = Notification.new(message).notice
|
8
|
+
publish_notice(notice)
|
9
|
+
end
|
10
|
+
|
11
|
+
def publish_notice(notice)
|
12
|
+
Publishers.publishers.each { |p| p.call(notice) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def logger
|
16
|
+
@logger ||= rails_default_logger || Logger.new(STDOUT)
|
17
|
+
end
|
18
|
+
|
19
|
+
def logger=(logger)
|
20
|
+
@logger = logger
|
21
|
+
end
|
22
|
+
|
23
|
+
def rails_default_logger
|
24
|
+
defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : nil
|
25
|
+
end
|
26
|
+
|
27
|
+
extend self
|
28
|
+
|
29
|
+
module Publishers
|
30
|
+
|
31
|
+
class << self
|
32
|
+
|
33
|
+
def publishers
|
34
|
+
@publishers ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
def register(&blk)
|
38
|
+
Chatterbox.logger.debug { "Registering publisher: #{blk}"}
|
39
|
+
publishers << blk
|
40
|
+
blk
|
41
|
+
end
|
42
|
+
|
43
|
+
def clear!
|
44
|
+
@publishers = []
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Chatterbox
|
2
|
+
|
3
|
+
class Notification
|
4
|
+
|
5
|
+
attr_reader :message
|
6
|
+
|
7
|
+
def initialize(message = nil)
|
8
|
+
@message = message
|
9
|
+
end
|
10
|
+
|
11
|
+
def notice
|
12
|
+
hash = normalize_message_to_hash(message)
|
13
|
+
default_info.merge(hash)
|
14
|
+
end
|
15
|
+
|
16
|
+
def normalize_message_to_hash(message)
|
17
|
+
case
|
18
|
+
when Exception === message
|
19
|
+
exception_to_notice(message)
|
20
|
+
when message.respond_to?(:to_hash)
|
21
|
+
message.to_hash
|
22
|
+
when message.respond_to?(:to_s)
|
23
|
+
string_to_notice(message.to_s)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_info
|
28
|
+
default_info = {
|
29
|
+
:summary => "N/A",
|
30
|
+
:environment => env,
|
31
|
+
:ruby_version => ruby_version,
|
32
|
+
:ruby_platform => ruby_platform
|
33
|
+
}
|
34
|
+
default_info = add_ruby_info(default_info)
|
35
|
+
default_info = add_rails_info(default_info) if rails_configuration
|
36
|
+
default_info
|
37
|
+
end
|
38
|
+
|
39
|
+
def string_to_notice(message)
|
40
|
+
{ :summary => message }
|
41
|
+
end
|
42
|
+
|
43
|
+
def exception_to_notice(exception)
|
44
|
+
{
|
45
|
+
:summary => "#{exception.class.name}: #{exception.message}",
|
46
|
+
:error_class => exception.class.name,
|
47
|
+
:error_message => exception.message,
|
48
|
+
:backtrace => exception.backtrace,
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_rails_info(data)
|
53
|
+
data.merge({
|
54
|
+
:rails_env => rails_configuration.env,
|
55
|
+
:rails_root => rails_configuration.root,
|
56
|
+
:rails_version => rails_configuration.version
|
57
|
+
})
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_ruby_info(data)
|
61
|
+
data.merge({
|
62
|
+
:ruby_version => ruby_version,
|
63
|
+
:ruby_platform => ruby_platform
|
64
|
+
})
|
65
|
+
end
|
66
|
+
|
67
|
+
def ruby_version
|
68
|
+
RUBY_VERSION
|
69
|
+
end
|
70
|
+
|
71
|
+
def ruby_platform
|
72
|
+
RUBY_PLATFORM
|
73
|
+
end
|
74
|
+
|
75
|
+
def env
|
76
|
+
ENV.to_hash
|
77
|
+
end
|
78
|
+
|
79
|
+
def rails_configuration
|
80
|
+
defined?(Rails) && Rails
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Chatterbox
|
2
|
+
|
3
|
+
module RailsCatcher
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
if base.instance_methods.map(&:to_s).include? 'rescue_action_in_public' and !base.instance_methods.map(&:to_s).include? 'rescue_action_in_public_without_chatterbox'
|
7
|
+
base.send(:alias_method, :rescue_action_in_public_without_chatterbox, :rescue_action_in_public)
|
8
|
+
base.send(:alias_method, :rescue_action_in_public, :rescue_action_in_public_with_chatterbox)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Overrides the rescue_action method in ActionController::Base, but does not inhibit
|
13
|
+
# any custom processing that is defined with Rails 2's exception helpers.
|
14
|
+
def rescue_action_in_public_with_chatterbox exception
|
15
|
+
Chatterbox.logger.debug { "#{self.class}#rescue_action_in_public_with_chatterbox: caught exception #{exception} - about to handle"}
|
16
|
+
Chatterbox.handle_notice(exception)
|
17
|
+
Chatterbox.logger.debug { "#{self.class}#rescue_action_in_public_with_chatterbox: handing exception #{exception} off to normal rescue handling"}
|
18
|
+
|
19
|
+
rescue_action_in_public_without_chatterbox(exception)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/lib/consumers.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Chatterbox
|
2
|
+
class EmailConsumer
|
3
|
+
|
4
|
+
attr_reader :notice
|
5
|
+
|
6
|
+
def initialize(notice)
|
7
|
+
@notice = notice
|
8
|
+
end
|
9
|
+
|
10
|
+
def process
|
11
|
+
Chatterbox.logger.debug { "Mailing notification #{notice['summary']}"}
|
12
|
+
Mailer.deliver_exception_notification(notice)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
class Mailer < ActionMailer::Base
|
18
|
+
@@sender_address = %("Exception Notifier" <exception.notifier@default.com>)
|
19
|
+
cattr_accessor :sender_address
|
20
|
+
|
21
|
+
@@exception_recipients = []
|
22
|
+
cattr_accessor :exception_recipients
|
23
|
+
|
24
|
+
@@email_prefix = "[ERROR] "
|
25
|
+
cattr_accessor :email_prefix
|
26
|
+
|
27
|
+
self.template_root = File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. views]))
|
28
|
+
|
29
|
+
def self.reloadable?() false end
|
30
|
+
|
31
|
+
def exception_notification(data={})
|
32
|
+
content_type "text/plain"
|
33
|
+
|
34
|
+
subject "#{email_prefix} Error - #{data['summary']}"
|
35
|
+
|
36
|
+
recipients exception_recipients
|
37
|
+
from sender_address
|
38
|
+
|
39
|
+
body data
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def sanitize_backtrace(trace)
|
45
|
+
re = Regexp.new(/^#{Regexp.escape(rails_root)}/)
|
46
|
+
trace.map { |line| Pathname.new(line.gsub(re, "[RAILS_ROOT]")).cleanpath.to_s }
|
47
|
+
end
|
48
|
+
|
49
|
+
def rails_root
|
50
|
+
@rails_root ||= Pathname.new(RAILS_ROOT).cleanpath.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/rails/init.rb
ADDED
data/version.yml
ADDED
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: relevance-chatterbox
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rob Sanheim
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-20 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: rsanheim@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.markdown
|
25
|
+
files:
|
26
|
+
- .gitignore
|
27
|
+
- .treasure_map.rb
|
28
|
+
- LICENSE
|
29
|
+
- README.markdown
|
30
|
+
- Rakefile
|
31
|
+
- examples/chatterbox_example.rb
|
32
|
+
- examples/example_helper.rb
|
33
|
+
- examples/lib/chatterbox/notification_example.rb
|
34
|
+
- examples/lib/chatterbox/rails_catcher_example.rb
|
35
|
+
- init.rb
|
36
|
+
- lib/chatterbox.rb
|
37
|
+
- lib/chatterbox/notification.rb
|
38
|
+
- lib/chatterbox/rails_catcher.rb
|
39
|
+
- lib/consumers.rb
|
40
|
+
- lib/consumers/email_consumer.rb
|
41
|
+
- rails/init.rb
|
42
|
+
- version.yml
|
43
|
+
- views/chatterbox/mailer/exception_notification.erb
|
44
|
+
has_rdoc: false
|
45
|
+
homepage: http://github.com/relevance/chatterbox
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --charset=UTF-8
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.2.0
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: TODO
|
70
|
+
test_files:
|
71
|
+
- examples/chatterbox_example.rb
|
72
|
+
- examples/example_helper.rb
|
73
|
+
- examples/lib/chatterbox/notification_example.rb
|
74
|
+
- examples/lib/chatterbox/rails_catcher_example.rb
|