Skip to content

Commit

Permalink
Logger updates
Browse files Browse the repository at this point in the history
This is to support the future acceptance tests, where the logger used
for each trigger/model will be inspected after all jobs are run.
  • Loading branch information
Brian D. Burns committed Mar 17, 2013
1 parent 9746f8a commit e1a7bfd
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 72 deletions.
1 change: 1 addition & 0 deletions lib/backup.rb
Expand Up @@ -7,6 +7,7 @@
require 'syslog'
require 'yaml'
require 'etc'
require 'forwardable'

require 'open4'
require 'thor'
Expand Down
137 changes: 80 additions & 57 deletions lib/backup/logger.rb
Expand Up @@ -5,7 +5,7 @@
require 'backup/logger/syslog'

module Backup
module Logger
class Logger

class Config
class Logger < Struct.new(:class, :options)
Expand All @@ -24,7 +24,7 @@ def initialize
Logger.new(Logfile, Logfile::Options.new),
Logger.new(Syslog, Syslog::Options.new)
]
@dsl = DSL.new(*@loggers.map(&:options))
@dsl = DSL.new(*loggers.map(&:options))
end
end

Expand All @@ -43,10 +43,10 @@ def formatted_lines
end

class << self
##
# Returns an Array of Message objects for all logged messages received.
# These are used to attach log files to Mail notifications.
attr_reader :messages
extend Forwardable
def_delegators :logger,
:start!, :abort!, :info, :warn, :error,
:messages, :has_warnings?, :has_errors?

##
# Allows the Logger to be configured.
Expand Down Expand Up @@ -76,75 +76,98 @@ class << self
# @see Logfile::Options
# @see Syslog::Options
def configure(&block)
@config.dsl.instance_eval(&block)
config.dsl.instance_eval(&block)
end

##
# Sends a message to the Logger using the specified log level.
# +obj+ may be any Object that responds to #to_s (i.e. an Exception)
[:info, :warn, :error].each do |level|
define_method level, lambda {|obj| log(obj, level) }
# Called after each backup model/trigger has been performed.
def clear!
@logger = nil
logger.start!
end

##
# Returns true if any +:warn+ level messages have been received.
def has_warnings?
@has_warnings
end
private

##
# The Logger is available as soon as Backup is loaded, and stores all
# messages it receives. Since the Logger may be configured via the
# command line and/or the user's +config.rb+, no messages are sent
# until configuration can be completed. (see CLI#perform)
#
# Once configuration is completed, this method is called to activate
# all enabled loggers and send them any messages that have been received
# up to this point. From this point onward, these loggers will be sent
# all messages as soon as they're received.
def start!
@config.loggers.each do |logger|
@loggers << logger.class.new(logger.options) if logger.enabled?
end
@messages.each do |message|
@loggers.each {|logger| logger.log(message) }
end
def config
@config ||= Config.new
end

##
# Called after each backup model/trigger has been performed.
def clear!
messages.clear
@has_warnings = false
def logger
@logger ||= new(config)
end

##
# If errors are encountered by Backup::CLI while preparing to perform
# the backup jobs, this method is called to dump all messages to the
# console before Backup exits.
def abort!
console = Console.new
console.log(@messages.shift) until @messages.empty?
def reset!
@config = @logger = nil
end
end

private
##
# Returns an Array of Message objects for all logged messages received.
# These are used to attach log files to Mail notifications.
attr_reader :messages

def initialize(config)
@config = config
@messages = []
@loggers = []
@has_warnings = @has_errors = false
end

def initialize!
@messages = []
@loggers = []
@config = Config.new
@has_warnings = false
end
##
# Sends a message to the Logger using the specified log level.
# +obj+ may be any Object that responds to #to_s (i.e. an Exception)
[:info, :warn, :error].each do |level|
define_method level, lambda {|obj| log(obj, level) }
end

##
# Returns true if any +:warn+ level messages have been received.
def has_warnings?
@has_warnings
end

##
# Returns true if any +:error+ level messages have been received.
def has_errors?
@has_errors
end

def log(obj, level)
@has_warnings ||= level == :warn
message = Message.new(Time.now, level, obj.to_s.split("\n"))
@messages << message
##
# The Logger is available as soon as Backup is loaded, and stores all
# messages it receives. Since the Logger may be configured via the
# command line and/or the user's +config.rb+, no messages are sent
# until configuration can be completed. (see CLI#perform)
#
# Once configuration is completed, this method is called to activate
# all enabled loggers and send them any messages that have been received
# up to this point. From this point onward, these loggers will be sent
# all messages as soon as they're received.
def start!
@config.loggers.each do |logger|
@loggers << logger.class.new(logger.options) if logger.enabled?
end
messages.each do |message|
@loggers.each {|logger| logger.log(message) }
end
end

##
# If errors are encountered by Backup::CLI while preparing to perform
# the backup jobs, this method is called to dump all messages to the
# console before Backup exits.
def abort!
console = Console.new
console.log(messages.shift) until messages.empty?
end

