tasks/request_log_analyzer.rake in request-log-analyzer-1.8.0 vs tasks/request_log_analyzer.rake in request-log-analyzer-1.8.1

- old
+ new

@@ -21,6 +21,108 @@ puts "" IO.popen("request-log-analyzer #{Rails.configuration.log_path} --output HTML --file #{output_file}") { |io| $stdout << io.read } end end + # Split a single logfile into multiple multiple logfiles based on PID information + # provided in the log lines. + # + # Usage: + # rake rla:split_log FILE=logfile + # + # Example: + # $> rake rla:split_log FILE=log/development.log + # Splitting the Rails log file by pid using the request-log-analyzer gem. + # + # Log file was split into the following files: + # split_log_development.catchall.log # <- log lines without a pid + # split_log_development.14634.log + # split_log_development.31277.log + # split_log_development.31279.log + # + # To analyze type: + # request-log-analyzer /log/split_log_development.*.log + desc "Split a logfile into seperate files by PID" + task :split do + + if ENV['FILE'] + logfile = ENV['FILE'] + if logfile.nil? + puts "Please provide a logfile to split" + exit(0) + elsif !File.exist?(logfile) + puts "the logfile name you provided can not be found" + exit(0) + end + + # Inline class def. Ugly, yet portable. + class LogSplitter + attr_reader :files_by_pid, :catchall, :filename, :rla_call_string + + # All generated files should contain this prefix to allow for easy glob file matches + PREFIX = 'split_log_' + # The logfile pattern that captures the pid, this will be log format specific. Using Logging::Logger + # we define: Logging::Layouts::Pattern(:pattern => "%d pid:%p [%c:%l] %m [%F:%L]\n") + # PID_PATTERN = Regexp.union(/.*\[(\d+)\]\:/, /pid:(\d+)/) + PID_PATTERN = /(?-mix:.*\[(\d+)\]\:)|(?-mix:pid:(\d+))/ # + + # Currently expects the filename to exist in the local directory for ease of implementation + def initialize(filename_to_split) + @filename = filename_to_split + directory = File.dirname(@filename) + '/' + directory = '' if @directory == './' + basename = @filename.split('/').last.gsub('.log', '') + @rla_call_string = "#{directory}#{PREFIX}#{basename}.*.log" + + @files_by_pid = + Hash.new {|hash, pid_key| hash[pid_key] = File.open("#{directory}#{PREFIX}#{basename}.#{pid_key}.log", 'w') } + @catchall = File.open("#{directory}#{PREFIX}#{basename}.catchall.log", 'w') + end + + def split + last_pid = nil + File.open(filename, 'r') do |f| + while(line = f.gets) + outfile = + if match_data = line.match(PID_PATTERN) + pid = match_data.captures[0] + last_pid = pid + files_by_pid[pid] + elsif last_pid + # handle cases where a single log call results in multiple lines of output. + files_by_pid[last_pid] + else + catchall + end + outfile.puts line + end + end + end + + def close_files + @files_by_pid.values.map(&:close) + @catchall.close + end + end + # End inline class def + + puts "Splitting the Rails log file by pid using the request-log-analyzer gem." + + log_splitter = LogSplitter.new(logfile) + log_splitter.split + log_splitter.close_files + + puts '' + puts '' + puts 'Log file was split into the following files:' + puts ' ' + log_splitter.catchall.path + log_splitter.files_by_pid.values.each {|f| puts ' ' + f.path } + puts '' + puts 'To analyze type:' + puts " request-log-analyzer #{log_splitter.rla_call_string}" + puts '' + puts '' + end + + end + end