rf_logger 0.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/Gemfile +2 -0
- data/Rakefile +9 -0
- data/lib/rf_logger/configuration.rb +71 -0
- data/lib/rf_logger/levels.rb +9 -0
- data/lib/rf_logger/log_for_notification.rb +29 -0
- data/lib/rf_logger/notifications/error_notification.rb +37 -0
- data/lib/rf_logger/notifications/error_notification_environment_constraints.rb +24 -0
- data/lib/rf_logger/sequel_logger.rb +35 -0
- data/lib/rf_logger/simple_logger.rb +23 -0
- data/lib/rf_logger/version.rb +3 -0
- data/lib/rf_logger.rb +32 -0
- data/rf_logger.gemspec +29 -0
- data/spec/lib/rf_logger/configuration_spec.rb +123 -0
- data/spec/lib/rf_logger/log_for_notification_spec.rb +29 -0
- data/spec/lib/rf_logger/notifications/error_notification_environment_constraints_spec.rb +50 -0
- data/spec/lib/rf_logger/notifications/error_notification_spec.rb +68 -0
- data/spec/lib/rf_logger/sequel_logger_spec.rb +81 -0
- data/spec/lib/rf_logger/simple_logger_spec.rb +51 -0
- data/spec/spec_helper.rb +17 -0
- metadata +174 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8663cdc8e6bfe142b8fedc05be357102726f6b7b
|
4
|
+
data.tar.gz: 43eed68ae68adb06a36a97a810afb75feb0e9400
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5521b3c588c108ca71de061baecfc3b63cb08b0a8027e0b2b62b9ef78a7c8ddab8037f50a83d65593c5abfc91e909b619d5004f9d04592352b7106b6f7ddca18
|
7
|
+
data.tar.gz: b7f8a7dbc6c4e63d54144b49d60297f22088371b5b0582e048d8694f6bfd1f6a0d200aec6c3f20dfb03cfb8840b02832144b078742a8e79871a648666dded9da
|
data/.gitignore
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
lib/bundler/man
|
11
|
+
pkg
|
12
|
+
rdoc
|
13
|
+
spec/reports
|
14
|
+
test/tmp
|
15
|
+
test/version_tmp
|
16
|
+
tmp
|
17
|
+
.bash_color
|
18
|
+
*.sublime-*
|
19
|
+
default.vim
|
20
|
+
default.vim.lock
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module RfLogger
|
2
|
+
# Stores configuration information
|
3
|
+
#
|
4
|
+
# Configuration information is loaded from a configuration block defined within
|
5
|
+
# the client application.
|
6
|
+
#
|
7
|
+
# @example Standard settings
|
8
|
+
# RfLogger.configure do |c|
|
9
|
+
# c.notification_subject = "Oh no!"
|
10
|
+
# c.set_notifier_list do |n|
|
11
|
+
# c.add_notifier Notification::DefinedElsewhere, :levels => [:error], :except => ['test', 'development']
|
12
|
+
# c.add_notifier Notification::OhNo, :levels => [:fatal, :error], :only => ['production']
|
13
|
+
# c.add_notifer Notifcation:VeryVerbose
|
14
|
+
# end
|
15
|
+
# # ...
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
class Configuration
|
19
|
+
class << self
|
20
|
+
def define_setting(name)
|
21
|
+
defined_settings << name
|
22
|
+
attr_accessor name
|
23
|
+
end
|
24
|
+
|
25
|
+
def defined_settings
|
26
|
+
@defined_settings ||= []
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
define_setting :environment
|
31
|
+
define_setting :notification_subject
|
32
|
+
|
33
|
+
def environment
|
34
|
+
@environment ||= begin
|
35
|
+
raise UndefinedSetting.new('RfLogger.environment must be set') unless framework_environment
|
36
|
+
framework_environment
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def notifiers
|
41
|
+
ErrorNotification.notifiers
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_notifier_list
|
45
|
+
yield(ErrorNotification)
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear!
|
52
|
+
defined_settings.each {|setting| instance_variable_set("@#{setting}", nil)}
|
53
|
+
ErrorNotification.reset!
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def defined_settings
|
59
|
+
self.class.defined_settings
|
60
|
+
end
|
61
|
+
|
62
|
+
def framework_environment
|
63
|
+
case
|
64
|
+
when defined?(Rails) then Rails.env
|
65
|
+
when defined?(Rory) then ENV['RORY_STAGE']
|
66
|
+
when defined?(Padrino) then Padrino.environment
|
67
|
+
when defined?(Sinatra::Application) then Sinatra::Application.environment
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RfLogger
|
2
|
+
class LogForNotification
|
3
|
+
attr_accessor :level
|
4
|
+
def initialize(entry)
|
5
|
+
@actor = entry[:actor]
|
6
|
+
@action = entry[:action]
|
7
|
+
@metadata = entry[:metadata]
|
8
|
+
@level = entry[:level]
|
9
|
+
end
|
10
|
+
|
11
|
+
def subject
|
12
|
+
interpolated_configured_subject ||
|
13
|
+
"#{@level.upcase}! (#{@actor}/#{@action}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def details
|
17
|
+
YAML.dump @metadata
|
18
|
+
end
|
19
|
+
|
20
|
+
def interpolated_configured_subject
|
21
|
+
if subject = RfLogger.configuration.notification_subject
|
22
|
+
%w(actor action level).each do |variable|
|
23
|
+
subject = subject.gsub("{{#{variable}}}", instance_variable_get("@#{variable}"))
|
24
|
+
end
|
25
|
+
subject
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative 'error_notification_environment_constraints'
|
2
|
+
|
3
|
+
module RfLogger
|
4
|
+
class ErrorNotification
|
5
|
+
class << self
|
6
|
+
def configure(&block)
|
7
|
+
yield self
|
8
|
+
end
|
9
|
+
|
10
|
+
def notifiers
|
11
|
+
@@notifiers ||= Hash[RfLogger::LEVELS.map { |level| [level, []] }]
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_notifier notifier, constraints={}
|
15
|
+
levels = constraints.delete(:levels) || RfLogger::LEVELS
|
16
|
+
constraint = ErrorNotification::EnvironmentConstraints.new(
|
17
|
+
RfLogger.configuration.environment,
|
18
|
+
constraints)
|
19
|
+
if constraint.valid_notifier?
|
20
|
+
levels.each do |level|
|
21
|
+
notifiers[level] << notifier
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def dispatch_error(log_info)
|
27
|
+
notifiers[log_info.level.to_sym].each do |notifier|
|
28
|
+
notifier.send_error_notification log_info
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def reset!
|
33
|
+
@@notifiers = nil; notifiers
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module RfLogger
|
2
|
+
class ErrorNotification
|
3
|
+
class EnvironmentConstraints
|
4
|
+
def initialize(environment, constraints={})
|
5
|
+
@constraints = constraints
|
6
|
+
@environment = environment
|
7
|
+
end
|
8
|
+
|
9
|
+
def valid_notifier?
|
10
|
+
@constraints.nil? || (included? && !excluded?)
|
11
|
+
end
|
12
|
+
|
13
|
+
def included?
|
14
|
+
only = @constraints[:only]
|
15
|
+
only.nil? || only.include?(@environment)
|
16
|
+
end
|
17
|
+
|
18
|
+
def excluded?
|
19
|
+
except = @constraints[:except]
|
20
|
+
except && except.include?(@environment)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RfLogger
|
2
|
+
class SequelLogger < Sequel::Model
|
3
|
+
class << self
|
4
|
+
RfLogger::LEVELS.each do |level|
|
5
|
+
define_method level.to_sym do |entry|
|
6
|
+
log = add level, entry
|
7
|
+
|
8
|
+
notification_log = LogForNotification.new(entry.merge(:level => level))
|
9
|
+
ErrorNotification.dispatch_error(notification_log)
|
10
|
+
log
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def add(level, entry)
|
15
|
+
entry[:level] = RfLogger::LEVELS.index(level.to_sym)
|
16
|
+
entry[:actor] = entry[:actor] || ''
|
17
|
+
entry[:metadata] = entry[:metadata] || {}
|
18
|
+
entry[:created_at] = Time.now
|
19
|
+
create(entry)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def metadata
|
24
|
+
JSON.parse(self[:metadata])
|
25
|
+
end
|
26
|
+
|
27
|
+
def metadata=(metadata_hash)
|
28
|
+
self[:metadata] = metadata_hash.to_json
|
29
|
+
end
|
30
|
+
|
31
|
+
def display_level
|
32
|
+
RfLogger::LEVELS[level]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RfLogger
|
2
|
+
class SimpleLogger
|
3
|
+
class << self
|
4
|
+
def entries
|
5
|
+
@entries ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(level, entry)
|
9
|
+
entries << { :level => RfLogger::LEVELS.index(level), :entry => entry, :level_name => level }
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear!
|
13
|
+
@entries = []
|
14
|
+
end
|
15
|
+
|
16
|
+
RfLogger::LEVELS.each do |level|
|
17
|
+
define_method level.to_sym do |entry|
|
18
|
+
add level, entry
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/rf_logger.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'yaml'
|
3
|
+
require 'rf_logger/version'
|
4
|
+
require 'rf_logger/configuration'
|
5
|
+
require 'rf_logger/levels'
|
6
|
+
|
7
|
+
require 'rf_logger/notifications/error_notification'
|
8
|
+
require 'rf_logger/notifications/error_notification_environment_constraints'
|
9
|
+
|
10
|
+
require 'rf_logger/simple_logger'
|
11
|
+
require 'rf_logger/log_for_notification'
|
12
|
+
|
13
|
+
if defined?(Sequel)
|
14
|
+
require 'json'
|
15
|
+
require 'rf_logger/sequel_logger'
|
16
|
+
end
|
17
|
+
|
18
|
+
module RfLogger
|
19
|
+
class UndefinedSetting < StandardError; end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
extend Forwardable
|
23
|
+
|
24
|
+
Configuration.defined_settings.each do |setting|
|
25
|
+
def_delegators :configuration, setting, "#{setting.to_s}="
|
26
|
+
end
|
27
|
+
|
28
|
+
def configuration
|
29
|
+
@configuration ||= RfLogger::Configuration.new
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/rf_logger.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rf_logger/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'rf_logger'
|
8
|
+
s.version = '0.0.0'
|
9
|
+
s.date = '2014-02-20'
|
10
|
+
s.summary = "A logger that adheres to Renewable Funding logging conventions"
|
11
|
+
s.description = "A logger that allows specification of severity, applicable entity/records, metadata, and optional notifications"
|
12
|
+
s.authors = ["Dave Miller", "Laurie Kemmerer", "Maher Hawash", "Ravi Gadad"]
|
13
|
+
s.email = 'devteam@renewfund.com'
|
14
|
+
s.homepage = ''
|
15
|
+
s.license = 'MIT'
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split($/)
|
18
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency "bundler", "~> 1.3"
|
23
|
+
s.add_development_dependency "rake"
|
24
|
+
s.add_development_dependency 'rspec'
|
25
|
+
s.add_development_dependency 'watchr'
|
26
|
+
s.add_development_dependency 'debugger'
|
27
|
+
s.add_development_dependency 'simplecov'
|
28
|
+
s.add_development_dependency 'sequel'
|
29
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
describe RfLogger::Configuration do
|
2
|
+
class SomeNotifier; end
|
3
|
+
let(:configuration) {described_class.new}
|
4
|
+
before :each do
|
5
|
+
configuration.clear!
|
6
|
+
end
|
7
|
+
|
8
|
+
after :each do
|
9
|
+
Object.send(:remove_const, :Rails) if defined?(Rails)
|
10
|
+
Object.send(:remove_const, :Rory) if defined?(Rory)
|
11
|
+
Object.send(:remove_const, :Padrino) if defined?(Padrino)
|
12
|
+
Object.send(:remove_const, :Sinatra) if defined?(Sinatra::Application)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#environment" do
|
16
|
+
it 'raises an error if client did not define' do
|
17
|
+
expect{configuration.environment}.to raise_error RfLogger::UndefinedSetting
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns environment set by user' do
|
21
|
+
configuration.environment = 'test'
|
22
|
+
configuration.environment.should == 'test'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'uses Rails.env if Rails is defined' do
|
26
|
+
class Rails
|
27
|
+
def self.env
|
28
|
+
'monkey'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
configuration.environment.should == 'monkey'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'uses Padrino.environment if defined' do
|
36
|
+
class Padrino
|
37
|
+
def self.environment
|
38
|
+
'padrino'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
configuration.environment.should == 'padrino'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'uses Sinatra::Application.environment if defined' do
|
46
|
+
class Sinatra
|
47
|
+
class Application
|
48
|
+
def self.environment
|
49
|
+
'sinatra'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
configuration.environment.should == 'sinatra'
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'uses ENV["RORY_STAGE"] if Rory is defined' do
|
58
|
+
class Rory
|
59
|
+
end
|
60
|
+
ENV['RORY_STAGE'] = 'rory'
|
61
|
+
|
62
|
+
configuration.environment.should == 'rory'
|
63
|
+
ENV['RORY_STAGE'] = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'raises error if automatic root detection returns nil' do
|
67
|
+
class Rails
|
68
|
+
def self.env
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
expect{configuration.environment}.to raise_error RfLogger::UndefinedSetting
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#clear!' do
|
78
|
+
it 'resets environment' do
|
79
|
+
configuration.environment = 'foo'
|
80
|
+
configuration.clear!
|
81
|
+
expect{configuration.environment}.to raise_error RfLogger::UndefinedSetting
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'resets notification subject' do
|
85
|
+
configuration.notification_subject = 'foo'
|
86
|
+
configuration.clear!
|
87
|
+
configuration.notification_subject.should be_nil
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'resets environmental error notifier settings' do
|
91
|
+
RfLogger.configuration.stub(:environment => 'test')
|
92
|
+
configuration.set_notifier_list { |n| n.add_notifier SomeNotifier }
|
93
|
+
configuration.clear!
|
94
|
+
configuration.notifiers.keys.should =~ RfLogger::LEVELS
|
95
|
+
configuration.notifiers.values.uniq.should == [[]]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'notification_subject' do
|
100
|
+
it 'sets the value' do
|
101
|
+
configuration.notification_subject = 'Foo!'
|
102
|
+
configuration.notification_subject.should == 'Foo!'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe 'set_notifier_list' do
|
107
|
+
class SomeOtherNotifier; end
|
108
|
+
class AThirdNotifier; end
|
109
|
+
it 'calls add_notifier on ErrorNotification and adds the notifier to config list' do
|
110
|
+
RfLogger.configuration.stub(:environment => 'test')
|
111
|
+
|
112
|
+
configuration.set_notifier_list do |n|
|
113
|
+
n.add_notifier SomeNotifier, :only => ['test'], :levels => [:fatal]
|
114
|
+
n.add_notifier SomeOtherNotifier, :except => ['test'], :levels => [:fatal]
|
115
|
+
n.add_notifier AThirdNotifier, :levels => [:fatal]
|
116
|
+
end
|
117
|
+
|
118
|
+
configuration.notifiers.delete(:fatal).should =~ [SomeNotifier, AThirdNotifier]
|
119
|
+
# all other levels shouldn't have notifiers
|
120
|
+
configuration.notifiers.values.uniq.should == [[]]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
describe RfLogger::LogForNotification do
|
2
|
+
subject { described_class.new(
|
3
|
+
:actor => 'fruit_cocktail',
|
4
|
+
:action => 'finding_maraschino_cherries',
|
5
|
+
:level => 'ERROR',
|
6
|
+
:metadata => { :something_is_wrong => 'with_the_refrigerator' }
|
7
|
+
)}
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
RfLogger.configuration.clear!
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'subject' do
|
14
|
+
it 'reports log level, actor, and action of the error' do
|
15
|
+
subject.subject.should =~ /ERROR.*fruit_cocktail.*finding_maraschino_cherries/
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'uses the configured subject, if given' do
|
19
|
+
RfLogger.configuration.notification_subject = "Help! {{level}} for {{actor}}/{{action}}"
|
20
|
+
subject.subject.should == "Help! ERROR for fruit_cocktail/finding_maraschino_cherries"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'details' do
|
25
|
+
it 'should include metadata' do
|
26
|
+
subject.details.should =~ /something_is_wrong.*with_the_refrigerator/
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RfLogger::ErrorNotification::EnvironmentConstraints do
|
4
|
+
describe '#included?' do
|
5
|
+
it 'returns true if no constraints for :only are given' do
|
6
|
+
described_class.new('alpha', {}).included?.should be_true
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'returns true if the environment is included in :only' do
|
10
|
+
described_class.new('alpha', {:only => ['alpha', 'beta']}).included?.should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns false if the environment is not in :only' do
|
14
|
+
described_class.new('alpha', {:only => ['beta']}).included?.should be_false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#excluded?' do
|
19
|
+
it 'returns false if no constraints for :except are given' do
|
20
|
+
described_class.new('alpha', {}).excluded?.should be_false
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns true if the environment is included in :except' do
|
24
|
+
described_class.new('alpha', {:except => ['alpha', 'beta']}).excluded?.should be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns false if the environment is not in :except' do
|
28
|
+
described_class.new('alpha', {:except => ['beta']}).excluded?.should be_false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#valid_notifier?' do
|
33
|
+
it 'returns true if there are no constraints' do
|
34
|
+
described_class.new('alpha', nil).valid_notifier?.should be_true
|
35
|
+
described_class.new('alpha', {}).valid_notifier?.should be_true
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns true if the environment is included in :only and not included in :except' do
|
39
|
+
described_class.new('alpha', {:only => ['alpha'], :except => []}).valid_notifier?.should be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns false if the environment is included in :except' do
|
43
|
+
described_class.new('alpha', {:except => ['alpha']}).valid_notifier?.should be_false
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns false if the environment is not in :only' do
|
47
|
+
described_class.new('alpha', {:only => ['beta']}).valid_notifier?.should be_false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RfLogger::ErrorNotification do
|
4
|
+
before :each do
|
5
|
+
RfLogger.configuration.environment = 'test'
|
6
|
+
end
|
7
|
+
|
8
|
+
after :each do
|
9
|
+
described_class.reset!
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'configuration' do
|
13
|
+
it 'allows specification of which log levels on which to notify' do
|
14
|
+
RfLogger.configuration.environment = 'alpha'
|
15
|
+
described_class.configure do |c|
|
16
|
+
c.add_notifier 'perfectly refined', :levels => [:fatal, :error]
|
17
|
+
c.add_notifier 'swiftly clean', :levels => [:fatal]
|
18
|
+
end
|
19
|
+
|
20
|
+
described_class.notifiers.delete(:error).should =~ ['perfectly refined']
|
21
|
+
described_class.notifiers.delete(:fatal).should =~ ['perfectly refined', 'swiftly clean']
|
22
|
+
described_class.notifiers.values.uniq.should == [[]]
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'allows multiple types of notification' do
|
26
|
+
described_class.configure do |c|
|
27
|
+
c.add_notifier 'gravy_pie'
|
28
|
+
c.add_notifier 'assiduous_hedgehog'
|
29
|
+
end
|
30
|
+
described_class.notifiers.keys.should == RfLogger::LEVELS
|
31
|
+
described_class.notifiers.values.uniq.tap do |unique_notifiers|
|
32
|
+
unique_notifiers.count.should == 1
|
33
|
+
unique_notifiers[0].should =~ ['assiduous_hedgehog', 'gravy_pie']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'allows notifications specifying particular environments' do
|
38
|
+
RfLogger.configuration.environment = 'alpha'
|
39
|
+
described_class.configure do |c|
|
40
|
+
c.add_notifier 'perfectly refined', :except => ['alpha']
|
41
|
+
c.add_notifier 'swiftly clean', :only => ['beta']
|
42
|
+
c.add_notifier 'terribly sweet'
|
43
|
+
end
|
44
|
+
|
45
|
+
described_class.notifiers.values.uniq.tap do |unique_notifiers|
|
46
|
+
unique_notifiers.count.should == 1
|
47
|
+
unique_notifiers[0].should == ['terribly sweet']
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '.dispatch_error' do
|
53
|
+
before :each do
|
54
|
+
described_class.configure do |c|
|
55
|
+
c.add_notifier 'gravy_pie'
|
56
|
+
c.add_notifier 'assiduous_hedgehog'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'calls error_notification on all configured notifiers' do
|
61
|
+
log = double(:log, :level => :warn)
|
62
|
+
described_class.notifiers[:warn].each do |n|
|
63
|
+
n.should_receive(:send_error_notification).with(log)
|
64
|
+
end
|
65
|
+
described_class.dispatch_error(log)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
describe RfLogger::SequelLogger do
|
2
|
+
before :each do
|
3
|
+
Time.stub(:now => 'NOW')
|
4
|
+
described_class.dataset =
|
5
|
+
DB[:logs].columns(:actor, :action, :target_type, :target_id,
|
6
|
+
:metadata, :created_at, :updated_at, :level)
|
7
|
+
end
|
8
|
+
|
9
|
+
RfLogger::LEVELS.each do |level|
|
10
|
+
describe ".#{level}" do
|
11
|
+
it "logs information in the database with #{level.upcase} level" do
|
12
|
+
described_class.should_receive(:add).
|
13
|
+
with(level, :something => :happened)
|
14
|
+
described_class.send(level.to_sym, :something => :happened)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'dispatches error notifications' do
|
18
|
+
described_class.stub(:add)
|
19
|
+
RfLogger::ErrorNotification.should_receive(:dispatch_error)
|
20
|
+
described_class.send(level.to_sym, :something => :happened)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '.add' do
|
26
|
+
it 'adds given object to the log at given level' do
|
27
|
+
RfLogger::SequelLogger.should_receive(:create).with(
|
28
|
+
:actor => 'cat herder',
|
29
|
+
:action => 'herd some cats',
|
30
|
+
:target_type => 'Cat',
|
31
|
+
:target_id => 'cat_numero_tres',
|
32
|
+
:metadata => {
|
33
|
+
:message => 'There are cats everywhere',
|
34
|
+
:danger => {
|
35
|
+
:level => 'really_high',
|
36
|
+
:rodent => 'mouse',
|
37
|
+
}
|
38
|
+
},
|
39
|
+
:level => RfLogger::LEVELS.index(:info),
|
40
|
+
:created_at => 'NOW',
|
41
|
+
)
|
42
|
+
|
43
|
+
described_class.add(:info, {
|
44
|
+
:actor => 'cat herder',
|
45
|
+
:action => 'herd some cats',
|
46
|
+
:target_type => 'Cat',
|
47
|
+
:target_id => 'cat_numero_tres',
|
48
|
+
:metadata => {
|
49
|
+
:message => 'There are cats everywhere',
|
50
|
+
:danger => {
|
51
|
+
:level => 'really_high',
|
52
|
+
:rodent => 'mouse',
|
53
|
+
}
|
54
|
+
}
|
55
|
+
})
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'sets actor to blank string if not provided' do
|
59
|
+
described_class.should_receive(:create).with(
|
60
|
+
:actor => '',
|
61
|
+
:action => 'palpitate',
|
62
|
+
:metadata => {},
|
63
|
+
:created_at => 'NOW',
|
64
|
+
:level => RfLogger::LEVELS.index(:info))
|
65
|
+
|
66
|
+
described_class.add(:info, { :action => 'palpitate' })
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'sets metadata to empty hash if not provided' do
|
70
|
+
described_class.should_receive(:create).with(
|
71
|
+
:actor => '',
|
72
|
+
:action => 'palpitate',
|
73
|
+
:metadata => {},
|
74
|
+
:created_at => 'NOW',
|
75
|
+
:level => RfLogger::LEVELS.index(:info)
|
76
|
+
)
|
77
|
+
|
78
|
+
described_class.add(:info, { :action => 'palpitate' })
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
describe RfLogger::SimpleLogger do
|
2
|
+
before :each do
|
3
|
+
RfLogger::SimpleLogger.clear!
|
4
|
+
end
|
5
|
+
|
6
|
+
RfLogger::LEVELS.each do |level|
|
7
|
+
describe ".#{level}" do
|
8
|
+
it "adds given object to the log with '#{level}' level" do
|
9
|
+
described_class.should_receive(:add).
|
10
|
+
with(level, :something => :happened)
|
11
|
+
described_class.send(level.to_sym, :something => :happened)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.add' do
|
17
|
+
it 'adds given object to the log at given level' do
|
18
|
+
described_class.add(:info, :super_serious_occurrence)
|
19
|
+
described_class.add(:debug, :weird_thing)
|
20
|
+
described_class.entries.should == [
|
21
|
+
{ :level => 1, :level_name => :info, :entry => :super_serious_occurrence },
|
22
|
+
{ :level => 0, :level_name => :debug, :entry => :weird_thing }
|
23
|
+
]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.entries' do
|
28
|
+
it 'returns entries at all levels when given no filter' do
|
29
|
+
described_class.info 'thing'
|
30
|
+
described_class.debug 'other thing'
|
31
|
+
described_class.info 'third thing'
|
32
|
+
described_class.fatal 'final thing'
|
33
|
+
described_class.entries.should == [
|
34
|
+
{ :level => 1, :level_name => :info, :entry => 'thing' },
|
35
|
+
{ :level => 0, :level_name => :debug, :entry => 'other thing' },
|
36
|
+
{ :level => 1, :level_name => :info, :entry => 'third thing' },
|
37
|
+
{ :level => 4, :level_name => :fatal, :entry => 'final thing' }
|
38
|
+
]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '.clear!' do
|
43
|
+
it 'deletes all entries' do
|
44
|
+
described_class.entries.should be_empty
|
45
|
+
described_class.info 'thing'
|
46
|
+
described_class.entries.should_not be_empty
|
47
|
+
described_class.clear!
|
48
|
+
described_class.entries.should be_empty
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
5
|
+
# in spec/support/ and its subdirectories.
|
6
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
7
|
+
|
8
|
+
require 'sequel'
|
9
|
+
DB = Sequel.mock
|
10
|
+
|
11
|
+
require './lib/rf_logger'
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
15
|
+
config.run_all_when_everything_filtered = true
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rf_logger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dave Miller
|
8
|
+
- Laurie Kemmerer
|
9
|
+
- Maher Hawash
|
10
|
+
- Ravi Gadad
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2014-02-20 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: bundler
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '1.3'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - '>='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: rspec
|
46
|
+
requirement: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: watchr
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
type: :development
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: debugger
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: simplecov
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
type: :development
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: sequel
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
type: :development
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
description: A logger that allows specification of severity, applicable entity/records,
|
115
|
+
metadata, and optional notifications
|
116
|
+
email: devteam@renewfund.com
|
117
|
+
executables: []
|
118
|
+
extensions: []
|
119
|
+
extra_rdoc_files: []
|
120
|
+
files:
|
121
|
+
- .gitignore
|
122
|
+
- .rspec
|
123
|
+
- Gemfile
|
124
|
+
- Rakefile
|
125
|
+
- lib/rf_logger.rb
|
126
|
+
- lib/rf_logger/configuration.rb
|
127
|
+
- lib/rf_logger/levels.rb
|
128
|
+
- lib/rf_logger/log_for_notification.rb
|
129
|
+
- lib/rf_logger/notifications/error_notification.rb
|
130
|
+
- lib/rf_logger/notifications/error_notification_environment_constraints.rb
|
131
|
+
- lib/rf_logger/sequel_logger.rb
|
132
|
+
- lib/rf_logger/simple_logger.rb
|
133
|
+
- lib/rf_logger/version.rb
|
134
|
+
- rf_logger.gemspec
|
135
|
+
- spec/lib/rf_logger/configuration_spec.rb
|
136
|
+
- spec/lib/rf_logger/log_for_notification_spec.rb
|
137
|
+
- spec/lib/rf_logger/notifications/error_notification_environment_constraints_spec.rb
|
138
|
+
- spec/lib/rf_logger/notifications/error_notification_spec.rb
|
139
|
+
- spec/lib/rf_logger/sequel_logger_spec.rb
|
140
|
+
- spec/lib/rf_logger/simple_logger_spec.rb
|
141
|
+
- spec/spec_helper.rb
|
142
|
+
homepage: ''
|
143
|
+
licenses:
|
144
|
+
- MIT
|
145
|
+
metadata: {}
|
146
|
+
post_install_message:
|
147
|
+
rdoc_options: []
|
148
|
+
require_paths:
|
149
|
+
- lib
|
150
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - '>='
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
requirements: []
|
161
|
+
rubyforge_project:
|
162
|
+
rubygems_version: 2.0.14
|
163
|
+
signing_key:
|
164
|
+
specification_version: 4
|
165
|
+
summary: A logger that adheres to Renewable Funding logging conventions
|
166
|
+
test_files:
|
167
|
+
- spec/lib/rf_logger/configuration_spec.rb
|
168
|
+
- spec/lib/rf_logger/log_for_notification_spec.rb
|
169
|
+
- spec/lib/rf_logger/notifications/error_notification_environment_constraints_spec.rb
|
170
|
+
- spec/lib/rf_logger/notifications/error_notification_spec.rb
|
171
|
+
- spec/lib/rf_logger/sequel_logger_spec.rb
|
172
|
+
- spec/lib/rf_logger/simple_logger_spec.rb
|
173
|
+
- spec/spec_helper.rb
|
174
|
+
has_rdoc:
|