class RailsLogDeinterleaver::Parser
Public Class Methods
new(filename, options={})
click to toggle source
# File lib/rails_log_deinterleaver/parser.rb, line 7 def initialize(filename, options={}) @filename = filename @options = options @options[:request_timeout] ||= 30 @options[:date_time_format] ||= "%b %d %H:%M:%S" @options[:start_request_regex] ||= /\[\d+\]: Started/ @options[:end_request_regex] ||= /\[\d+\]: Completed/ @options[:output] ||= $stdout @pids = {} end
Public Instance Methods
ensure_timeouts_logged()
click to toggle source
# File lib/rails_log_deinterleaver/parser.rb, line 75 def ensure_timeouts_logged expired_time = Time.now - @options[:request_timeout] # Loop over a clone of @pids because there is a chance that the parent thread # will want to add to the @pids Hash whilst this is running, triggering an exception. @pids.dup.each do |pid, details| if details[:last_seen_at] <= expired_time output_logs_for_pid(pid) end end sleep 1 self.ensure_timeouts_logged end
output_logs_for_pid(pid)
click to toggle source
Output all lines of the log for a single request, followed by an empty blank line.
# File lib/rails_log_deinterleaver/parser.rb, line 62 def output_logs_for_pid(pid) @options[:output].puts (@pids[pid][:lines] << '') @pids.delete(pid) end
pid_for_line(line)
click to toggle source
# File lib/rails_log_deinterleaver/parser.rb, line 67 def pid_for_line(line) line.match(/\[(\d+)\]/).captures.first.to_i end
process_line(line)
click to toggle source
# File lib/rails_log_deinterleaver/parser.rb, line 33 def process_line(line) # It is possible for the file to contain UTF-8 byte streams. Get rid of them here. # String#encode does not do anything if source and destination encoding are the same, # so encode to UTF-16 before converting back to UTF-8. line = line.encode('UTF-16', :invalid => :replace, :replace => '').encode('UTF-8') pid = pid_for_line(line) if line.match(@options[:start_request_regex]) if @pids[pid] # Already a request started but not finished for this pid. (Should be rare) # Log what we have to start a new request output_logs_for_pid(pid) end @pids[pid] = {lines: []} end return unless @pids[pid] @pids[pid][:last_seen_at] = Time.now @pids[pid][:lines].push(line) if line.match(@options[:end_request_regex]) output_logs_for_pid(pid) end end
run()
click to toggle source
# File lib/rails_log_deinterleaver/parser.rb, line 18 def run Thread.new do self.ensure_timeouts_logged end File.open(@filename, 'r:UTF-8') do |log| log.extend(File::Tail) log.interval = 0.1 log.backward(@options[:backward]) if @options[:backward] log.tail do |line| process_line line end end end
time_for_line(line)
click to toggle source
# File lib/rails_log_deinterleaver/parser.rb, line 71 def time_for_line(line) DateTime.strptime(line, @options[:date_time_format]) end