rusen 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rusen.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rusen/settings'
2
+ require 'rusen/notifier'
3
+ #require 'rusen/notification'
4
+
5
+ module Rusen
6
+
7
+ @settings = Settings.new
8
+ @notifier = Notifier.new(@settings)
9
+
10
+ def self.settings
11
+ @settings
12
+ end
13
+
14
+ def self.notify(exception, request = nil, environment = nil, session = nil)
15
+ @notifier.notify(exception, request, environment, session)
16
+ end
17
+
18
+ end
@@ -0,0 +1,38 @@
1
+ require 'rusen/settings'
2
+ require 'rusen/notifier'
3
+ require 'rusen/notification'
4
+
5
+ module Rusen
6
+ module Middleware
7
+
8
+ class RusenRack
9
+ def initialize(app, settings = {})
10
+ @app = app
11
+
12
+ @rusen_settings = Settings.new
13
+
14
+ @rusen_settings.outputs = settings[:outputs]
15
+ @rusen_settings.sections = settings[:sections]
16
+ @rusen_settings.email_prefix = settings[:email_prefix]
17
+ @rusen_settings.sender_address = settings[:sender_address]
18
+ @rusen_settings.exception_recipients = settings[:exception_recipients]
19
+ @rusen_settings.smtp_settings = settings[:smtp_settings]
20
+
21
+ @notifier = Notifier.new(@rusen_settings)
22
+ end
23
+
24
+ def call(env)
25
+ begin
26
+ @app.call(env)
27
+ rescue Exception => error
28
+ request = Rack::Request.new(env)
29
+
30
+ @notifier.notify(error, request.GET.merge(request.POST), env, request.session)
31
+
32
+ raise
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ module Rusen
2
+
3
+ class Notification
4
+
5
+ attr_reader :exception, :request, :environment, :session
6
+
7
+ def initialize(exception, request = nil, environment = nil, session = nil)
8
+ @exception = exception
9
+ @request = request || {}
10
+ @environment = environment || {}
11
+ @session = session || {}
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,41 @@
1
+ require 'rusen/notification'
2
+ require 'rusen/notifiers/io_notifier'
3
+ require 'rusen/notifiers/email_notifier'
4
+
5
+ module Rusen
6
+
7
+ class Notifier
8
+
9
+ def initialize(settings)
10
+ @settings = settings
11
+
12
+ @notifiers = []
13
+ Notifiers.constants.each do |constant|
14
+ klass = Notifiers.const_get(constant)
15
+ if @settings.outputs.include?(klass.identification_symbol)
16
+ register(klass)
17
+ end
18
+ end
19
+ end
20
+
21
+ def register(notifier_class)
22
+ @notifiers << notifier_class.new(@settings)
23
+ end
24
+
25
+ def notify(exception, request = nil, environment = nil, session = nil)
26
+ begin
27
+ notification = Notification.new(exception, request, environment, session)
28
+
29
+ @notifiers.each do |notifier|
30
+ notifier.notify(notification)
31
+ end
32
+
33
+ # We need to ignore all the exceptions thrown by the notifiers.
34
+ rescue Exception
35
+ ERROR("Rusen: Some or all the notifiers failed to sent the notification.")
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,58 @@
1
+ require 'pony'
2
+ require 'erb'
3
+
4
+ module Rusen
5
+ module Notifiers
6
+
7
+ class EmailNotifier
8
+
9
+ def self.identification_symbol
10
+ :email
11
+ end
12
+
13
+ def initialize(settings)
14
+ @settings = settings
15
+ end
16
+
17
+ def notify(notification)
18
+ begin
19
+ @notification = notification
20
+
21
+ Pony.mail(email_options.merge({:body => build_body}))
22
+
23
+ # We need to ignore all the exceptions thrown by EmailNotifier.notify.
24
+ rescue Exception => e
25
+ ERROR("Rusen: #{e.message} prevented the notification email from being sent.")
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def email_options
32
+ {
33
+ :to => @settings.exception_recipients,
34
+ :via => :smtp,
35
+ :charset => 'utf-8',
36
+ :from => @settings.sender_address,
37
+ :headers => { 'Content-Type' => 'text/html' },
38
+ :via_options => @settings.smtp_settings,
39
+ :subject => email_subject.force_encoding('UTF-8')
40
+ }
41
+ end
42
+
43
+ def email_subject
44
+ @settings.email_prefix + "#{@notification.exception.class}: #{@notification.exception.message}"
45
+ end
46
+
47
+ def build_body
48
+ template_path = File.expand_path('../../templates/email_template.html.erb', __FILE__)
49
+
50
+ template = File.open(template_path).read
51
+ rhtml = ERB.new(template)
52
+ rhtml.result(binding)
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,67 @@
1
+ module Rusen
2
+ module Notifiers
3
+
4
+ class IONotifier
5
+
6
+ STDOUT = $stdout
7
+
8
+ def self.identification_symbol
9
+ :io
10
+ end
11
+
12
+ def initialize(settings, output = STDOUT)
13
+ @settings = settings
14
+ @output = output
15
+ end
16
+
17
+ def notify(notification)
18
+ begin
19
+ if @settings.sections.include?(:backtrace)
20
+
21
+ print_title('Backtrace')
22
+
23
+ @output.puts notification.exception.message
24
+ @output.puts notification.exception.backtrace
25
+ end
26
+
27
+ if @settings.sections.include?(:request)
28
+ print_title('Request')
29
+
30
+ print_hash(notification.request)
31
+ end
32
+
33
+ if @settings.sections.include?(:session)
34
+ print_title('Session')
35
+
36
+ print_hash(notification.session)
37
+ end
38
+
39
+ if @settings.sections.include?(:environment)
40
+ print_title('Environment')
41
+
42
+ print_hash(notification.environment)
43
+ end
44
+
45
+ # We need to ignore all the exceptions thrown by IONotifier.notify.
46
+ rescue Exception => e
47
+ ERROR("Rusen: #{e.message} prevented the io notifier from login the error.")
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def print_title(title)
54
+ @output.puts '-------------------------------'
55
+ @output.puts "#{title}:"
56
+ @output.puts '-------------------------------'
57
+ end
58
+
59
+ def print_hash(hash)
60
+ hash.each.each do |k, v|
61
+ @output.puts "#{k}\t\t\t#{v}"
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,38 @@
1
+ module Rusen
2
+
3
+ class Settings
4
+
5
+ attr_writer :outputs
6
+ attr_writer :email_prefix
7
+ attr_writer :sender_address
8
+ attr_writer :exception_recipients
9
+ attr_writer :sections
10
+ attr_writer :smtp_settings
11
+
12
+ def outputs
13
+ @outputs || [:io, :email]
14
+ end
15
+
16
+ def email_prefix
17
+ @email_prefix || '[Exception] '
18
+ end
19
+
20
+ def sender_address
21
+ @sender_address || ''
22
+ end
23
+
24
+ def exception_recipients
25
+ @exception_recipients || []
26
+ end
27
+
28
+ def sections
29
+ @sections || [:backtrace, :request, :session, :environment]
30
+ end
31
+
32
+ def smtp_settings
33
+ @smtp_settings || {}
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,77 @@
1
+ <%= @notification.exception.class %>: <%= @notification.exception.message %>
2
+
3
+ <% if @settings.sections.include?(:backtrace) %>
4
+ <table style="border-collapse: collapse; border-spacing: 0; width: 100%; border: double; margin-bottom: 10px;">
5
+ <thead style="background-color: #EFEFEF; font-size: 10pt; font-weight: bold;">
6
+ <tr>
7
+ <td><h4>Backtrace:</h4></td>
8
+ <td></td>
9
+ </tr>
10
+ </thead>
11
+ <tbody style="font-size: 11pt;">
12
+ <% @notification.exception.backtrace.each do |backtrace_step| %>
13
+ <tr>
14
+ <td style="border: solid 1px #000000; margin: 0; padding: 4pt 6pt;"><%= backtrace_step %></td>
15
+ </tr>
16
+ <% end %>
17
+ </tbody>
18
+ </table>
19
+ <% end %>
20
+
21
+ <% if @settings.sections.include?(:request) %>
22
+ <table style="border-collapse: collapse; border-spacing: 0; width: 100%; border: double; margin-bottom: 10px;">
23
+ <thead style="background-color: #EFEFEF; font-size: 10pt; font-weight: bold;">
24
+ <tr>
25
+ <td><h4>Request:</h4></td>
26
+ <td></td>
27
+ </tr>
28
+ </thead>
29
+ <tbody style="font-size: 11pt;">
30
+ <% @notification.request.each do |k, v| %>
31
+ <tr>
32
+ <td style="border: solid 1px #000000; margin: 0; padding: 4pt 6pt;"><%= k %></td>
33
+ <td style="border: solid 1px #000000; margin: 0; padding: 4pt 6pt;"><%= v %></td>
34
+ </tr>
35
+ <% end %>
36
+ </tbody>
37
+ </table>
38
+ <% end %>
39
+
40
+ <% if @settings.sections.include?(:session) %>
41
+ <table style="border-collapse: collapse; border-spacing: 0; width: 100%; border: double; margin-bottom: 10px;">
42
+ <thead style="background-color: #EFEFEF; font-size: 10pt; font-weight: bold;">
43
+ <tr>
44
+ <td><h4>Session:</h4></td>
45
+ <td></td>
46
+ </tr>
47
+ </thead>
48
+ <tbody style="font-size: 11pt;">
49
+ <% @notification.session.each do |k, v| %>
50
+ <tr>
51
+ <td style="border: solid 1px #000000; margin: 0; padding: 4pt 6pt;"><%= k %></td>
52
+ <td style="border: solid 1px #000000; margin: 0; padding: 4pt 6pt;"><%= v %></td>
53
+ </tr>
54
+ <% end %>
55
+ </tbody>
56
+ </table>
57
+ <% end %>
58
+
59
+
60
+ <% if @settings.sections.include?(:environment) %>
61
+ <table style="border-collapse: collapse; border-spacing: 0; width: 100%; border: double; margin-bottom: 10px;">
62
+ <thead style="background-color: #EFEFEF; font-size: 10pt; font-weight: bold;">
63
+ <tr>
64
+ <td><h4>Environment:</h4></td>
65
+ <td></td>
66
+ </tr>
67
+ </thead>
68
+ <tbody style="font-size: 11pt;">
69
+ <% @notification.environment.each do |k, v| %>
70
+ <tr>
71
+ <td style="border: solid 1px #000000; margin: 0; padding: 4pt 6pt;"><%= k %></td>
72
+ <td style="border: solid 1px #000000; margin: 0; padding: 4pt 6pt;"><%= v %></td>
73
+ </tr>
74
+ <% end %>
75
+ </tbody>
76
+ </table>
77
+ <% end %>
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rusen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Adrian Gomez
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pony
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: simplecov
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: ! "RUby Simple Exception Notification (a.k.a. rusen) as it names indicates
63
+ is a\n simple exception notification for ruby."
64
+ email: adri4n.gomez@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - lib/rusen.rb
70
+ - lib/rusen/templates/email_template.html.erb
71
+ - lib/rusen/notifier.rb
72
+ - lib/rusen/settings.rb
73
+ - lib/rusen/notifiers/io_notifier.rb
74
+ - lib/rusen/notifiers/email_notifier.rb
75
+ - lib/rusen/notification.rb
76
+ - lib/rusen/middleware/rusen_rack.rb
77
+ homepage: https://github.com/Moove-it/rusen
78
+ licenses: []
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 1.8.23
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: RUby Simple Exception Notification
101
+ test_files: []