denouncer 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0d9585cf186ffdb08fc942cddf41d041f1296206
4
+ data.tar.gz: de1fab455ae3ae74db81b561b99d06bc32e945cc
5
+ SHA512:
6
+ metadata.gz: 8498a42f1f5aa436c0f0b567caa64da06a624360fdbe3c6eefefc59c434bf6b0819716d3852c40593fdb27ead6d540e24dfbeeaa39b67d0321bda470553a2af4
7
+ data.tar.gz: ec63e2488edf124098f3c2e64c59293d0c4dd62b093b4e32db555927033107921cd6b78cd181eadb59413322a1d644afb6d887f06ea027c89ff79e10626d5501
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ test_example.txt
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Julian Weber
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.
@@ -0,0 +1,140 @@
1
+ # Denouncer
2
+
3
+ Denouncer allows you to send notifications for occuring errors within your ruby applications.
4
+ Right now it supports SMTP to send mail notifications with error details.
5
+ The gem is designed to be extendable and provides a simple interface to implement other notification
6
+ methods.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'denouncer'
13
+
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install denouncer
22
+
23
+ ## Configuration
24
+
25
+ The configuration options depend on the chosen Notifier.
26
+ Basic configuration variables are:
27
+ * application_name - the name of your application (required)
28
+
29
+ ### Console Notifier
30
+
31
+ The ConsoleNotifier is just for testing and demo purposes. It prints out exception details on the command line.
32
+
33
+ ### SmtpNotifier
34
+
35
+ The STMP notifier sends email messages using the SMTP protocol.
36
+ Set the notifier configuration setting to :smtp to use the SmtpNotifier.
37
+
38
+ Configuration variables are:
39
+ * application_name - the name of your application (required)
40
+ * server - the smtp server address to use (default: localhost)
41
+ * port - the port to use for smtp connections (default: 25)
42
+ * domain - the from domain to use (default: localhost)
43
+ * username - the username for the smtp connection (default: nil)
44
+ * password - the password for the smtp connection (default: nil)
45
+ * authtype - the smtp auth type to use (default: :cram_md5) (:plain, :login or :cram_md5)
46
+ * sender - the sender (from) address to use (required)
47
+ * recipients - an array of recipients for the notifications (required)
48
+
49
+ #### External SMTP server
50
+
51
+ Denouncer uses the Net::SMTP class to send mail. Additional configuration options are described [here](http://ruby-doc.org/stdlib-2.0/libdoc/net/smtp/rdoc/Net/SMTP.html).
52
+ require 'denouncer'
53
+
54
+ Denouncer.configure(
55
+ application_name: 'my_app',
56
+ notifier: :smtp,
57
+ port: 25,
58
+ server: 'mail.example.com',
59
+ sender: 'noreply@example.com',
60
+ username: 'noreply@example.com',
61
+ password: 'your_password',
62
+ recipients: ['usera@example.com', 'userb@example.com'],
63
+ authtype: :plain,
64
+ domain: 'mail.example.com'
65
+ )
66
+
67
+ #### mailcatcher configuration
68
+
69
+ For more information in mailcatcher please refer to their [github repo](https://github.com/sj26/mailcatcher).
70
+
71
+ require 'denouncer'
72
+
73
+ Denouncer.configure(
74
+ application_name: "my_app",
75
+ notifier: :smtp,
76
+ port: 1025,
77
+ server: "localhost",
78
+ sender: "noreply@example.com",
79
+ recipients: ['usera@example.com', 'userb@example.com']
80
+ )
81
+
82
+ ### AmqpNotifier
83
+
84
+ Denouncer uses the bunny gem to send mail. Additional configuration options are described [here](http://reference.rubybunny.info/).
85
+
86
+ #### !!!ATTENTION
87
+
88
+ The bunny gem is required for the AmqpNotifier. Please add the bunny gem to your Gemfile as follows:
89
+
90
+ gem 'bunny'
91
+
92
+ Configuration variables are:
93
+ * application_name - the name of your application (required)
94
+ * server - the amqp server address to use (default: localhost)
95
+ * port - the port to use for amqp connections (default: 5672)
96
+ * username - the username for the amqp connection (default: 'guest')
97
+ * password - the password for the amqp connection (default: 'guest')
98
+ * vhost - the virtual host to use for the amqp connection (default: '/')
99
+ * message_queue - the message queue to use (default: "#{application_name}.errors", e.g. "myapp.errors")
100
+
101
+ #### AMQP Configuration
102
+
103
+ require 'denouncer'
104
+
105
+ Denouncer.configure(
106
+ application_name: "my_app",
107
+ notifier: :amqp,
108
+ port: 5672,
109
+ server: "localhost",
110
+ vhost: "/",
111
+ username: "guest",
112
+ password: "guest",
113
+ message_queue: "my_app.errors"
114
+ )
115
+
116
+ ## Usage
117
+
118
+ The example below shows a basic usage pattern for denouncer notifications.
119
+ Catch exceptions, then use denouncer's notify function and the re-raise the error again.
120
+
121
+ begin
122
+ 1/0
123
+ rescue => err
124
+ Denouncer.notify err, { test: "my metadata 1", test2: "my metadata 2" }
125
+ raise err
126
+ end
127
+
128
+ The metadata is optional and defaults to nil.
129
+
130
+ ## Test Suite
131
+
132
+ bundle exec rspec
133
+
134
+ ## Contributing
135
+
136
+ 1. Fork it ( https://github.com/[my-github-username]/denouncer/fork )
137
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
138
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
139
+ 4. Push to the branch (`git push origin my-new-feature`)
140
+ 5. Create a new Pull Request
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ desc 'Run a pry console session'
4
+ task :console do
5
+ exec("pry -r ./lib/denouncer.rb")
6
+ end
7
+ task c: :console
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'denouncer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "denouncer"
8
+ spec.version = Denouncer::VERSION
9
+ spec.authors = ["Julian Weber"]
10
+ spec.email = ["jweber@anynines.com"]
11
+ spec.summary = %q{Denouncer allows you to send notifications (SMTP, AMQP) with error/exception details using a simple interface.}
12
+ spec.description = %q{Denouncer allows you to send notifications with error/exception details using a simple interface. New methods of sending error messages can be implemented using a pre-defined class interface. SMTP and AMQP notification are the first implemented adapters. Use denouncer to get informed on error occurences instantly.}
13
+ spec.homepage = "http://github.com/julweber/denouncer"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "pry-byebug"
26
+ spec.add_development_dependency "simplecov"
27
+ spec.add_development_dependency "bunny"
28
+ end
@@ -0,0 +1,65 @@
1
+ require "denouncer/version"
2
+
3
+ module Denouncer
4
+ autoload :Notifiers, File.expand_path('../denouncer/notifiers', __FILE__)
5
+
6
+ DEFAULT_NOTIFIER = :smtp
7
+
8
+ @@notifier = nil
9
+
10
+ # Configures denouncer using the specified configuration hash.
11
+ #
12
+ # @param options [Hash] a configuration hash
13
+ def self.configure(options)
14
+ check_base_configuration! options
15
+ if options[:notifier].nil?
16
+ options[:notifier] = DEFAULT_NOTIFIER
17
+ end
18
+ initialize_notifier options
19
+ options
20
+ end
21
+
22
+ def self.reset_configuration
23
+ @@notifier = nil
24
+ end
25
+
26
+ def self.is_configured?
27
+ !notifier.nil?
28
+ end
29
+
30
+ # Returns the current notifier's config or nil if not configured.
31
+ def self.config
32
+ return nil unless is_configured?
33
+ notifier.config
34
+ end
35
+
36
+ # Sends a notification using the configured notifier.
37
+ #
38
+ # @param error [StandardError]
39
+ # @param metadata [Hash]
40
+ def self.notify(error, metadata = nil)
41
+ raise "Denouncer is not configured yet. Please run Denouncer.configure(options) to setup denouncer!" if @@notifier.nil?
42
+ notifier.notify error
43
+ end
44
+
45
+ private
46
+
47
+ def self.notifier
48
+ return @@notifier
49
+ end
50
+
51
+ def self.check_base_configuration!(options)
52
+ raise "Invalid configuration hash: nil" if options.nil?
53
+ raise "Invalid configuration hash: no hash or subclass of hash given" unless options.is_a? Hash
54
+ end
55
+
56
+ def self.initialize_notifier(options)
57
+ case options[:notifier]
58
+ when :smtp then @@notifier = ::Denouncer::Notifiers::SmtpNotifier.new options
59
+ when :console then @@notifier = ::Denouncer::Notifiers::ConsoleNotifier.new options
60
+ when :amqp then @@notifier = ::Denouncer::Notifiers::AmqpNotifier.new options
61
+ else
62
+ raise "Invalid notifier configuration: #{options} is not a valid :notifier setting!"
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,8 @@
1
+ module Denouncer
2
+ module Notifiers
3
+ autoload :BaseNotifier, File.expand_path('../notifiers/base_notifier', __FILE__)
4
+ autoload :ConsoleNotifier, File.expand_path('../notifiers/console_notifier', __FILE__)
5
+ autoload :SmtpNotifier, File.expand_path('../notifiers/smtp_notifier', __FILE__)
6
+ autoload :AmqpNotifier, File.expand_path('../notifiers/amqp_notifier', __FILE__)
7
+ end
8
+ end
@@ -0,0 +1,84 @@
1
+ require 'socket'
2
+ require 'json'
3
+
4
+ module Denouncer
5
+ module Notifiers
6
+ class AmqpNotifier < BaseNotifier
7
+ DEFAULT_PORT = 5672
8
+ DEFAULT_SERVER = 'localhost'
9
+ DEFAULT_VHOST = '/'
10
+ DEFAULT_USERNAME = 'guest'
11
+ DEFAULT_PASSWORD = 'guest'
12
+
13
+ # @raise [StandardError] if the configuration is invalid
14
+ def set_configuration!(options)
15
+ require 'bunny'
16
+ raise "Configuration error: :application_name is not set!" if options[:application_name].nil?
17
+
18
+ options[:server] = DEFAULT_SERVER if options[:server].nil?
19
+ options[:port] = DEFAULT_PORT if options[:port].nil?
20
+ options[:vhost] = DEFAULT_VHOST if options[:vhost].nil?
21
+ options[:username] = DEFAULT_USERNAME if options[:username].nil?
22
+ options[:password] = DEFAULT_PASSWORD if options[:password].nil?
23
+ options[:message_queue] = "#{options[:application_name]}.errors" if options[:errors].nil?
24
+ return options
25
+ end
26
+
27
+ # Sends an error notification via amqp.
28
+ #
29
+ # @param error [StandardError]
30
+ # @param metadata [Hash]
31
+ def notify(error, metadata = nil)
32
+ msg = generate_json_message error, metadata
33
+ send_message_via_amqp msg
34
+ end
35
+
36
+ private
37
+
38
+ def generate_message_hash(error, metadata = nil)
39
+ hostname = Socket.gethostname
40
+ time_now = get_current_timestamp
41
+ {
42
+ notification_time: time_now,
43
+ application_name: config[:application_name],
44
+ hostname: hostname,
45
+ error_class: error.class.name,
46
+ error_backtrace: error.backtrace,
47
+ error_message: error.message,
48
+ error_cause: error.cause,
49
+ metadata: metadata
50
+ }
51
+ end
52
+
53
+ def generate_json_message(error, metadata = nil)
54
+ generate_message_hash(error, metadata).to_json
55
+ end
56
+
57
+ def send_message_via_amqp(message)
58
+ # Start a communication session with RabbitMQ
59
+ connection_hash = {
60
+ host: config[:server],
61
+ vhost: config[:vhost],
62
+ port: config[:port],
63
+ username: config[:username],
64
+ password: config[:password],
65
+ threaded: false
66
+ }
67
+ conn = Bunny.new connection_hash
68
+ conn.start
69
+
70
+ # open a channel
71
+ ch = conn.create_channel
72
+
73
+ # declare a queue
74
+ q = ch.queue(config[:message_queue])
75
+
76
+ # publish a message to the default exchange which then gets routed to this queue
77
+ q.publish(message)
78
+
79
+ # close the connection
80
+ conn.stop
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,34 @@
1
+ require 'time'
2
+
3
+ module Denouncer
4
+ module Notifiers
5
+ class BaseNotifier
6
+ attr_reader :config
7
+
8
+ def initialize(options)
9
+ if options[:application_name].nil? || !options[:application_name].is_a?(String)
10
+ raise "Invalid configuration hash: No valid :application_name given"
11
+ end
12
+ opts = set_configuration!(options).dup
13
+ @config = opts
14
+ end
15
+
16
+ # Returns the current timestamp in utc is8601 format
17
+ def get_current_timestamp
18
+ Time.now.utc.iso8601
19
+ end
20
+
21
+ def set_configuration!(options)
22
+ raise NotImplementedException("This method needs to be implemented in a sub-class!")
23
+ end
24
+
25
+ # Sends a notification.
26
+ #
27
+ # @param error [StandardError]
28
+ # @param metadata [Hash]
29
+ def notify(error, metadata = nil)
30
+ raise NotImplementedException("This method needs to be implemented in a sub-class!")
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ module Denouncer
2
+ module Notifiers
3
+ class ConsoleNotifier < BaseNotifier
4
+
5
+ def set_configuration!(options)
6
+ return options
7
+ end
8
+
9
+ def notify(error, metadata = nil)
10
+ puts "Timestamp: #{get_current_timestamp}"
11
+ puts "Error Class: #{error.class.name}"
12
+ puts "Error Message: #{error.message}"
13
+ puts "Metadata: #{metadata.to_s}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,72 @@
1
+ require 'net/smtp'
2
+ require 'time'
3
+ require 'socket'
4
+
5
+ module Denouncer
6
+ module Notifiers
7
+ class SmtpNotifier < BaseNotifier
8
+ DEFAULT_PORT = 25
9
+ DEFAULT_SERVER = 'localhost'
10
+ DEFAULT_DOMAIN = 'localhost'
11
+
12
+ # @raise [StandardError] if the configuration is invalid
13
+ def set_configuration!(options)
14
+ raise "Configuration error: :application_name is not set!" if options[:application_name].nil?
15
+ raise "SMTP configuration error: #{options[:sender]} is not a valid :sender setting!" if options[:sender].nil? || !options[:sender].is_a?(String)
16
+ raise "SMTP configuration error: :recipients is nil!" if options[:recipients].nil?
17
+
18
+ options[:server] = DEFAULT_SERVER if options[:server].nil?
19
+ options[:port] = DEFAULT_PORT if options[:port].nil?
20
+ options[:domain] = DEFAULT_DOMAIN if options[:domain].nil?
21
+ return options
22
+ end
23
+
24
+ # Sends an error notification via mail.
25
+ #
26
+ # @param error [StandardError]
27
+ # @param metadata [Hash]
28
+ def notify(error, metadata = nil)
29
+ Net::SMTP.start(config[:server], config[:port], config[:domain], config[:username], config[:password], config[:authtype]) do |smtp|
30
+ smtp.send_message generate_text_message(error), config[:sender], config[:recipients]
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def generate_text_message(error, metadata = nil)
37
+ hostname = Socket.gethostname
38
+ time_now = get_current_timestamp
39
+ msgstr = <<END_OF_MESSAGE
40
+ From: #{config[:application_name]} <#{config[:sender]}>
41
+ Subject: [ERROR] - #{config[:application_name]} - An exception occured
42
+ Date: #{time_now}
43
+
44
+ Application name:
45
+ #{config[:application_name]}
46
+
47
+ Hostname:
48
+ #{hostname}
49
+
50
+ Notification time:
51
+ #{time_now} UTC
52
+
53
+ Error class:
54
+ #{error.class.name}
55
+
56
+ Error message:
57
+ #{error.message}
58
+
59
+ Backtrace:
60
+ #{error.backtrace}
61
+
62
+ Error cause:
63
+ #{error.cause}
64
+
65
+ Additional metadata:
66
+ #{metadata.to_s}
67
+ END_OF_MESSAGE
68
+ return msgstr
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ module Denouncer
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+ describe Denouncer do
4
+ let(:notifier_configuration) do
5
+ { application_name: "MyApplication", notifier: :console }
6
+ end
7
+ let(:error) do
8
+ StandardError.new("Test")
9
+ end
10
+
11
+ before do
12
+ Denouncer.reset_configuration
13
+ end
14
+
15
+ describe ".configure" do
16
+ let(:new_configuration) do
17
+ { application_name: "TestAppThing", notifier: :console, extra: "abc" }
18
+ end
19
+
20
+ context "configured" do
21
+ before do
22
+ Denouncer.configure notifier_configuration
23
+ end
24
+
25
+ it "should override the configuration" do
26
+ Denouncer.configure new_configuration
27
+ expect(Denouncer.config).to eq new_configuration
28
+ end
29
+
30
+ it "should initialize a notifier" do
31
+ Denouncer.configure new_configuration
32
+ expect(Denouncer.send(:notifier)).not_to be_nil
33
+ end
34
+ end
35
+
36
+ context "unconfigured" do
37
+ it "should set the given configuration" do
38
+ Denouncer.configure new_configuration
39
+ expect(Denouncer.config).to eq new_configuration
40
+ end
41
+
42
+ it "should initialize a notifier" do
43
+ Denouncer.configure new_configuration
44
+ expect(Denouncer.send(:notifier)).not_to be_nil
45
+ end
46
+ end
47
+
48
+ context "invalid config hash" do
49
+ context "no :application_name setting given" do
50
+ let(:invalid) do
51
+ { notifier: :console, extra: "abc" }
52
+ end
53
+
54
+ it "should raise an error" do
55
+ expect { Denouncer.configure invalid }.to raise_error
56
+ end
57
+ end
58
+
59
+ context "no hash given" do
60
+ let(:invalid) do
61
+ "Invalid String"
62
+ end
63
+
64
+ it "should raise an error" do
65
+ expect { Denouncer.configure invalid }.to raise_error
66
+ end
67
+ end
68
+
69
+ context "nil given" do
70
+ it "should raise an error" do
71
+ expect { Denouncer.configure nil }.to raise_error
72
+ end
73
+ end
74
+
75
+ context "invalid notifier setting given" do
76
+ let(:invalid) do
77
+ { application_name: "TestAppThing", notifier: :not_existing }
78
+ end
79
+
80
+ it "should raise an error" do
81
+ expect { Denouncer.configure invalid }.to raise_error
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ describe ".is_configured?" do
88
+ context "configured" do
89
+ before do
90
+ Denouncer.configure notifier_configuration
91
+ end
92
+
93
+ it "should return true" do
94
+ expect(Denouncer.is_configured?).to be_truthy
95
+ end
96
+ end
97
+
98
+ context "unconfigured" do
99
+ it "should return false" do
100
+ expect(Denouncer.is_configured?).to be_falsey
101
+ end
102
+ end
103
+ end
104
+
105
+ describe ".reset_configuration" do
106
+ before do
107
+ Denouncer.configure notifier_configuration
108
+ end
109
+
110
+ it "should set the notifier to nil" do
111
+ Denouncer.reset_configuration
112
+ expect(Denouncer.config).to be_nil
113
+ expect(Denouncer.is_configured?).to be_falsey
114
+ end
115
+ end
116
+
117
+ describe ".config" do
118
+ context "configured" do
119
+ before do
120
+ Denouncer.configure notifier_configuration
121
+ end
122
+
123
+ it "should return the notifier's configuration" do
124
+ notifier = Denouncer.send(:notifier)
125
+ expect(Denouncer.config).to eq notifier.config
126
+ end
127
+ end
128
+
129
+ context "unconfigured" do
130
+ it "should return nil" do
131
+ expect(Denouncer.config).to be_nil
132
+ end
133
+ end
134
+ end
135
+
136
+ describe ".notify" do
137
+ context "configured" do
138
+ before do
139
+ Denouncer.configure notifier_configuration
140
+ end
141
+
142
+ it "should call it's notifiers notify method" do
143
+ notifier = Denouncer.send(:notifier)
144
+ expect(notifier).to receive(:notify)
145
+ Denouncer.notify error
146
+ end
147
+ end
148
+
149
+ context "unconfigured" do
150
+ it "should raise an error" do
151
+ expect { Denouncer.notify error }.to raise_error
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ describe Denouncer::Notifiers::AmqpNotifier do
4
+ let(:error) do
5
+ error = nil
6
+ begin
7
+ 1/0
8
+ rescue => err
9
+ error = err
10
+ end
11
+ error
12
+ end
13
+ let(:app_name) { "my_app" }
14
+ let(:server) { 'localhost' }
15
+ let(:port) { 5672 }
16
+ let(:username) { 'guest' }
17
+ let(:password) { 'guest' }
18
+ let(:vhost) { '/'}
19
+ let(:message_queue) { 'my_app.errors' }
20
+ let(:config) do
21
+ {
22
+ application_name: app_name,
23
+ notifier: :amqp,
24
+ port: port,
25
+ server: server,
26
+ vhost: vhost,
27
+ username: username,
28
+ password: password,
29
+ message_queue: message_queue
30
+ }
31
+ end
32
+
33
+ describe "initialize" do
34
+ context "valid configuration" do
35
+ it "should set the configuration" do
36
+ notifier = Denouncer::Notifiers::AmqpNotifier.new config
37
+ expect(notifier.config).to eq config
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "set_configuration!" do
43
+ let(:notifier) { Denouncer::Notifiers::AmqpNotifier.new config }
44
+
45
+ context "valid configuration" do
46
+ it "should not raise an error" do
47
+ expect { notifier.set_configuration!(config) }.not_to raise_error
48
+ end
49
+
50
+ it "should return the options hash" do
51
+ expect(notifier.set_configuration!(config)).to eq config
52
+ end
53
+ end
54
+
55
+ context "invalid configuration" do
56
+ context "no application_name" do
57
+ let(:invalid) do
58
+ config.delete(:application_name)
59
+ config
60
+ end
61
+
62
+ it "should raise an error" do
63
+ expect { notifier.set_configuration! invalid }.to raise_error
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "#generate_json_message" do
70
+ let(:notifier) { Denouncer::Notifiers::AmqpNotifier.new config }
71
+ let(:metadata_var) { "HASHVAR123" }
72
+ let(:metadata) { { hash_var: metadata_var } }
73
+
74
+ it "should generate a json encoded message" do
75
+ msg = notifier.send(:generate_json_message, error, metadata)
76
+ expect(msg).to be_kind_of String
77
+ expect { JSON.parse(msg) }.not_to raise_error
78
+ end
79
+
80
+ it "should contain the error message" do
81
+ msg = notifier.send(:generate_json_message, error, metadata)
82
+ parsed = JSON.parse(msg)
83
+ expect(parsed["error_message"]).to match (error.message)
84
+ end
85
+
86
+ it "should contain the error class" do
87
+ msg = notifier.send(:generate_json_message, error, metadata)
88
+ parsed = JSON.parse(msg)
89
+ expect(parsed["error_class"]).to eq (error.class.name)
90
+ end
91
+
92
+ it "should contain the application_name" do
93
+ msg = notifier.send(:generate_json_message, error, metadata)
94
+ parsed = JSON.parse(msg)
95
+ expect(parsed["application_name"]).to eq app_name
96
+ end
97
+
98
+ it "should contain the metadata hash" do
99
+ msg = notifier.send(:generate_json_message, error, metadata)
100
+ parsed = JSON.parse(msg)
101
+ expect(parsed["metadata"]).to be_kind_of Hash
102
+ expect(parsed["metadata"]["hash_var"]).to eq metadata_var
103
+ end
104
+
105
+ it "should contain the backtrace" do
106
+ msg = notifier.send(:generate_json_message, error, metadata)
107
+ parsed = JSON.parse(msg)
108
+ expect(parsed["error_backtrace"]).to be_kind_of Array
109
+ end
110
+
111
+ it "should contain the notification_time" do
112
+ msg = notifier.send(:generate_json_message, error, metadata)
113
+ parsed = JSON.parse(msg)
114
+ expect(parsed["notification_time"]).not_to be_nil
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Denouncer::Notifiers::ConsoleNotifier do
4
+ let(:config) { { application_name: "my_app" } }
5
+ let(:notifier) { Denouncer::Notifiers::ConsoleNotifier.new config }
6
+
7
+ describe "#set_configuration!" do
8
+ it "should return the options" do
9
+ conf = notifier.set_configuration! config
10
+ expect(conf).to eq config
11
+ end
12
+ end
13
+
14
+ describe "#notify" do
15
+ it "should call puts" do
16
+ expect_any_instance_of(Object).to receive(:puts).at_least(:once)
17
+ notifier.notify(StandardError.new("Test"))
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,132 @@
1
+ require 'spec_helper'
2
+
3
+ describe Denouncer::Notifiers::SmtpNotifier do
4
+ let(:error) do
5
+ error = nil
6
+ begin
7
+ 1/0
8
+ rescue => err
9
+ error = err
10
+ end
11
+ error
12
+ end
13
+ let(:app_name) { "my_app" }
14
+ let(:server) { 'localhost' }
15
+ let(:port) { 1025 }
16
+ let(:domain) { 'localhost' }
17
+ let(:username) { nil }
18
+ let(:password) { nil }
19
+ let(:authtype) { nil }
20
+ let(:config) do
21
+ {
22
+ application_name: app_name,
23
+ notifier: :smtp,
24
+ port: port,
25
+ server: server,
26
+ sender: "noreply@example.com",
27
+ recipients: ['usera@example.com', 'userb@example.com'],
28
+ domain: domain,
29
+ username: username,
30
+ password: password,
31
+ authtype: authtype
32
+ }
33
+ end
34
+
35
+ describe "initialize" do
36
+ context "valid configuration" do
37
+ it "should set the configuration" do
38
+ notifier = Denouncer::Notifiers::SmtpNotifier.new config
39
+ expect(notifier.config).to eq config
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "notify" do
45
+ let(:notifier) { Denouncer::Notifiers::SmtpNotifier.new config }
46
+
47
+ it "should start a SMTP connection" do
48
+ expect(Net::SMTP).to receive(:start).with(server, port, domain, username, password, authtype)
49
+ notifier.notify(error, { test: "abc" })
50
+ end
51
+ end
52
+
53
+ describe "set_configuration!" do
54
+ let(:notifier) { Denouncer::Notifiers::SmtpNotifier.new config }
55
+
56
+ context "valid configuration" do
57
+ it "should not raise an error" do
58
+ expect { notifier.set_configuration!(config) }.not_to raise_error
59
+ end
60
+
61
+ it "should return the options hash" do
62
+ expect(notifier.set_configuration!(config)).to eq config
63
+ end
64
+ end
65
+
66
+ context "invalid configuration" do
67
+ context "no application_name" do
68
+ let(:invalid) do
69
+ config.delete(:application_name)
70
+ config
71
+ end
72
+
73
+ it "should raise an error" do
74
+ expect { notifier.set_configuration! invalid }.to raise_error
75
+ end
76
+ end
77
+
78
+ context "no sender" do
79
+ let(:invalid) do
80
+ config.delete(:sender)
81
+ config
82
+ end
83
+
84
+ it "should raise an error" do
85
+ expect { notifier.set_configuration! invalid }.to raise_error
86
+ end
87
+ end
88
+
89
+ context "no recipients array" do
90
+ let(:invalid) do
91
+ config.delete(:recipients)
92
+ config
93
+ end
94
+
95
+ it "should raise an error" do
96
+ expect { notifier.set_configuration! invalid }.to raise_error
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "#generate_text_message" do
103
+ let(:notifier) { Denouncer::Notifiers::SmtpNotifier.new config }
104
+ let(:metadata_var) { "HASHVAR123" }
105
+ let(:metadata) { { hash_var: metadata_var } }
106
+
107
+ it "should generate a text message" do
108
+ msg = notifier.send(:generate_text_message, error, metadata)
109
+ expect(msg).to be_kind_of String
110
+ end
111
+
112
+ it "should contain the error message" do
113
+ msg = notifier.send(:generate_text_message, error, metadata)
114
+ expect(msg).to match error.message
115
+ end
116
+
117
+ it "should contain the error class" do
118
+ msg = notifier.send(:generate_text_message, error, metadata)
119
+ expect(msg).to match error.class.name
120
+ end
121
+
122
+ it "should contain the application_name" do
123
+ msg = notifier.send(:generate_text_message, error, metadata)
124
+ expect(msg).to match app_name
125
+ end
126
+
127
+ it "should contain the metadata hash" do
128
+ msg = notifier.send(:generate_text_message, error, metadata)
129
+ expect(msg).to match metadata_var
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,16 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
4
+ require_relative '../lib/denouncer'
5
+ require 'rspec'
6
+
7
+ RSpec.configure do |config|
8
+
9
+ config.formatter = :documentation
10
+ config.tty = true
11
+ config.color = true
12
+
13
+ config.mock_with :rspec do |mocks|
14
+ mocks.syntax = [:expect, :should]
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: denouncer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Julian Weber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bunny
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Denouncer allows you to send notifications with error/exception details
112
+ using a simple interface. New methods of sending error messages can be implemented
113
+ using a pre-defined class interface. SMTP and AMQP notification are the first implemented
114
+ adapters. Use denouncer to get informed on error occurences instantly.
115
+ email:
116
+ - jweber@anynines.com
117
+ executables: []
118
+ extensions: []
119
+ extra_rdoc_files: []
120
+ files:
121
+ - ".gitignore"
122
+ - Gemfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - denouncer.gemspec
127
+ - lib/denouncer.rb
128
+ - lib/denouncer/notifiers.rb
129
+ - lib/denouncer/notifiers/amqp_notifier.rb
130
+ - lib/denouncer/notifiers/base_notifier.rb
131
+ - lib/denouncer/notifiers/console_notifier.rb
132
+ - lib/denouncer/notifiers/smtp_notifier.rb
133
+ - lib/denouncer/version.rb
134
+ - spec/lib/denouncer/denouncer_spec.rb
135
+ - spec/lib/denouncer/notifiers/amqp_notifier_spec.rb
136
+ - spec/lib/denouncer/notifiers/console_notifier_spec.rb
137
+ - spec/lib/denouncer/notifiers/smtp_notifier_spec.rb
138
+ - spec/spec_helper.rb
139
+ homepage: http://github.com/julweber/denouncer
140
+ licenses:
141
+ - MIT
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.2.2
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Denouncer allows you to send notifications (SMTP, AMQP) with error/exception
163
+ details using a simple interface.
164
+ test_files:
165
+ - spec/lib/denouncer/denouncer_spec.rb
166
+ - spec/lib/denouncer/notifiers/amqp_notifier_spec.rb
167
+ - spec/lib/denouncer/notifiers/console_notifier_spec.rb
168
+ - spec/lib/denouncer/notifiers/smtp_notifier_spec.rb
169
+ - spec/spec_helper.rb