initialize!
private

def log(obj, level)
@has_warnings ||= level == :warn
@has_errors ||= level == :error
message = Message.new(Time.now, level, obj.to_s.split("\n"))
messages << message
@loggers.each {|logger| logger.log(message) }
end
end
end
2 changes: 1 addition & 1 deletion lib/backup/logger/console.rb
@@ -1,7 +1,7 @@
# encoding: utf-8

module Backup
module Logger
class Logger
class Console
class Options
##
Expand Down
2 changes: 1 addition & 1 deletion lib/backup/logger/logfile.rb
@@ -1,7 +1,7 @@
# encoding: utf-8

module Backup
module Logger
class Logger
class Logfile
class Options
##
Expand Down
2 changes: 1 addition & 1 deletion lib/backup/logger/syslog.rb
@@ -1,7 +1,7 @@
# encoding: utf-8

module Backup
module Logger
class Logger
class Syslog
class Options
##
Expand Down
50 changes: 39 additions & 11 deletions spec/logger_spec.rb
Expand Up @@ -9,7 +9,7 @@ module Backup
let(:syslog_logger) { mock('Syslog Logger') }
let(:default_loggers) { [console_logger, logfile_logger] }

# Note: spec_helper initializes Logger before each example
# Note: spec_helper calls Logger.reset! before each example
before do
Logger::Console.stubs(:new).
with(kind_of(Logger::Console::Options)).
Expand Down Expand Up @@ -68,7 +68,7 @@ module Backup
context 'when the console and logfile loggers are enabled' do
before do
Logger::Syslog.expects(:new).never
subject.configure do
Logger.configure do
console.quiet = false
logfile.enabled = true
syslog.enabled = false
Expand All @@ -93,7 +93,7 @@ module Backup
context 'when the logfile and syslog loggers are enabled' do
before do
Logger::Console.expects(:new).never
subject.configure do
Logger.configure do
console.quiet = true
logfile.enabled = true
syslog.enabled = true
Expand All @@ -118,7 +118,7 @@ module Backup
context 'when the console and syslog loggers are enabled' do
before do
Logger::Logfile.expects(:new).never
subject.configure do
Logger.configure do
console.quiet = false
logfile.enabled = false
syslog.enabled = true
Expand Down Expand Up @@ -156,7 +156,7 @@ module Backup
Logger::Syslog.expects(:new).never

Logger.info 'a message'
Logger.instance_variable_get(:@loggers).should be_empty
Logger.send(:logger).instance_variable_get(:@loggers).should be_empty
end
end

Expand Down Expand Up @@ -200,7 +200,8 @@ module Backup

it 'instantiates all enabled loggers' do
Logger.start!
Logger.instance_variable_get(:@loggers).should == default_loggers
Logger.send(:logger).instance_variable_get(:@loggers).
should == default_loggers
end
end
end # describe '.start!'
Expand Down Expand Up @@ -260,10 +261,7 @@ module Backup
describe '.has_warnings?' do
context 'when messages with :warn log level are sent' do
it 'returns true' do
Logger.info 'info message'
Logger.warn 'warn message'
Logger.error 'error message'

Logger.has_warnings?.should be_true
end
end
Expand All @@ -272,10 +270,24 @@ module Backup
it 'returns false' do
Logger.info 'info message'
Logger.error 'error message'
Logger.info 'info message'

Logger.has_warnings?.should be_false
end
end
end

describe '.has_errors?' do
context 'when messages with :error log level are sent' do
it 'returns true' do
Logger.error 'error message'
Logger.has_errors?.should be_true
end
end

context 'when no messages with :warn log level are sent' do
it 'returns false' do
Logger.info 'info message'
Logger.warn 'warn message'
Logger.has_errors?.should be_false
end
end
end
Expand All @@ -288,8 +300,11 @@ module Backup

Logger.messages.count.should be(3)
Logger.has_warnings?.should be_true
Logger.has_errors?.should be_true

@initial_logger = Logger.instance_variable_get(:@logger)
Logger.clear!
@current_logger = Logger.instance_variable_get(:@logger)
end

it 'clears all stored messages' do
Expand All @@ -299,6 +314,19 @@ module Backup
it 'resets has_warnings? to false' do
Logger.has_warnings?.should be_false
end

it 'resets has_errors? to false' do
Logger.has_errors?.should be_false
end

it 'replaces the logger' do
@current_logger.should be_a(Backup::Logger)
@current_logger.should_not be(@initial_logger)
end

it 'starts the new logger' do
@current_logger.instance_variable_get(:@loggers).should == default_loggers
end
end

describe '.abort!' do
Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Expand Up @@ -56,7 +56,7 @@ def capture_io
Backup::Utilities.send(:reset!)
Backup::Config.send(:reset!)
# Logger only queues messages received until Logger.start! is called.
Backup::Logger.send(:initialize!)
Backup::Logger.send(:reset!)
end
end

Expand Down

0 comments on commit e1a7bfd

Please sign in to comment.