rnotifier 0.0.2
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.
- data/.gitignore +17 -0
- data/Gemfile +6 -0
- data/README.md +11 -0
- data/Rakefile +2 -0
- data/lib/generators/rnotifier/rnotifier_generator.rb +23 -0
- data/lib/generators/rnotifier/templates/initializer.rb +5 -0
- data/lib/rnotifier/configuration.rb +49 -0
- data/lib/rnotifier/email_notifier.rb +19 -0
- data/lib/rnotifier/notifier.rb +58 -0
- data/lib/rnotifier/rails_exception.rb +49 -0
- data/lib/rnotifier/rlogger.rb +27 -0
- data/lib/rnotifier/util.rb +29 -0
- data/lib/rnotifier/version.rb +3 -0
- data/lib/rnotifier/views/email_notifier/exception_notify.html.erb +29 -0
- data/lib/rnotifier.rb +15 -0
- data/rnotifier.gemspec +19 -0
- metadata +96 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
class RnotifierGenerator < Rails::Generators::Base
|
2
|
+
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
class_option :api_key, :aliases => '-k', :type => :string, :desc => 'Rnotifier API key.'
|
5
|
+
|
6
|
+
def add_config
|
7
|
+
if options[:api_key]
|
8
|
+
template 'initializer.rb', 'config/initializers/rnotifier.rb'
|
9
|
+
p "******* INFO *************"
|
10
|
+
p "Set exception recipients email address in 'config/initializers/rnotifier.rb'"
|
11
|
+
p "i.e. c.exception_recipients => %w{user1@example.com, user2@example.com} "
|
12
|
+
else
|
13
|
+
p 'Set option --api-key or -k.'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def api_key
|
19
|
+
"'#{options[:api_key]}'"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rnotifier
|
2
|
+
class Configuration
|
3
|
+
DEFAULT_CONFIG = {
|
4
|
+
:api_host => 'http://rnotifier.com/notify/api/v1',
|
5
|
+
:validate_path => 'validate',
|
6
|
+
:notify_path => 'exception'
|
7
|
+
}
|
8
|
+
|
9
|
+
FILTER_PARAMS = ['password', 'password_confirmation']
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :api_key
|
13
|
+
attr_accessor :client_ip
|
14
|
+
attr_accessor :client_host_name
|
15
|
+
attr_accessor :is_valid
|
16
|
+
attr_accessor :filter_params
|
17
|
+
attr_accessor :notification_server
|
18
|
+
attr_accessor :exception_recipients
|
19
|
+
|
20
|
+
def [](key)
|
21
|
+
DEFAULT_CONFIG[key] || send(key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_config
|
25
|
+
|
26
|
+
unless self.notification_server
|
27
|
+
self.notification_server = DEFAULT_CONFIG[:api_host]
|
28
|
+
else
|
29
|
+
self.notification_server += '/notify/api/v1'
|
30
|
+
end
|
31
|
+
|
32
|
+
if self.api_key
|
33
|
+
response = Util.get(self[:validate_path])
|
34
|
+
self.is_valid = true if response['valid_api_key']
|
35
|
+
else
|
36
|
+
Rlogger.error('[CONFIG] Check your config API key is not define.')
|
37
|
+
end
|
38
|
+
|
39
|
+
unless self.is_valid
|
40
|
+
Rlogger.error('[CONFIG] Invalid API KEY. Please check it.')
|
41
|
+
else
|
42
|
+
Rlogger.info('[CONFIG] API key is valid.')
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rnotifier
|
2
|
+
class EmailNotifier < ActionMailer::Base
|
3
|
+
default :from => 'Rnotifier Exception<exception@rnotifier.in>'
|
4
|
+
self.mailer_name = 'email_notifier'
|
5
|
+
self.append_view_path "#{File.dirname(__FILE__)}/views"
|
6
|
+
|
7
|
+
def exception_notify(exception)
|
8
|
+
@exception = exception
|
9
|
+
@project_name = Rails.application.class.to_s.sub('::Application', '')
|
10
|
+
|
11
|
+
emails = Configuration.exception_recipients
|
12
|
+
subject = "[RNOTIFIER][#{@project_name}##{@exception[:environment]}] #{@exception[:message]}"
|
13
|
+
|
14
|
+
mail(:to => emails, :subject => subject) do |format|
|
15
|
+
format.html { render "#{mailer_name}/exception_notify" }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Rnotifier
|
2
|
+
class Notifier
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def config(&block)
|
6
|
+
yield(Rnotifier::Configuration)
|
7
|
+
Configuration.validate_config rescue Rlogger.error('[CONFIG] Error from notification server.')
|
8
|
+
|
9
|
+
#Initialize Rails Exception handler
|
10
|
+
Rnotifier::RailsException.initialize if Configuration.is_valid
|
11
|
+
|
12
|
+
Configuration.filter_params ||= []
|
13
|
+
|
14
|
+
if Configuration.filter_params.empty?
|
15
|
+
Configuration.filter_params.concat(Configuration::FILTER_PARAMS)
|
16
|
+
end
|
17
|
+
|
18
|
+
Configuration.freeze
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_exception(exception_data)
|
22
|
+
exception_data[:params] = filter_params(exception_data[:params])
|
23
|
+
exception_data[:occurred_at] = Time.now
|
24
|
+
|
25
|
+
t = Thread.new do
|
26
|
+
begin
|
27
|
+
response = Util.post(Configuration[:notify_path], {:exception_data => exception_data})
|
28
|
+
|
29
|
+
Rlogger.error("[SEND] #{response['message']}") unless response['notify']
|
30
|
+
rescue Exception => e
|
31
|
+
Rlogger.error("[SERVER] #{e.message}")
|
32
|
+
Rlogger.error("[SERVER] #{e.backtrace}")
|
33
|
+
end
|
34
|
+
send_email_notification(exception_data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def send_email_notification(exception_data)
|
39
|
+
begin
|
40
|
+
EmailNotifier.exception_notify(exception_data).deliver
|
41
|
+
rescue Exception => e
|
42
|
+
Rlogger.error("[MAILER] #{e.message}")
|
43
|
+
Rlogger.error("[MAILER] #{e.backtrace}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def filter_params(params = {})
|
48
|
+
return if params.empty?
|
49
|
+
|
50
|
+
Configuration.filter_params.each do |key|
|
51
|
+
params[key] = '[FILTERED]' if params.has_key?(key)
|
52
|
+
end
|
53
|
+
params
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rnotifier
|
2
|
+
module RailsException
|
3
|
+
module Catcher
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.send(:alias_method, :render_exception_without_rnotifier, :render_exception)
|
7
|
+
base.send(:alias_method, :render_exception, :render_exception_with_rnotifier)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
def render_exception_with_rnotifier(env,exception)
|
12
|
+
request = ActionDispatch::Request.new(env)
|
13
|
+
unless (@consider_all_requests_local || request.local?)
|
14
|
+
exception_data = {
|
15
|
+
:url => request.url,
|
16
|
+
:params => request.params,
|
17
|
+
:session => request.session,
|
18
|
+
:ip => request.ip,
|
19
|
+
:http_method => request.method,
|
20
|
+
:status_code => status_code(exception),
|
21
|
+
:class_name => exception.class.to_s,
|
22
|
+
:message => exception.message,
|
23
|
+
:exception_line => Rails.backtrace_cleaner.clean(exception.backtrace, :silent).first,
|
24
|
+
:backtrace => Rails.backtrace_cleaner.clean(exception.backtrace, nil),
|
25
|
+
:environment => Rails.env.capitalize,
|
26
|
+
:user_agent => request.user_agent
|
27
|
+
}
|
28
|
+
|
29
|
+
exception_data[:session].delete('session_id')
|
30
|
+
exception_data[:exception_hash] = Digest::MD5.hexdigest(exception_data[:message].gsub(/#<\w*:\w*>/, '') +
|
31
|
+
exception_data[:exception_line])
|
32
|
+
exception_data[:env_variables] = Util.request_env(request.filtered_env)
|
33
|
+
|
34
|
+
Notifier.send_exception(exception_data)
|
35
|
+
end
|
36
|
+
|
37
|
+
render_exception_without_rnotifier(env, exception)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.initialize
|
43
|
+
if defined?(ActionDispatch::ShowExceptions)
|
44
|
+
Configuration.filter_params = Rails.application.config.filter_parameters.uniq
|
45
|
+
ActionDispatch::ShowExceptions.send(:include, Rnotifier::RailsException::Catcher)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rnotifier
|
2
|
+
class Rlogger
|
3
|
+
|
4
|
+
LOG_TITLE = '[RNOTIFIER]'
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def info(msg)
|
9
|
+
logger.info("#{LOG_TITLE}#{msg}")
|
10
|
+
end
|
11
|
+
|
12
|
+
def error(msg)
|
13
|
+
logger.error("#{LOG_TITLE}#{msg}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def warn(msg)
|
17
|
+
logger.warn("#{LOG_TITLE}#{msg}")
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def logger
|
22
|
+
@rlogger ||= (defined?(Rails.logger) ? Rails.logger : Logger.new(STDERR))
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Rnotifier
|
2
|
+
class Util
|
3
|
+
class << self
|
4
|
+
def post(path, data = {})
|
5
|
+
url = URI.parse(Configuration.notification_server)
|
6
|
+
post = Net::HTTP::Post.new("#{url.path}/#{path}/#{Configuration[:api_key]}",{'Content-Type' =>'application/json'})
|
7
|
+
|
8
|
+
http = Net::HTTP.new(url.host, url.port)
|
9
|
+
http.use_ssl = true if url.port == 443
|
10
|
+
JSON.parse(http.request(post, data.to_json).body)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(path, params = {})
|
14
|
+
url = "#{Configuration.notification_server}/#{path}/#{Configuration[:api_key]}"
|
15
|
+
JSON.parse(Net::HTTP.get(URI.parse(url)))
|
16
|
+
end
|
17
|
+
|
18
|
+
def request_env(env)
|
19
|
+
env_hash = env.reject{|k,v| k.include?('action') || k.include?('rack')}
|
20
|
+
env_hash.delete('HTTP_COOKIE')
|
21
|
+
env_hash['HOSTNAME'] = Socket.gethostname
|
22
|
+
|
23
|
+
env_hash.to_json
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'>
|
5
|
+
</head>
|
6
|
+
<body style='color:#333;font-size:14px;margin-top:30px;'>
|
7
|
+
<span style='font-size:15px;'>
|
8
|
+
<strong style='margin-right:45px;'>Project</strong> : <%= @project_name %>
|
9
|
+
<br/>
|
10
|
+
<strong style='margin-right:5px;'>Environment</strong> : <%= @exception[:environment] %>
|
11
|
+
</span>
|
12
|
+
<div style='border:2px solid #FBC7C6;padding:10px 15px;margin-top:20px;'>
|
13
|
+
<p style='font-weight:bold'>
|
14
|
+
Exception: <%= @exception[:message] %>
|
15
|
+
</p>
|
16
|
+
<p>
|
17
|
+
<strong>Action : </strong><%= "#{@exception[:params][:controller]}##{@exception[:params][:action]}" %>
|
18
|
+
</p>
|
19
|
+
<p>
|
20
|
+
<strong>Exception Line : </strong><%= @exception[:exception_line] %>
|
21
|
+
</p>
|
22
|
+
<p>
|
23
|
+
<strong>Occurred at : </strong><%= @exception[:occurred_at] %> </p>
|
24
|
+
<p>
|
25
|
+
<strong>Request Url : </strong><%= "#{@exception[:http_method]} #{@exception[:url]}" %>
|
26
|
+
</p>
|
27
|
+
</div>
|
28
|
+
</body>
|
29
|
+
</html>
|
data/lib/rnotifier.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rnotifier/version'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
require 'logger'
|
5
|
+
require 'action_mailer'
|
6
|
+
|
7
|
+
module Rnotifier
|
8
|
+
autoload :Notifier, 'rnotifier/notifier'
|
9
|
+
autoload :Configuration, 'rnotifier/configuration'
|
10
|
+
autoload :RailsException, 'rnotifier/rails_exception'
|
11
|
+
autoload :EmailNotifier, 'rnotifier/email_notifier'
|
12
|
+
autoload :Util, 'rnotifier/util'
|
13
|
+
autoload :Rlogger, 'rnotifier/rlogger'
|
14
|
+
end
|
15
|
+
|
data/rnotifier.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/rnotifier/version', __FILE__)
|
3
|
+
#require "rnotifier/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.authors = ["Jiren Patel"]
|
7
|
+
gem.email = ["jiren@joshsoftware.com"]
|
8
|
+
gem.description = %q{Rails 3 Exception catcher}
|
9
|
+
gem.summary = %q{Rails 3 Exception catcher}
|
10
|
+
gem.homepage = "https://github.com/jiren/rnotifier"
|
11
|
+
|
12
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
13
|
+
gem.files = `git ls-files`.split("\n")
|
14
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
gem.name = "rnotifier"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = Rnotifier::VERSION
|
18
|
+
gem.add_dependency('json', '>= 1.5.3')
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rnotifier
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jiren Patel
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-11-18 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
22
|
+
none: false
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
hash: 5
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 5
|
30
|
+
- 3
|
31
|
+
version: 1.5.3
|
32
|
+
prerelease: false
|
33
|
+
requirement: *id001
|
34
|
+
type: :runtime
|
35
|
+
name: json
|
36
|
+
description: Rails 3 Exception catcher
|
37
|
+
email:
|
38
|
+
- jiren@joshsoftware.com
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- .gitignore
|
47
|
+
- Gemfile
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- lib/generators/rnotifier/rnotifier_generator.rb
|
51
|
+
- lib/generators/rnotifier/templates/initializer.rb
|
52
|
+
- lib/rnotifier.rb
|
53
|
+
- lib/rnotifier/configuration.rb
|
54
|
+
- lib/rnotifier/email_notifier.rb
|
55
|
+
- lib/rnotifier/notifier.rb
|
56
|
+
- lib/rnotifier/rails_exception.rb
|
57
|
+
- lib/rnotifier/rlogger.rb
|
58
|
+
- lib/rnotifier/util.rb
|
59
|
+
- lib/rnotifier/version.rb
|
60
|
+
- lib/rnotifier/views/email_notifier/exception_notify.html.erb
|
61
|
+
- rnotifier.gemspec
|
62
|
+
homepage: https://github.com/jiren/rnotifier
|
63
|
+
licenses: []
|
64
|
+
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.8.11
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Rails 3 Exception catcher
|
95
|
+
test_files: []
|
96
|
+
|