class Logging::Appenders::RollingFile::Roller

Not intended for general consumption, but the Roller class is used internally by the RollingFile appender to roll dem log files according to the user's desires.

Constants

RGXP

The magic regex for finding user-defined roller patterns.

Attributes

keep[R]
roll[RW]
roll_by[R]

Public Class Methods

new( name, opts ) click to toggle source

Create a new roller. See the RollingFile#initialize documentation for the list of options.

name - The appender name as a String opts - The options Hash

# File lib/logging/appenders/rolling_file.rb, line 261
def initialize( name, opts )
  # raise an error if a filename was not given
  @fn = opts.fetch(:filename, name)
  raise ArgumentError, 'no filename was given' if @fn.nil?

  if (m = RGXP.match @fn)
    @roll_by = ("#{m[2]}%d" == m[1]) ? :number : :date
  else
    age = opts.fetch(:age, nil)
    size = opts.fetch(:size, nil)

    @roll_by =
        case opts.fetch(:roll_by, nil)
        when 'number'; :number
        when 'date'; :date
        else
          (age && !size) ? :date : :number
        end

    ext = ::File.extname(@fn)
    bn  = ::File.join(::File.dirname(@fn), ::File.basename(@fn, ext))

    @fn = if :date == @roll_by && %w[daily weekly monthly].include?(age)
            "#{bn}{{.%Y%m%d}}#{ext}"
          elsif :date == @roll_by
            "#{bn}{{.%Y%m%d-%H%M%S}}#{ext}"
          else
            "#{bn}{{.%d}}#{ext}"
          end
  end

  @fn = ::File.expand_path(@fn)
  ::Logging::Appenders::File.assert_valid_logfile(filename)

  @roll = false
  @keep = opts.fetch(:keep, nil)
  @keep = Integer(keep) unless keep.nil?
end

Public Instance Methods

copy_file() click to toggle source

Returns the file name to use as the temporary copy location. We are using copy-and-truncate semantics for rolling files so that the IO file descriptor remains valid during rolling.

# File lib/logging/appenders/rolling_file.rb, line 313
def copy_file
  return @copy_file if defined? @copy_file
  @copy_file = filename + '._copy_'
  @copy_file.freeze
end
filename() click to toggle source

Returns the regular log file name without any roller text.

# File lib/logging/appenders/rolling_file.rb, line 304
def filename
  return @filename if defined? @filename
  @filename = (@fn =~ RGXP ?  @fn.sub(RGXP, '') : @fn.dup)
  @filename.freeze
end
format() click to toggle source

Returns the format String used to generate rolled file names. Depending upon the `roll_by` type (:date or :number), this String will be processed by `sprintf` or `Time#strftime`.

# File lib/logging/appenders/rolling_file.rb, line 331
def format
  return @format if defined? @format
  m = RGXP.match @fn
  @format = @fn.sub(RGXP, m[1])
  @format.freeze
end
glob() click to toggle source

Returns the glob pattern used to find rolled log files. We use this list for pruning older log files and doing the numbered rolling.

# File lib/logging/appenders/rolling_file.rb, line 321
def glob
  return @glob if defined? @glob
  m = RGXP.match @fn
  @glob = @fn.sub(RGXP, (m[2] ? "#{m[2]}*" : '*'))
  @glob.freeze
end
roll_by_date( files ) click to toggle source

Roll the list of log files optionally removing older files. The “older files” are determined by the mtime of the log files. So touching log files or otherwise messing with them will screw this up.

files - The Array of filename Strings

Returns nil

# File lib/logging/appenders/rolling_file.rb, line 394
def roll_by_date( files )
  length = files.length

  if keep && length >= keep
    files = files.sort do |a,b|
              a = ::File.mtime(a)
              b = ::File.mtime(b)
              b <=> a
            end
    files.last(length-keep+1).each { |fn| ::File.delete fn }
  end

  # rename the copied log file
  ::File.rename(copy_file, Time.now.strftime(format))
end
roll_by_number( files ) click to toggle source

Roll the list of log files optionally removing older files. The “older files” are determined by extracting the number from the log file name and order by the number.

files - The Array of filename Strings

Returns nil

# File lib/logging/appenders/rolling_file.rb, line 363
def roll_by_number( files )
  @number_rgxp ||= Regexp.new(@fn.sub(RGXP, '\2(\d+)'))

  # sort the files in reverse order based on their count number
  files = files.sort do |a,b|
            a = Integer(@number_rgxp.match(a)[1])
            b = Integer(@number_rgxp.match(b)[1])
            b <=> a
          end

  # for each file, roll its count number one higher
  files.each do |fn|
    cnt = Integer(@number_rgxp.match(fn)[1])
    if keep && cnt >= keep
      ::File.delete fn
      next
    end
    ::File.rename fn, sprintf(format, cnt+1)
  end

  # finally rename the copied log file
  ::File.rename(copy_file, sprintf(format, 1))
end
roll_files() click to toggle source

Roll the log files. This method will collect the list of rolled files and then pass that list to either `roll_by_number` or `roll_by_date` to perform the actual rolling.

Returns nil

# File lib/logging/appenders/rolling_file.rb, line 343
def roll_files
  return unless roll && ::File.exist?(copy_file)

  files = Dir.glob(glob)
  files.delete copy_file

  self.send "roll_by_#{roll_by}", files

  nil
ensure
  self.roll = false
end