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