module RequestLogAnalyzer
# The Logprocessor class is used to perform simple processing actions over log files.
# It will go over the log file/stream line by line, pass the line to a processor and
# write the result back to the output file or stream. The processor can alter the
# contents of the line, remain it intact or remove it altogether, based on the current
# file format
#
# Currently, one processors is supported:
# * :strip will remove all irrelevent lines (according to the file format) from the
# sources. A compact, information packed log will remain/.
#
class LogProcessor
attr_reader :mode, :options, :sources, :file_format
attr_accessor :output_file
# Builds a logprocessor instance from the arguments given on the command line
# command The command hat was used to start the log processor. This will set the
# processing mode. Currently, only :strip is supported.
# arguments The parsed command line arguments (a CommandLine::Arguments instance)
def self.build(command, arguments)
options = {
:discard_teaser_lines => arguments[:discard_teaser_lines],
:keep_junk_lines => arguments[:keep_junk_lines],
}
log_processor = RequestLogAnalyzer::LogProcessor.new(arguments[:format].to_sym, command, options)
log_processor.output_file = arguments[:output] if arguments[:output]
arguments.parameters.each do |input|
log_processor.sources << input
end
return log_processor
end
# Initializes a new LogProcessor instance.
# format The file format to use (e.g. :rails).
# mode The processing mode
# options A hash with options to take into account
def initialize(format, mode, options = {})
@options = options
@mode = mode
@sources = []
@file_format = format
$output_file = nil
end
# Processes input files by opening it and sending the filestream to process_io
,
# in which the actual processing is performed.
# file The file to process
def process_file(file)
File.open(file, 'r') { |file| process_io(file) }
end
# Processes an input stream by iteration over each line and processing it according to
# the current operation mode
# io The IO instance to process.
def process_io(io)
case mode
when :strip; io.each_line { |line| @output << strip_line(line) }
end
end
# Returns the line itself if the string matches any of the line definitions. If no match is
# found, an empty line is returned, which will strip the line from the output.
# line The line to strip
def strip_line(line)
file_format.line_definitions.any? { |name, definition| definition =~ line } ? line : ""
end
# Runs the log processing by setting up the output stream and iterating over all the
# input sources. Input sources can either be filenames (String instances) or IO streams
# (IO instances). The strings "-" and "STDIN" will be substituted for the $stdin variable.
def run!
if @output_file.nil?
@output = $stdout
else
@output = File.new(@output_file, 'a')
end
@sources.each do |source|
if source.kind_of?(String) && File.exist?(source)
process_file(source)
elsif source.kind_of?(IO)
process_io(source)
elsif ['-', 'STDIN'].include?(source)
process_io($stdin)
end
end
ensure
@output.close if @output.kind_of?(File)
end
end
end