Class: Logbert::Handlers::LogRotator
Overview
This class is a custom Handler responsible for rotating logs. This #
means that it will periodically: #
- Close the current log file and rename it. #
- Begin writing future log messages to a new file. #
- Delete the oldest log files to free up space #
Time-based log rotation #
Instance Attribute Summary collapse
Instance Method Summary
collapse
Methods inherited from BaseHandler
#formatter, #formatter=, #publish
Constructor Details
#initialize(path, options = {}) ⇒ LogRotator
Returns a new instance of LogRotator.
40
41
42
43
44
45
|
# File 'lib/logbert/handlers/log_rotator.rb', line 40
def initialize(path, options = {})
@path = path
@max_backups = options.fetch(:max_backups, nil)
@timestamp_formatter = options.fetch(:timestamp_formatter, LocaltimeFormatter.new)
@interval = options.fetch(:interval, (24 * 60 * 60))
end
|
Instance Attribute Details
#expiration_timestamp ⇒ Object
Returns the value of attribute expiration_timestamp.
37
38
39
|
# File 'lib/logbert/handlers/log_rotator.rb', line 37
def expiration_timestamp
@expiration_timestamp
end
|
#file_handle ⇒ Object
Returns the value of attribute file_handle.
36
37
38
|
# File 'lib/logbert/handlers/log_rotator.rb', line 36
def file_handle
@file_handle
end
|
#interval ⇒ Object
Returns the value of attribute interval.
36
37
38
|
# File 'lib/logbert/handlers/log_rotator.rb', line 36
def interval
@interval
end
|
#max_backups ⇒ Object
Returns the value of attribute max_backups.
37
38
39
|
# File 'lib/logbert/handlers/log_rotator.rb', line 37
def max_backups
@max_backups
end
|
#path ⇒ Object
Returns the value of attribute path.
38
39
40
|
# File 'lib/logbert/handlers/log_rotator.rb', line 38
def path
@path
end
|
Returns the value of attribute timestamp_formatter.
36
37
38
|
# File 'lib/logbert/handlers/log_rotator.rb', line 36
def timestamp_formatter
@timestamp_formatter
end
|
Instance Method Details
#already_rotated? ⇒ Boolean
59
60
61
|
# File 'lib/logbert/handlers/log_rotator.rb', line 59
def already_rotated?
return File.ctime(@path) > @expiration_timestamp
end
|
#attach_to_logfile! ⇒ Object
63
64
65
66
67
68
69
70
71
|
# File 'lib/logbert/handlers/log_rotator.rb', line 63
def attach_to_logfile!
lock do
dirname = File.dirname(File.absolute_path(@path))
FileUtils.mkdir_p dirname unless File.exists? dirname
@file_handle = File.open(@path, 'a')
creation_timestamp = File.ctime(@path)
@expiration_timestamp = compute_expiration_timestamp_from(creation_timestamp)
end
end
|
#attached? ⇒ Boolean
47
48
49
|
# File 'lib/logbert/handlers/log_rotator.rb', line 47
def attached?
return !file_handle.nil?
end
|
#compress_backups ⇒ Object
128
129
130
131
132
133
134
135
136
137
138
|
# File 'lib/logbert/handlers/log_rotator.rb', line 128
def compress_backups
get_old_logs.each do |log|
unless File.extname(log) == ".gz"
gzip(log)
File.delete(log)
end
end
end
|
#compute_expiration_timestamp_from(timestamp) ⇒ Object
80
81
82
|
# File 'lib/logbert/handlers/log_rotator.rb', line 80
def compute_expiration_timestamp_from(timestamp)
return timestamp + @interval
end
|
#delete_backups ⇒ Object
140
141
142
143
144
145
146
147
148
149
|
# File 'lib/logbert/handlers/log_rotator.rb', line 140
def delete_backups
unless @max_backups.nil?
old_logs = get_old_logs.sort_by {|f| File.ctime(f)}.reverse[@max_backups..-1]
old_logs.each {|f| File.delete(f)} if old_logs
end
end
|
#emit(output) ⇒ Object
73
74
75
76
77
78
|
# File 'lib/logbert/handlers/log_rotator.rb', line 73
def emit(output)
attach_to_logfile! unless attached?
rotate_logs! if rotation_required?
@file_handle.puts output
@file_handle.flush
end
|
#get_old_logs ⇒ Object
160
161
162
163
164
|
# File 'lib/logbert/handlers/log_rotator.rb', line 160
def get_old_logs
absolute_dir = File.dirname(File.absolute_path(@path))
older_files = Dir[File.join(absolute_dir, "#{@path}.backup.*")]
return older_files
end
|
#gzip(file) ⇒ Object
151
152
153
154
155
156
157
158
|
# File 'lib/logbert/handlers/log_rotator.rb', line 151
def gzip(file)
Zlib::GzipWriter.open("#{file}.gz") do |gz|
gz.mtime = File.mtime(file)
gz.orig_name = file
gz.write IO.binread(file)
gz.close
end
end
|
#lock(&block) ⇒ Object
84
85
86
87
88
89
90
91
|
# File 'lib/logbert/handlers/log_rotator.rb', line 84
def lock(&block)
p = lock_file_name_for(@path)
FileUtils.mkdir_p File.dirname(p)
Lockfile.new(p) do
block.call
end
end
|
#lock_file_name_for(log_path) ⇒ Object
51
52
53
|
# File 'lib/logbert/handlers/log_rotator.rb', line 51
def lock_file_name_for(log_path)
return "#{log_path}.lock"
end
|
#rotate_logs! ⇒ Object
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/logbert/handlers/log_rotator.rb', line 93
def rotate_logs!
performed_swap = false
lock do
unless already_rotated?
performed_swap = true
if @file_handle and not @file_handle.closed?
@file_handle.close
end
if File.exists? @path
FileUtils.mv @path, archive_destination
end
end
end
attach_to_logfile!
post_process if performed_swap
end
|
#rotation_required? ⇒ Boolean
55
56
57
|
# File 'lib/logbert/handlers/log_rotator.rb', line 55
def rotation_required?
return Time.now > @expiration_timestamp
end
|