Class: Sawmill::Rotater::DateBasedLogFile
- Inherits:
-
Object
- Object
- Sawmill::Rotater::DateBasedLogFile
- Defined in:
- lib/sawmill/rotater/date_based_log_file.rb
Overview
A rotation strategy that produces log files with the date stamp in the file name. For example, you could set up an hourly log rotation that produces the following files:
rails.2009-10-09-22.log
rails.2009-10-09-23.log
rails.2009-10-10-00.log
rails.2009-10-10-01.log
etc...
The exact format depends on the rotation frequency, which could be anywhere from yearly to hourly. For settings less frequent than hourly, fewer fields will appear in the date stamp portion of the file name.
Class Method Summary collapse
-
.simple_uniquifier(opts_ = {}) ⇒ Object
Returns a simple uniquifier that inserts an incrementing number before the path suffix.
Instance Method Summary collapse
-
#before_write ⇒ Object
Implements the rotation strategy contract.
-
#close_handle(handle_, io_) ⇒ Object
Implements the rotation strategy contract.
-
#initialize(options_) ⇒ DateBasedLogFile
constructor
Create a new date-based log file rotation strategy.
-
#open_handle(handle_) ⇒ Object
Implements the rotation strategy contract.
-
#preferred_handle ⇒ Object
Implements the rotation strategy contract.
Constructor Details
#initialize(options_) ⇒ DateBasedLogFile
Create a new date-based log file rotation strategy.
Recognized options include:
:turnover_frequency-
How often the log files should turn over. Allowed values are:
:yearly,:monthly,:daily,:hourly, and:never. :basedir-
The base directory used if the filepath is a relative path. If not specified, the current working directory is used.
:path_prefix-
The logfile path prefix. In the filename “rails.2009-10-11.log”, the prefix is “rails”. If not specified, defaults to “sawmill”.
:path_suffix-
The logfile name prefix. In the filename “rails.2009-10-11.log”, the suffix is “.log”. If not specified, defaults to “.log”.
:uniquifier-
If provided, log files are never reopened. (That is, they are opened with ::File::CREAT | ::File::EXCL.) The value of this parameter must be a proc that returns an actual file name to attempt to open. This proc is called repeatedly until it either returns a file path that does not yet exist, or signals failure by returning nil. See the session on Uniquifiers below.
:local_datestamps-
If true, use the local timezone to create datestamps. The default is to use UTC.
Uniquifiers
DateBasedLogFile provides a facility for ensuring that log files are written to by only one process, by generating unique file names for log files. This facility is useful, for example, if you are deploying via Phusion Passenger where you may have a variable number of rails processes, and you want each process to own its own logfile so entries in log records are not interleaved.
To activate this feature, pass a proc to the :uniquifier option. When DateBasedLogFile wants to open a log file for writing, it first calls this proc. The proc should return a file path to try opening. DateBasedLogFile then tries to open the file with ::File::CREAT | ::File::EXCL, which will succeed only if the file has not already been created (e.g. by another process). If the file already exists, the proc will be called again, and repeatedly until it either returns a path that has not yet been created, or nil indicating that it has given up.
The proc is passed a single hash that provides information about what path to generate, as well as space for the proc to store any state it wishes to persist through the process. These keys are given to the proc by DateBasedLogFile. Any other keys are available for use by the proc.
:original_path-
The original file path generated by DateBasedLogFile, which would have been used if there were no uniquifier.
:last_path-
The last path generated by the proc, or nil if this is the first time this proc is called for a particular logfile.
:basedir-
The basedir of the DateBasedLogFile.
:path_prefix-
The path_prefix of the DateBasedLogFile.
:path_suffix-
The path_suffix of the DateBasedLogFile.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/sawmill/rotater/date_based_log_file.rb', line 128 def initialize() @turnover_frequency = [:turnover_frequency] || :none @basedir = [:basedir] || [:dirname] || ::Dir.getwd @prefix = [:path_prefix] || [:prefix] || 'sawmill' @suffix = [:path_suffix] || [:suffix] || '.log' @suffix = ".#{@suffix}" unless @suffix.length == 0 || @suffix[0,1] == '.' @uniquifier = [:uniquifier] @local_datestamps = [:local_datestamps] @date_pattern = case @turnover_frequency when :yearly then "%Y" when :monthly then "%Y-%m" when :daily then "%Y-%m-%d" when :hourly then "%Y-%m-%d-%H" else nil end end |
Class Method Details
.simple_uniquifier(opts_ = {}) ⇒ Object
Returns a simple uniquifier that inserts an incrementing number before the path suffix. i.e. if the non-uniquified filename is “rails.2009-10-11.log”, then these names are generated:
rails.2009-10-11.0.log
rails.2009-10-11.1.log
rails.2009-10-11.2.log
etc.
The following options are available:
:min_digits-
If provided, indicates the minimum number of digits for the unique number. For example, if :digits is set to 2, these names are generated:
rails.2009-10-11.00.log rails.2009-10-11.01.log rails.2009-10-11.02.log ... rails.2009-10-11.09.log rails.2009-10-11.10.log rails.2009-10-11.11.log ... rails.2009-10-11.99.log rails.2009-10-11.100.log rails.2009-10-11.101.log etc.The default is 1.
:start_value-
The first value for the unique number. Default is 0.
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/sawmill/rotater/date_based_log_file.rb', line 233 def simple_uniquifier(opts_={}) if (digits_ = opts_[:min_digits]) pattern_ = "%s.%0#{digits_.to_i}d%s" else pattern_ = "%s.%d%s" end ::Proc.new do |hash_| if hash_[:last_path] hash_[:value] += 1 else suffix_ = hash_[:path_suffix] orig_ = hash_[:original_path] suffix_len_ = suffix_.length if suffix_len_ > 0 && orig_[-suffix_len_, suffix_len_] == suffix_ pre_ = orig_[0, orig_.length - suffix_len_] post_ = suffix_ else pre_ = orig_ post_ = '' end hash_[:value] = opts_[:start_value].to_i hash_[:pre] = pre_ hash_[:post] = post_ end pattern_ % [hash_[:pre], hash_[:value], hash_[:post]] end end |
Instance Method Details
#before_write ⇒ Object
Implements the rotation strategy contract.
195 196 |
# File 'lib/sawmill/rotater/date_based_log_file.rb', line 195 def before_write end |
#close_handle(handle_, io_) ⇒ Object
Implements the rotation strategy contract.
188 189 190 |
# File 'lib/sawmill/rotater/date_based_log_file.rb', line 188 def close_handle(handle_, io_) io_.close end |
#open_handle(handle_) ⇒ Object
Implements the rotation strategy contract.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/sawmill/rotater/date_based_log_file.rb', line 162 def open_handle(handle_) path_ = ::File.(@date_pattern ? "#{@prefix}.#{handle_}#{@suffix}" : @prefix+@suffix, @basedir) file_ = nil if @uniquifier hash_ = {:path_prefix => @prefix, :path_suffix => @suffix, :basedir => @basedir, :original_path => path_.dup, :last_path => nil} until file_ path_ = @uniquifier.call(hash_) unless path_ raise Errors::NoUniqueLogFileError, "Could not find a unique log file path for #{hash_.inspect}" end begin file_ = ::File.open(path_, ::File::CREAT | ::File::EXCL | ::File::WRONLY) rescue ::Errno::EEXIST hash_[:last_path] = path_ end end else file_ = ::File.open(path_, 'a') end file_.sync = true file_ end |
#preferred_handle ⇒ Object
Implements the rotation strategy contract.
149 150 151 152 153 154 155 156 157 |
# File 'lib/sawmill/rotater/date_based_log_file.rb', line 149 def preferred_handle if @date_pattern time_ = ::Time.now time_.utc unless @local_datestamps time_.strftime(@date_pattern) else '' end end |