Class: FileSeries

Inherits:
Object
  • Object
show all
Defined in:
lib/file_series.rb

Overview

Writes to this logger will be directed to new files at a configurable frequency.

=> logger = FileSeries.new('.', :prefix=>'test', :rotate_every=>60)
=> logger.write("some message\n")

This will create a file like ‘test-1342477810-60.log’. A new file will be created every 60 seconds. You don’t need to do anything except keep calling logger.write().

Files are created as needed, so you won’t end up with lots of 0-length files. If you do see a recent 0-length file, it’s probably due to your OS buffering writes to the file.

Other configuration options:

:binary - boolean. If true, log files are opened in binary mode. (Useful for Marshal.dump)
:separator - string. Appended to each write. Defaults to \n. Use something else in :binary mode.

Constant Summary collapse

DEFAULT_DIR =
'.'
DEFAULT_PREFIX =
'log'
DEFAULT_FREQ =
60
DEFAULT_SEPARATOR =
"\n"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ FileSeries

Returns a new instance of FileSeries.



32
33
34
35
36
37
38
39
40
41
# File 'lib/file_series.rb', line 32

def initialize(options={})
  @dir = options[:dir] || DEFAULT_DIR
  @file = nil
  @current_ts = nil
  @filename_prefix = options[:prefix] || DEFAULT_PREFIX
  @rotate_freq = options[:rotate_every] || DEFAULT_FREQ #seconds
  @binary_mode = options[:binary]
  @separator = options[:separator] || DEFAULT_SEPARATOR
  @sync = options[:sync] || false
end

Instance Attribute Details

#current_tsObject

Returns the value of attribute current_ts.



30
31
32
# File 'lib/file_series.rb', line 30

def current_ts
  @current_ts
end

#dirObject

Returns the value of attribute dir.



28
29
30
# File 'lib/file_series.rb', line 28

def dir
  @dir
end

#fileObject

Returns the value of attribute file.



29
30
31
# File 'lib/file_series.rb', line 29

def file
  @file
end

#separatorObject

Returns the value of attribute separator.



27
28
29
# File 'lib/file_series.rb', line 27

def separator
  @separator
end

Instance Method Details

#complete_filesObject

get all files which match our pattern which are not current. (safe for consumption. no longer being written to.)



85
86
87
88
89
90
91
92
93
# File 'lib/file_series.rb', line 85

def complete_files
  current_file = filename

  Dir.glob(
    File.join(@dir, "#{@filename_prefix}-*-#{@rotate_freq}.log")
  ).select do |name|
    name != current_file
  end
end

#eachObject

enumerate over all the writes in a series, across all files.



96
97
98
99
100
101
102
# File 'lib/file_series.rb', line 96

def each
  complete_files.sort.each do |file|
    File.open(file,"r#{'b' if @binary_mode}").each_line(@separator) do |raw|
      yield raw
    end
  end
end

#filename(ts = nil) ⇒ Object

return a string filename for the logfile for the supplied timestamp. defaults to current time period.



78
79
80
81
# File 'lib/file_series.rb', line 78

def filename(ts=nil)
  ts ||= this_period
  File.join(@dir, "#{@filename_prefix}-#{Time.at(ts).utc.strftime('%Y%m%d-%H%M%SZ')}-#{@rotate_freq}.log")
end

#log_fileObject

return a File object for the current log file.



49
50
51
52
53
54
55
56
57
58
# File 'lib/file_series.rb', line 49

def log_file
  ts = this_period

  # if we're in a new time period, start writing to new file.
  if (! file) || (ts != current_ts)
    rotate(ts)
  end

  file
end

#rotate(ts = nil) ⇒ Object

close current file handle and open a new one for a new logging period. ts defaults to the current time period.



68
69
70
71
72
73
74
# File 'lib/file_series.rb', line 68

def rotate(ts=nil)
  ts ||= this_period
  @file.close if @file
  @file = File.open(filename(ts), "a#{'b' if @binary_mode}")
  @file.sync = @sync
  @current_ts = ts
end

#this_periodObject

compute the current time period.



61
62
63
64
# File 'lib/file_series.rb', line 61

def this_period
  t = Time.now.to_i
  t - (t % @rotate_freq)
end

#write(message) ⇒ Object

write something to the current log file.



44
45
46
# File 'lib/file_series.rb', line 44

def write(message)
  log_file.write(message.to_s + @separator)
end