lib/backup/logger/logfile.rb
module Backup
class Logger
class Logfile
class Error < Backup::Error; end
class Options
##
# Enable the use of Backup's log file.
#
# While not necessary, as this is +true+ by default,
# this may also be set on the command line using +--logfile+.
#
# The use of Backup's log file may be disabled using the
# command line option +--no-logfile+.
#
# If +--no--logfile+ is used on the command line, then the
# log file will be disabled and any setting here will be ignored.
#
# @param [Boolean, nil]
# @return [Boolean, nil] Default: +true+
attr_reader :enabled
##
# Path to directory where Backup's logfile will be written.
#
# This may be given as an absolute path, or a path relative
# to Backup's +--root-path+ (which defaults to +~/Backup+).
#
# This may also be set on the command line using +--log-path+.
# If set on the command line, any setting here will be ignored.
#
# @param [String]
# @return [String] Default: 'log'
attr_reader :log_path
##
# Backup's logfile in which backup logs can be written
#
# As there is already a log_path, this can simply be just a file name
# that will be created (If not exists) on log_path directory
#
# This may also be set on the command line using +--log-file+.
# If set on the command line, any setting here will be ignored.
#
# @param [String]
# @return [String] Default: 'backup.log'
attr_reader :log_file
##
# Size in bytes to truncate logfile to before backup jobs are run.
#
# This is done once before all +triggers+, so the maximum logfile size
# would be this value plus whatever the jobs produce.
#
# @param [Integer]
# @return [Integer] Default: +500_000+
attr_accessor :max_bytes
def initialize
@enabled = true
@log_path = ""
@max_bytes = 500_000
end
def enabled?
!!enabled
end
def enabled=(val)
@enabled = val unless enabled.nil?
end
def log_path=(val)
@log_path = val.to_s.strip if log_path.empty?
end
end
def initialize(options)
@options = options
@logfile = setup_logfile
truncate!
end
def log(message)
File.open(@logfile, "a") { |f| f.puts message.formatted_lines }
end
private
##
# Returns the full path to the log file, based on the configured
# @options.log_path, and ensures the path to the log file exists.
def setup_logfile
# strip any trailing '/' in case the user supplied this as part of
# an absolute path, so we can match it against File.expand_path()
path = @options.log_path.chomp("/")
if path.empty?
path = File.join(Backup::Config.root_path, "log")
elsif path != File.expand_path(path)
path = File.join(Backup::Config.root_path, path)
end
FileUtils.mkdir_p(path)
log_file = @options.log_file || "backup.log"
path = File.join(path, log_file)
if File.exist?(path) && !File.writable?(path)
raise Error, "Log File at '#{path}' is not writable"
end
path
end
##
# Truncates the logfile to @options.max_bytes
def truncate!
return unless File.exist?(@logfile)
if File.stat(@logfile).size > @options.max_bytes
FileUtils.cp(@logfile, @logfile + "~")
File.open(@logfile + "~", "r") do |io_in|
File.open(@logfile, "w") do |io_out|
io_in.seek(-@options.max_bytes, IO::SEEK_END) && io_in.gets
while line = io_in.gets
io_out.puts line
end
end
end
FileUtils.rm_f(@logfile + "~")
end
end
end
end
end