exceptioner 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +63 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/exceptioner.gemspec +77 -0
- data/init.rb +1 -0
- data/lib/exceptioner/action_controller.rb +31 -0
- data/lib/exceptioner/core_ext/class/attribute_accessors.rb +42 -0
- data/lib/exceptioner/core_ext/module/attribute_accessors.rb +34 -0
- data/lib/exceptioner/middleware.rb +20 -0
- data/lib/exceptioner/notifier.rb +27 -0
- data/lib/exceptioner/railtie.rb +25 -0
- data/lib/exceptioner/transport/base.rb +43 -0
- data/lib/exceptioner/transport/helper.rb +23 -0
- data/lib/exceptioner/transport/jabber/jabber.rb +46 -0
- data/lib/exceptioner/transport/mail/mail.rb +56 -0
- data/lib/exceptioner/transport/templates/exception.erb +18 -0
- data/lib/exceptioner.rb +39 -0
- data/lib/generators/exceptioner/USAGE +3 -0
- data/lib/generators/exceptioner/install_generator.rb +13 -0
- data/lib/generators/exceptioner/templates/exceptioner.rb +45 -0
- data/spec/exceptioner_spec.rb +7 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- metadata +130 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Michał Łomnicki
|
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.rdoc
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
= Exceptioner
|
2
|
+
|
3
|
+
Be notified about exceptions by various transports Email, Jabber, IRC, etc. Choose the option you want.
|
4
|
+
|
5
|
+
The most common use is to use Exceptioner as rack middleware and send notifications when an exception occur in you web application. It may be used with Rails, Sinatra or any other rack citizen.
|
6
|
+
Exceptioner may be also used with any ruby code you want. Just configure delivery methods and don't miss any exception.
|
7
|
+
|
8
|
+
= Currently available delivery methods
|
9
|
+
* Email - BETA
|
10
|
+
* Jabber/XMPP - ALPHA
|
11
|
+
|
12
|
+
= Usage
|
13
|
+
|
14
|
+
Note: Exceptioner is under heavy development and it is not recommended to use for
|
15
|
+
production applications.
|
16
|
+
|
17
|
+
== Rails 3 users
|
18
|
+
|
19
|
+
Add to your Gemfile
|
20
|
+
gem 'exceptioner'
|
21
|
+
|
22
|
+
and obviously run bundle install
|
23
|
+
|
24
|
+
Then copy config file to your application
|
25
|
+
rails generate exceptioner:install.
|
26
|
+
|
27
|
+
You probably want to check config/initializers/exceptioner.rb and customize it a bit
|
28
|
+
|
29
|
+
== Rails 2.X users
|
30
|
+
|
31
|
+
NEED SUPPORT
|
32
|
+
|
33
|
+
== Any Rack application users
|
34
|
+
|
35
|
+
gem install exceptioner
|
36
|
+
|
37
|
+
Then require exceptioner and add Exceptioner::Middleware to your stack
|
38
|
+
|
39
|
+
== Any Ruby application users
|
40
|
+
|
41
|
+
gem install exceptioner
|
42
|
+
|
43
|
+
Then require excptioner and use it like:
|
44
|
+
|
45
|
+
begin
|
46
|
+
# some code which may fail
|
47
|
+
rescue VeryFatalError => e
|
48
|
+
Exceptioner::Notifier.dispatch(e)
|
49
|
+
end
|
50
|
+
|
51
|
+
== Note on Patches/Pull Requests
|
52
|
+
|
53
|
+
* Fork the project.
|
54
|
+
* Make your feature addition or bug fix.
|
55
|
+
* Add tests for it. This is important so I don't break it in a
|
56
|
+
future version unintentionally.
|
57
|
+
* Commit, do not mess with rakefile, version, or history.
|
58
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
59
|
+
* Send me a pull request. Bonus points for topic branches.
|
60
|
+
|
61
|
+
== Copyright
|
62
|
+
|
63
|
+
Copyright (c) 2010 Michał Łomnicki. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "exceptioner"
|
8
|
+
gem.summary = %Q{Be notified about exceptions by various transports Email, Jabber, RSS. Choose the option you want}
|
9
|
+
gem.description = %Q{The most common use is to use Exceptioner as rack middleware and send notifications when an exception occur in you web application. It may be used with Rails, Sinatra or any other rack citizen.
|
10
|
+
Exceptioner may be also used with any ruby code you want. Just configure delivery methods and don't miss any exception.}
|
11
|
+
gem.email = "michal@lomnicki.com.pl"
|
12
|
+
gem.homepage = "http://github.com/mlomnicki/exceptioner"
|
13
|
+
gem.authors = ["Michał Łomnicki"]
|
14
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
15
|
+
gem.add_dependency "mail", "~> 2.2"
|
16
|
+
gem.add_dependency "xmpp4r", "~> 0.5"
|
17
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'spec/rake/spectask'
|
25
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
26
|
+
spec.libs << 'lib' << 'spec'
|
27
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
28
|
+
end
|
29
|
+
|
30
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
31
|
+
spec.libs << 'lib' << 'spec'
|
32
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
+
spec.rcov = true
|
34
|
+
end
|
35
|
+
|
36
|
+
task :spec => :check_dependencies
|
37
|
+
|
38
|
+
task :default => :spec
|
39
|
+
|
40
|
+
require 'rake/rdoctask'
|
41
|
+
Rake::RDocTask.new do |rdoc|
|
42
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
43
|
+
|
44
|
+
rdoc.rdoc_dir = 'rdoc'
|
45
|
+
rdoc.title = "exceptioner #{version}"
|
46
|
+
rdoc.rdoc_files.include('README*')
|
47
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/exceptioner.gemspec
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{exceptioner}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Micha\305\202 \305\201omnicki"]
|
12
|
+
s.date = %q{2010-12-14}
|
13
|
+
s.description = %q{The most common use is to use Exceptioner as rack middleware and send notifications when an exception occur in you web application. It may be used with Rails, Sinatra or any other rack citizen.
|
14
|
+
Exceptioner may be also used with any ruby code you want. Just configure delivery methods and don't miss any exception.}
|
15
|
+
s.email = %q{michal@lomnicki.com.pl}
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".gitignore",
|
23
|
+
"LICENSE",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"exceptioner.gemspec",
|
28
|
+
"init.rb",
|
29
|
+
"lib/exceptioner.rb",
|
30
|
+
"lib/exceptioner/action_controller.rb",
|
31
|
+
"lib/exceptioner/core_ext/class/attribute_accessors.rb",
|
32
|
+
"lib/exceptioner/core_ext/module/attribute_accessors.rb",
|
33
|
+
"lib/exceptioner/middleware.rb",
|
34
|
+
"lib/exceptioner/notifier.rb",
|
35
|
+
"lib/exceptioner/railtie.rb",
|
36
|
+
"lib/exceptioner/transport/base.rb",
|
37
|
+
"lib/exceptioner/transport/helper.rb",
|
38
|
+
"lib/exceptioner/transport/jabber/jabber.rb",
|
39
|
+
"lib/exceptioner/transport/mail/mail.rb",
|
40
|
+
"lib/exceptioner/transport/templates/exception.erb",
|
41
|
+
"lib/generators/exceptioner/USAGE",
|
42
|
+
"lib/generators/exceptioner/install_generator.rb",
|
43
|
+
"lib/generators/exceptioner/templates/exceptioner.rb",
|
44
|
+
"spec/exceptioner_spec.rb",
|
45
|
+
"spec/spec.opts",
|
46
|
+
"spec/spec_helper.rb"
|
47
|
+
]
|
48
|
+
s.homepage = %q{http://github.com/mlomnicki/exceptioner}
|
49
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
50
|
+
s.require_paths = ["lib"]
|
51
|
+
s.rubygems_version = %q{1.3.6}
|
52
|
+
s.summary = %q{Be notified about exceptions by various transports Email, Jabber, RSS. Choose the option you want}
|
53
|
+
s.test_files = [
|
54
|
+
"spec/exceptioner_spec.rb",
|
55
|
+
"spec/spec_helper.rb"
|
56
|
+
]
|
57
|
+
|
58
|
+
if s.respond_to? :specification_version then
|
59
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
60
|
+
s.specification_version = 3
|
61
|
+
|
62
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
63
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
64
|
+
s.add_runtime_dependency(%q<mail>, ["~> 2.2"])
|
65
|
+
s.add_runtime_dependency(%q<xmpp4r>, ["~> 0.5"])
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
68
|
+
s.add_dependency(%q<mail>, ["~> 2.2"])
|
69
|
+
s.add_dependency(%q<xmpp4r>, ["~> 0.5"])
|
70
|
+
end
|
71
|
+
else
|
72
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
73
|
+
s.add_dependency(%q<mail>, ["~> 2.2"])
|
74
|
+
s.add_dependency(%q<xmpp4r>, ["~> 0.5"])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'exceptioner'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# This model is intended to be included in Rails2.x ApplicationController
|
2
|
+
# For Rails 3 as well as for other web frameworks you should use
|
3
|
+
# Exceptioner::Middleware
|
4
|
+
#
|
5
|
+
# Rails 2.x catch exceptions in ActionController::Base so they aren't propagated
|
6
|
+
# to underlaying middlewares. This obviously makes Exceptioner::Middleware
|
7
|
+
# useless.
|
8
|
+
|
9
|
+
require 'exceptioner/notifier'
|
10
|
+
|
11
|
+
module Exceptioner
|
12
|
+
module ActionController
|
13
|
+
|
14
|
+
private
|
15
|
+
def rescue_action_in_public(exception)
|
16
|
+
super
|
17
|
+
exceptioner_dispatch_exception(exception)
|
18
|
+
end
|
19
|
+
|
20
|
+
def rescue_action_locally(exception)
|
21
|
+
super
|
22
|
+
exceptioner_dispatch_exception(exception) if Exceptioner.dispatch_local_requests
|
23
|
+
end
|
24
|
+
|
25
|
+
def exceptioner_dispatch_exception(exception)
|
26
|
+
Notifier.dispatch(exception, :controller => self, :env => request.env)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# This code is stolen from ActiveSupport gem.
|
2
|
+
# We don't need to pass options like :instance_writer
|
3
|
+
# for cattr_ methods so responsible part of code was removed.
|
4
|
+
#
|
5
|
+
# Note we don't overwrite cattr_ methods if they exist already.
|
6
|
+
|
7
|
+
class Class
|
8
|
+
def cattr_reader(*syms)
|
9
|
+
syms.each do |sym|
|
10
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
11
|
+
unless defined? @@#{sym}
|
12
|
+
@@#{sym} = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.#{sym}
|
16
|
+
@@#{sym}
|
17
|
+
end
|
18
|
+
EOS
|
19
|
+
end
|
20
|
+
end unless method_defined?(:cattr_reader)
|
21
|
+
|
22
|
+
def cattr_writer(*syms)
|
23
|
+
syms.each do |sym|
|
24
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
25
|
+
unless defined? @@#{sym}
|
26
|
+
@@#{sym} = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.#{sym}=(obj)
|
30
|
+
@@#{sym} = obj
|
31
|
+
end
|
32
|
+
EOS
|
33
|
+
|
34
|
+
self.send("#{sym}=", yield) if block_given?
|
35
|
+
end
|
36
|
+
end unless method_defined?(:cattr_writer)
|
37
|
+
|
38
|
+
def cattr_accessor(*syms, &blk)
|
39
|
+
cattr_reader(*syms)
|
40
|
+
cattr_writer(*syms, &blk)
|
41
|
+
end unless method_defined?(:cattr_accessor)
|
42
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# This code is stolen from ActiveSupport gem.
|
2
|
+
# We don't need to pass options like :instance_writer
|
3
|
+
# for mattr_ methods so responsible part of code was removed.
|
4
|
+
#
|
5
|
+
# Note we don't overwrite mattr_ methods if they exist already.
|
6
|
+
|
7
|
+
class Module
|
8
|
+
def mattr_reader(*syms)
|
9
|
+
syms.each do |sym|
|
10
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
11
|
+
@@#{sym} = nil unless defined? @@#{sym}
|
12
|
+
|
13
|
+
def self.#{sym}
|
14
|
+
@@#{sym}
|
15
|
+
end
|
16
|
+
EOS
|
17
|
+
end
|
18
|
+
end unless method_defined?(:mattr_reader)
|
19
|
+
|
20
|
+
def mattr_writer(*syms)
|
21
|
+
syms.each do |sym|
|
22
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
23
|
+
def self.#{sym}=(obj)
|
24
|
+
@@#{sym} = obj
|
25
|
+
end
|
26
|
+
EOS
|
27
|
+
end
|
28
|
+
end unless method_defined?(:mattr_writer)
|
29
|
+
|
30
|
+
def mattr_accessor(*syms)
|
31
|
+
mattr_reader(*syms)
|
32
|
+
mattr_writer(*syms)
|
33
|
+
end unless method_defined?(:mattr_accessor)
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'exceptioner/notifier'
|
2
|
+
|
3
|
+
module Exceptioner
|
4
|
+
class Middleware
|
5
|
+
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
begin
|
12
|
+
@app.call(env)
|
13
|
+
rescue Exception => exception
|
14
|
+
Notifier.dispatch(exception, :controller => env['action_controller.instance'], :env => env)
|
15
|
+
raise exception
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Exceptioner
|
2
|
+
class Notifier
|
3
|
+
|
4
|
+
def self.dispatch(exception, options = {})
|
5
|
+
available_transports = classify_transports(options[:transports] || transports)
|
6
|
+
available_transports.each do |transport|
|
7
|
+
transport.deliver(exception, options)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
def self.transports
|
13
|
+
Exceptioner.transports
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.classify_transports(transports)
|
17
|
+
transports.collect do |transport|
|
18
|
+
begin
|
19
|
+
transport.is_a?(Class) ? transport : Transport.const_get(transport.to_s.camelize)
|
20
|
+
rescue NameError
|
21
|
+
raise ExceptionerError, "No such transport: #{transport.to_s}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Exceptioner
|
2
|
+
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
|
5
|
+
initializer "exceptioner.use_rack_middleware" do |app|
|
6
|
+
app.config.middleware.use "Exceptioner::Middleware"
|
7
|
+
end
|
8
|
+
|
9
|
+
initializer "exceptioner.use_rails_default" do |app|
|
10
|
+
Exceptioner.mail.delivery_method = rails_delivery(app)
|
11
|
+
Exceptioner.mail.delivery_options = rails_delivery_options(app)
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
def rails_delivery(app)
|
16
|
+
app.config.action_mailer.delivery_method
|
17
|
+
end
|
18
|
+
|
19
|
+
def rails_delivery_options(app)
|
20
|
+
app.config.action_mailer.send("#{rails_delivery(app)}_settings") if app.config.action_mailer.respond_to?("#{rails_delivery(app)}_settings")
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Exceptioner::Transport
|
2
|
+
|
3
|
+
class Base
|
4
|
+
|
5
|
+
cattr_accessor :sender
|
6
|
+
|
7
|
+
cattr_accessor :recipients
|
8
|
+
|
9
|
+
cattr_accessor :prefix
|
10
|
+
|
11
|
+
cattr_accessor :subject
|
12
|
+
|
13
|
+
|
14
|
+
def self.deliver(exception, options = {})
|
15
|
+
raise Exceptioner::ExceptionerError, 'Implement deliver class method in your Exceptioner::Transport::Base subclass'
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
def self.default_options
|
20
|
+
{
|
21
|
+
:sender => sender || 'exceptioner',
|
22
|
+
:recipients => recipients,
|
23
|
+
:prefix => prefix || '[ERROR] ',
|
24
|
+
:subject => subject
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.prefixed_subject(exception, options)
|
29
|
+
"#{options[:prefix]}#{exception.message}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.render(exception, options = {})
|
33
|
+
ERB.new(template, nil, '>').result(binding)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.template
|
37
|
+
@template ||= File.read(File.expand_path(File.join(File.dirname(__FILE__), 'templates', 'exception.erb')))
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Exceptioner::Transport
|
2
|
+
module Helper
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def format_env(env)
|
6
|
+
unless env.empty?
|
7
|
+
max_length = env.keys.max_by { |key| key.to_s.size }.size
|
8
|
+
env.keys.sort.collect do |key|
|
9
|
+
"* #{"%-*s: %s" % [max_length, key, env[key].to_s.strip[0..50]]}\n\t"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def title(text)
|
15
|
+
length = text.size + 5
|
16
|
+
char = '#'
|
17
|
+
"#{char * length}\n#{text}:\n#{char * length}\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'xmpp4r/client'
|
2
|
+
require 'erb'
|
3
|
+
require 'exceptioner/transport/base'
|
4
|
+
require 'exceptioner/transport/helper'
|
5
|
+
|
6
|
+
module Exceptioner::Transport
|
7
|
+
|
8
|
+
class Jabber < Base
|
9
|
+
|
10
|
+
cattr_accessor :jabber_id
|
11
|
+
|
12
|
+
cattr_accessor :password
|
13
|
+
|
14
|
+
def self.deliver(exception, options = {})
|
15
|
+
connect
|
16
|
+
messages = prepare_messages(exception, options)
|
17
|
+
messages.each do |message|
|
18
|
+
@client.send(message)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
def self.prepare_messages(exception, message_options)
|
24
|
+
options = message_options.dup
|
25
|
+
options = default_options.merge(options)
|
26
|
+
options[:body] ||= render(exception, message_options)
|
27
|
+
|
28
|
+
messages = []
|
29
|
+
Array(options[:recipients]).each do |recipient|
|
30
|
+
message = ::Jabber::Message.new(recipient, options[:body])
|
31
|
+
message.set_type(:chat)
|
32
|
+
messages << message
|
33
|
+
end
|
34
|
+
messages
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.connect
|
38
|
+
jid = ::Jabber::JID.new(self.jabber_id)
|
39
|
+
@client = ::Jabber::Client.new(jid)
|
40
|
+
@client.connect
|
41
|
+
@client.auth(self.password)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'mail'
|
2
|
+
require 'erb'
|
3
|
+
require 'exceptioner/transport/base'
|
4
|
+
require 'exceptioner/transport/helper'
|
5
|
+
|
6
|
+
module Exceptioner::Transport
|
7
|
+
|
8
|
+
class Mail < Base
|
9
|
+
DEFAULT_SENDER_ADDRESS = 'exceptioner@exceptioner.net'
|
10
|
+
|
11
|
+
cattr_accessor :delivery_method
|
12
|
+
|
13
|
+
cattr_accessor :delivery_options
|
14
|
+
|
15
|
+
def self.deliver(exception, options = {})
|
16
|
+
mail = prepare_mail(exception, options)
|
17
|
+
mail.deliver
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.determine_mail_options(exception, mail_options)
|
21
|
+
options = {}
|
22
|
+
options[:from] ||= options[:sender]
|
23
|
+
options[:to] ||= options[:recipients]
|
24
|
+
options[:subject] ||= prefixed_subject(exception, options)
|
25
|
+
options[:body] ||= render(exception, mail_options)
|
26
|
+
options.merge!(default_options)
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
def self.default_options
|
31
|
+
super.merge(
|
32
|
+
:delivery_method => delivery_method,
|
33
|
+
:delivery_options => delivery_options,
|
34
|
+
:sender => DEFAULT_SENDER_ADDRESS
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.prepare_mail(exception, mail_options)
|
39
|
+
options = mail_options.dup
|
40
|
+
options = default_options.merge(options)
|
41
|
+
options[:subject] ||= prefixed_subject(exception, options)
|
42
|
+
options[:body] ||= render(exception, mail_options)
|
43
|
+
|
44
|
+
mail = ::Mail.new(
|
45
|
+
:from => options[:sender],
|
46
|
+
:to => options[:recipients],
|
47
|
+
:subject => options[:subject],
|
48
|
+
:body => options[:body]
|
49
|
+
)
|
50
|
+
mail.delivery_method(options[:delivery_method], options[:delivery_options]) if options[:delivery_method]
|
51
|
+
mail
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Application raised <%= exception.class %>
|
2
|
+
<% if options[:controller] %>
|
3
|
+
from <%= options[:controller].controller_name %>#<%= options[:controller].action_name %>
|
4
|
+
<% end %>.
|
5
|
+
|
6
|
+
Message: <%= exception.message.to_s %>.
|
7
|
+
|
8
|
+
<%= Exceptioner::Transport::Helper.title('Backtrace') %>
|
9
|
+
|
10
|
+
<%= exception.backtrace.join("\n\t") %>
|
11
|
+
|
12
|
+
|
13
|
+
<% if options[:env] %>
|
14
|
+
<%= Exceptioner::Transport::Helper.title('Environment') %>
|
15
|
+
|
16
|
+
<%= Exceptioner::Transport::Helper.format_env(options[:env]) %>
|
17
|
+
<% end %>
|
18
|
+
|
data/lib/exceptioner.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'exceptioner/core_ext/class/attribute_accessors'
|
2
|
+
require 'exceptioner/core_ext/module/attribute_accessors'
|
3
|
+
require 'exceptioner/railtie' if defined?(Rails::Railtie)
|
4
|
+
|
5
|
+
module Exceptioner
|
6
|
+
|
7
|
+
class ExceptionerError < StandardError; end
|
8
|
+
|
9
|
+
autoload :Middleware, 'exceptioner/middleware'
|
10
|
+
autoload :ActionController, 'exceptioner/action_controller'
|
11
|
+
|
12
|
+
module Transport
|
13
|
+
autoload :Mail, 'exceptioner/transport/mail/mail'
|
14
|
+
autoload :Jabber, 'exceptioner/transport/jabber/jabber'
|
15
|
+
end
|
16
|
+
|
17
|
+
# Define how to deliver exceptions data.
|
18
|
+
# For example :mail, :jabber, :irc
|
19
|
+
mattr_accessor :transports
|
20
|
+
@@transports = [:mail]
|
21
|
+
|
22
|
+
# If true exceptions raised by local requests will be delivered
|
23
|
+
# Note it is Rails 2.x specific setting
|
24
|
+
mattr_accessor :dispatch_local_requests
|
25
|
+
@@dispatch_local_requests = false
|
26
|
+
|
27
|
+
def self.setup
|
28
|
+
yield self
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.mail
|
32
|
+
Transport::Mail
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.jabber
|
36
|
+
Transport::Jabber
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Exceptioner
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
desc 'Copy Exceptioner default files'
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
def copy_initializers
|
8
|
+
copy_file 'exceptioner.rb', 'config/initializers/exceptioner.rb'
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Use this setup block to configure options available in Exceptioner
|
2
|
+
Exceptioner.setup do |config|
|
3
|
+
|
4
|
+
# Define how to deliver information about exception
|
5
|
+
# Available options are: email
|
6
|
+
# config.transports = [:mail]
|
7
|
+
|
8
|
+
# ### The section below regards mail transport only ###
|
9
|
+
|
10
|
+
# Set message recipients
|
11
|
+
# config.mail.recipients = %w[bofh@yourapp.com dev@yourapp.com]
|
12
|
+
|
13
|
+
# Set delivery method and options.
|
14
|
+
# Values are forwarded to underlying mail gem
|
15
|
+
# To see available options visit https://github.com/mikel/mail
|
16
|
+
# config.mail.delivery_method = :smtp
|
17
|
+
# config.mail.delivery_options = { :address => 'smtp.example.com' }
|
18
|
+
|
19
|
+
# Custom FROM header
|
20
|
+
# config.mail.sender = 'exceptions@yourapp.com'
|
21
|
+
|
22
|
+
# Custom subject
|
23
|
+
# Note that prefix is appended to subject.
|
24
|
+
# If you want to get rid of prefix just set it to nil
|
25
|
+
# config.mail.subject = 'OMG Exception occurred in myapp.com'
|
26
|
+
|
27
|
+
# Prefix prepended to email subject
|
28
|
+
# config.mail.prefix = '[ERROR] '
|
29
|
+
|
30
|
+
|
31
|
+
# ### The section below regards jabber/xmpp transport only ###
|
32
|
+
|
33
|
+
# List JIDs which we'll delivery exceptions to
|
34
|
+
# config.jabber.recipients = %w[jid@jabber.org myname@gmail.com]
|
35
|
+
|
36
|
+
# Following settings are currently REQUIRED.
|
37
|
+
# We have to log in as user with following credentials:
|
38
|
+
|
39
|
+
# Sender's JID
|
40
|
+
# config.jabber.jabber_id = 'server@jabber.org'
|
41
|
+
|
42
|
+
# Sender's password
|
43
|
+
# conifg.jabber.password = 'SECRETXXX'
|
44
|
+
|
45
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: exceptioner
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- "Micha\xC5\x82 \xC5\x81omnicki"
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-12-14 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
31
|
+
version: 1.2.9
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: mail
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 2
|
43
|
+
- 2
|
44
|
+
version: "2.2"
|
45
|
+
type: :runtime
|
46
|
+
version_requirements: *id002
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: xmpp4r
|
49
|
+
prerelease: false
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
- 5
|
57
|
+
version: "0.5"
|
58
|
+
type: :runtime
|
59
|
+
version_requirements: *id003
|
60
|
+
description: |-
|
61
|
+
The most common use is to use Exceptioner as rack middleware and send notifications when an exception occur in you web application. It may be used with Rails, Sinatra or any other rack citizen.
|
62
|
+
Exceptioner may be also used with any ruby code you want. Just configure delivery methods and don't miss any exception.
|
63
|
+
email: michal@lomnicki.com.pl
|
64
|
+
executables: []
|
65
|
+
|
66
|
+
extensions: []
|
67
|
+
|
68
|
+
extra_rdoc_files:
|
69
|
+
- LICENSE
|
70
|
+
- README.rdoc
|
71
|
+
files:
|
72
|
+
- .document
|
73
|
+
- .gitignore
|
74
|
+
- LICENSE
|
75
|
+
- README.rdoc
|
76
|
+
- Rakefile
|
77
|
+
- VERSION
|
78
|
+
- exceptioner.gemspec
|
79
|
+
- init.rb
|
80
|
+
- lib/exceptioner.rb
|
81
|
+
- lib/exceptioner/action_controller.rb
|
82
|
+
- lib/exceptioner/core_ext/class/attribute_accessors.rb
|
83
|
+
- lib/exceptioner/core_ext/module/attribute_accessors.rb
|
84
|
+
- lib/exceptioner/middleware.rb
|
85
|
+
- lib/exceptioner/notifier.rb
|
86
|
+
- lib/exceptioner/railtie.rb
|
87
|
+
- lib/exceptioner/transport/base.rb
|
88
|
+
- lib/exceptioner/transport/helper.rb
|
89
|
+
- lib/exceptioner/transport/jabber/jabber.rb
|
90
|
+
- lib/exceptioner/transport/mail/mail.rb
|
91
|
+
- lib/exceptioner/transport/templates/exception.erb
|
92
|
+
- lib/generators/exceptioner/USAGE
|
93
|
+
- lib/generators/exceptioner/install_generator.rb
|
94
|
+
- lib/generators/exceptioner/templates/exceptioner.rb
|
95
|
+
- spec/exceptioner_spec.rb
|
96
|
+
- spec/spec.opts
|
97
|
+
- spec/spec_helper.rb
|
98
|
+
has_rdoc: true
|
99
|
+
homepage: http://github.com/mlomnicki/exceptioner
|
100
|
+
licenses: []
|
101
|
+
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options:
|
104
|
+
- --charset=UTF-8
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
segments:
|
112
|
+
- 0
|
113
|
+
version: "0"
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
121
|
+
requirements: []
|
122
|
+
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 1.3.6
|
125
|
+
signing_key:
|
126
|
+
specification_version: 3
|
127
|
+
summary: Be notified about exceptions by various transports Email, Jabber, RSS. Choose the option you want
|
128
|
+
test_files:
|
129
|
+
- spec/exceptioner_spec.rb
|
130
|
+
- spec/spec_helper.rb
|