Permalink
Browse files

ST: Optionally define the header in the datefile adapter

  • Loading branch information...
1 parent 25b63d9 commit c4e97c00d6954c32a1b6d204cd40d11dc45f8749 @rudionrails committed Sep 20, 2012
Showing with 68 additions and 14 deletions.
  1. +46 −14 lib/yell/adapters/datefile.rb
  2. +22 −0 spec/yell/adapters/datefile_spec.rb
@@ -4,25 +4,32 @@ module Yell #:nodoc:
module Adapters #:nodoc:
# The +Datefile+ adapter is similar to the +File+ adapter. However, it
- # rotates the file at midnight.
+ # rotates the file at midnight (by default).
class Datefile < Yell::Adapters::File
# The default date pattern, e.g. "19820114" (14 Jan 1982)
DefaultDatePattern = "%Y%m%d"
# Metadata
- Metadata = lambda { |date, pattern| "# -*- #{date.iso8601} (#{date.to_f}) [#{pattern}] -*-" }
- MetadataRegexp = /^# -\*- (.+) \((\d+\.\d+)\) \[(.+)\] -\*-$/
+ Header = lambda { |date, pattern| "# -*- #{date.iso8601} (#{date.to_f}) [#{pattern}] -*-" }
+ HeaderRegexp = /^# -\*- (.+) \((\d+\.\d+)\) \[(.+)\] -\*-$/
setup do |options|
@date, @date_strftime = nil, nil # default; do not override --R
+ # check whether to write the log header (default true)
+ self.header = options.fetch(:header, true)
+
+ # check the date pattern on the filename (default "%Y%m%d")
self.date_pattern = options.fetch(:date_pattern, DefaultDatePattern)
- self.keep = options.fetch(:keep, 0)
+ # check whether to cleanup old files of the same pattern (default false)
+ self.keep = options.fetch(:keep, false)
+
+ # check whether to symlink the otiginal filename (default false)
self.symlink = if options.key?(:symlink_original_filename)
- Yell._deprecate( "0.13.3", "Use :symlink for symlinking to oriinal filename",
+ Yell._deprecate( "0.13.3", "Use :symlink for symlinking to original filename",
:before => "Yell.new { |l| l.adapter :datefile, :symlink_original_filename => true }",
:after => "Yell.new { |l| l.adapter :datefile, :symlink => true }"
)
@@ -43,7 +50,7 @@ class Datefile < Yell::Adapters::File
symlink! if symlink?
return if ::File.exist?( @filename ) # exit when file ready present
- stream.puts( Metadata.call(@date, date_pattern) )
+ stream.puts( Header.call(@date, date_pattern) ) if header? # write the header if applicable
end
close do
@@ -77,6 +84,15 @@ class Datefile < Yell::Adapters::File
# keep = 0
attr_accessor :keep
+ # You can suppress the first line of the logfile that contains
+ # the metadata. This is important upon rollover, because on *nix
+ # systems, it is not possible to determine the creation time of a file,
+ # on the last access time. The header compensates this.
+ #
+ # @example
+ # header = false
+ attr_accessor :header
+
private
@@ -98,21 +114,30 @@ def close?
false
end
- # Cleanup old files
+ # Removes old logfiles of the same date pattern.
+ #
+ # By reading the header of the files that match the date pattern, the
+ # adapter determines whether to remove them or not. If no header is present,
+ # it makes the best guess by checking the last access time (which may result
+ # in false cleanups).
def cleanup!
files = Dir[ @original_filename.sub( /(\.\w+)?$/, ".*\\1" ) ].map do |f|
- [ f, metadata_from(f).last ]
+ [ f, header_from(f).last ]
end.select do |(_, p)|
date_pattern == p
end
::File.unlink( *files.map(&:first)[0..-keep] )
end
+ # Cleanup old logfiles?
+ #
+ # @return [Boolean] true or false
def cleanup?
- keep.to_i > 0
+ !!keep && keep.to_i > 0
end
+ # Symlink the current filename to the original one.
def symlink!
# do nothing, because symlink is already correct
return if ::File.symlink?(@original_filename) && ::File.readlink(@original_filename) == @filename
@@ -121,17 +146,24 @@ def symlink!
::File.symlink( @filename, @original_filename )
end
- def symlink?
- !!symlink
- end
+ # Symlink the original filename?
+ #
+ # @return [Boolean] true or false
+ def symlink?; !!symlink; end
+
+ # Write header into the file?
+ #
+ # @return [Boolean] true or false
+ def header?; !!header; end
# Sets the filename with the `:date_pattern` appended to it.
def filename_from( date )
@original_filename.sub( /(\.\w+)?$/, ".#{date.strftime(date_pattern)}\\1" )
end
- def metadata_from( file )
- if m = ::File.open( file, &:readline ).match( MetadataRegexp )
+ # Fetch the header form the file
+ def header_from( file )
+ if m = ::File.open( file, &:readline ).match( HeaderRegexp )
[ Time.at( m[2].to_f ), m[3] ]
else
[ ::File.mtime( file ), "" ]
@@ -80,6 +80,28 @@
end
end
+ describe :header do
+ let( :adapter ) { Yell::Adapters::Datefile.new(:filename => filename) }
+ let( :header ) { File.open(datefile_filename, &:readline) }
+
+ before do
+ adapter.format = "%m" # easier to parse
+ end
+
+ it "should be written by default" do
+ adapter.write( event )
+
+ header.should match(Yell::Adapters::Datefile::HeaderRegexp)
+ end
+
+ it "should not be written when false" do
+ adapter.header = false
+ adapter.write( event )
+
+ header.should == "Hello World\n"
+ end
+ end
+
private

0 comments on commit c4e97c0

Please sign in to comment.