class GroongaQueryLog::Command::CheckCrash::Checker

Public Class Methods

new(log_paths) click to toggle source
# File lib/groonga-query-log/command/check-crash.rb, line 114
def initialize(log_paths)
  split_log_paths(log_paths)
end

Public Instance Methods

check() click to toggle source
# File lib/groonga-query-log/command/check-crash.rb, line 118
def check
  processes = ProcessEnumerator.new(@general_log_paths)
  processes.each do |process|
    need_query_log_parsing = true
    if process.successfully_finished?
      need_query_log_parsing = false
      p [:process,
         :success,
         process.version,
         process.start_time.iso8601,
         process.end_time.iso8601,
         process.pid,
         process.start_log_path,
         process.end_log_path]
    elsif process.crashed?
      p [:process,
         :crashed,
         process.version,
         process.start_time.iso8601,
         process.end_time.iso8601,
         process.pid,
         process.start_log_path,
         process.end_log_path]
    else
      p [:process,
         :unfinished,
         process.version,
         process.start_time.iso8601,
         process.pid,
         process.start_log_path]
    end

    unless process.n_leaks.zero?
      p [:leak,
         process.version,
         process.n_leaks,
         process.end_time.iso8601,
         process.pid,
         process.end_log_path]
    end

    unless process.important_entries.empty?
      puts("Important entries:")
      process.important_entries.each_with_index do |entry, i|
        puts("#{entry.timestamp.iso8601}: " +
             "#{entry.log_level}: " +
             "#{entry.message}")
      end
    end

    next unless need_query_log_parsing

    start_time = process.start_time
    end_time = process.end_time
    @flushed = true
    @unflushed_statistics = []
    query_log_parser = Parser.new
    query_log_parser.parse_paths(@query_log_paths) do |statistic|
      next if statistic.start_time < start_time
      break if statistic.start_time > end_time
      check_query_log_statistic(query_log_parser.current_path,
                                statistic)
    end
    parsing_statistics = query_log_parser.parsing_statistics
    target_parsing_statistics = parsing_statistics.reject do |statistic|
      statistic.start_time < start_time
    end
    unless target_parsing_statistics.empty?
      puts("Running queries:")
      target_parsing_statistics.each do |statistic|
        puts("#{statistic.start_time.iso8601}:")
        puts(statistic.command.to_command_format(pretty_print: true))
      end
    end
    unless @unflushed_statistics.empty?
      puts("Unflushed commands in " +
           "#{start_time.iso8601}/#{end_time.iso8601}")
      @unflushed_statistics.each do |statistic|
        puts("#{statistic.start_time.iso8601}: #{statistic.raw_command}")
      end
    end
  end
end

Private Instance Methods

check_io_flush(io_flush) click to toggle source
# File lib/groonga-query-log/command/check-crash.rb, line 252
def check_io_flush(io_flush)
  # TODO: Improve flushed target detection.
  if io_flush.target_name
    if io_flush.recursive?
      @unflushed_statistics.reject! do |statistic|
        case statistic.command.command_name
        when "load"
          # TODO: Not enough
          statistic.command.table == io_flush.target_name
        when "delete"
          # TODO: Not enough
          statistic.command.table == io_flush.target_name
        when "truncate"
          # TODO: Not enough
          statistic.command.target_name == io_flush.target_name
        else
          false
        end
      end
    else
      @unflushed_statistics.reject! do |statistic|
        case statistic.command.command_name
        when /_create/
          true # TODO: Need io_flush for database
        else
          false
        end
      end
    end
  else
    if io_flush.recursive?
      @unflushed_statistics.clear
    else
      @unflushed_statistics.reject! do |statistic|
        case statistic.command.command_name
        when /_create\z/
          true # TODO: Need io_flush for the target
        when /_remove\z/, /_rename\z/
          true
        when "plugin_register", "plugin_unregister"
          true
        else
          false
        end
      end
    end
  end
  @flushed = @unflushed_statistics.empty?
end
check_query_log_statistic(path, statistic) click to toggle source
# File lib/groonga-query-log/command/check-crash.rb, line 218
def check_query_log_statistic(path, statistic)
  command = statistic.command
  return if command.nil?

  case command.command_name
  when "load"
    @flushed = false
    @unflushed_statistics << statistic
  when "delete"
    @flushed = false
    @unflushed_statistics << statistic
  when "truncate"
    @flushed = false
    @unflushed_statistics << statistic
  when "io_flush"
    check_io_flush(command)
  when "database_unmap"
    @unflushed_statistics.reject! do |statistic|
      command.name == "load"
    end
  when "table_list", "column_list"
    # ignore
  when /\Atable_/
    @flushed = false
    @unflushed_statistics << statistic
  when /\Acolumn_/
    @flushed = false
    @unflushed_statistics << statistic
  when "plugin_register", "plugin_unregister"
    @flushed = false
    @unflushed_statistics << statistic
  end
end
split_log_paths(log_paths) click to toggle source
# File lib/groonga-query-log/command/check-crash.rb, line 203
def split_log_paths(log_paths)
  @general_log_paths = []
  @query_log_paths = []
  log_paths.each do |log_path|
    sample_lines = GroongaLog::Input.open(log_path) do |log_file|
      log_file.each_line.take(10)
    end
    if sample_lines.any? {|line| Parser.target_line?(line)}
      @query_log_paths << log_path
    elsif sample_lines.any? {|line| GroongaLog::Parser.target_line?(line)}
      @general_log_paths << log_path
    end
  end
end