[Groonga-commit] groonga/groonga [master] Move groonga-query-log-analyzer to groonga-query-log gem

Back to archive index

Haruka Yoshihara null+****@clear*****
Fri Dec 14 16:05:57 JST 2012


Haruka Yoshihara	2012-12-14 16:05:57 +0900 (Fri, 14 Dec 2012)

  New Revision: 110c5911447095cabdbdca802d85ed4a9b0b5d7e
  https://github.com/groonga/groonga/commit/110c5911447095cabdbdca802d85ed4a9b0b5d7e

  Log:
    Move groonga-query-log-analyzer to groonga-query-log gem
    
    groonga-query-log:
      https://github.com/groonga/groonga-query-log

  Removed files:
    tools/groonga-query-log-analyzer

  Deleted: tools/groonga-query-log-analyzer (+0 -1419) 100755
===================================================================
--- tools/groonga-query-log-analyzer    2012-12-14 12:40:02 +0900 (bb8aadb)
+++ /dev/null
@@ -1,1419 +0,0 @@
-#!/usr/bin/env ruby
-
-require 'English'
-require 'optparse'
-require 'cgi'
-require 'thread'
-require 'shellwords'
-require 'time'
-require 'erb'
-
-# For ruby 1.8.5 on CentOS 5.6.
-class String
-  unless method_defined?(:start_with?)
-    def start_with?(string)
-      /\A#{Regexp.escape(string)}/ =~ self
-    end
-  end
-end
-
-class Array
-  unless method_defined?(:each_slice)
-    def each_slice(n)
-      sub_elements = []
-      each do |element|
-        sub_elements << element
-        if sub_elements.size == n
-          yield(sub_elements)
-          sub_elements = []
-        end
-      end
-      yield(sub_elements) unless sub_elements.empty?
-    end
-  end
-end
-
-class GroongaQueryLogAnalyzer
-  class Error < StandardError
-  end
-
-  class UnsupportedReporter < Error
-  end
-
-  def initialize
-    setup_options
-  end
-
-  def run(argv=nil)
-    log_paths = @option_parser.parse!(argv || ARGV)
-
-    stream = @options[:stream]
-    dynamic_sort = @options[:dynamic_sort]
-    statistics = SizedStatistics.new
-    statistics.apply_options(@options)
-    parser = QueryLogParser.new
-    if stream
-      streamer = Streamer.new(create_reporter(statistics))
-      streamer.start
-      process_statistic = lambda do |statistic|
-        streamer << statistic
-      end
-    elsif dynamic_sort
-      process_statistic = lambda do |statistic|
-        statistics << statistic
-      end
-    else
-      full_statistics = []
-      process_statistic = lambda do |statistic|
-        full_statistics << statistic
-      end
-    end
-    if log_paths.empty?
-      parser.parse(ARGF, &process_statistic)
-    else
-      log_paths.each do |log_path|
-        File.open(log_path) do |log|
-          parser.parse(log, &process_statistic)
-        end
-      end
-    end
-    if stream
-      streamer.finish
-      return
-    end
-    statistics.replace(full_statistics) unless dynamic_sort
-
-    reporter = create_reporter(statistics)
-    reporter.apply_options(@options)
-    reporter.report
-  end
-
-  private
-  def setup_options
-    @options = {}
-    @options[:n_entries] = 10
-    @options[:order] = "-elapsed"
-    @options[:color] = :auto
-    @options[:output] = "-"
-    @options[:slow_operation_threshold] = 0.1
-    @options[:slow_response_threshold] = 0.2
-    @options[:reporter] = "console"
-    @options[:dynamic_sort] = true
-    @options[:stream] = false
-    @options[:report_summary] = true
-
-    @option_parser = OptionParser.new do |parser|
-      parser.banner += " LOG1 ..."
-
-      parser.on("-n", "--n-entries=N",
-                Integer,
-                "Show top N entries",
-                "(#{@options[:n_entries]})") do |n|
-        @options[:n_entries] = n
-      end
-
-      available_orders = ["elapsed", "-elapsed", "start-time", "-start-time"]
-      parser.on("--order=ORDER",
-                available_orders,
-                "Sort by ORDER",
-                "available values: [#{available_orders.join(', ')}]",
-                "(#{@options[:order]})") do |order|
-        @options[:order] = order
-      end
-
-      color_options = [
-        [:auto, :auto],
-        ["-", false],
-        ["no", false],
-        ["false", false],
-        ["+", true],
-        ["yes", true],
-        ["true", true],
-      ]
-      parser.on("--[no-]color=[auto]",
-                color_options,
-                "Enable color output",
-                "(#{@options[:color]})") do |color|
-        if color.nil?
-          @options[:color] = true
-        else
-          @options[:color] = color
-        end
-      end
-
-      parser.on("--output=PATH",
-                "Output to PATH.",
-                "'-' PATH means standard output.",
-                "(#{@options[:output]})") do |output|
-        @options[:output] = output
-      end
-
-      parser.on("--slow-operation-threshold=THRESHOLD",
-                Float,
-                "Use THRESHOLD seconds to detect slow operations.",
-                "(#{@options[:slow_operation_threshold]})") do |threshold|
-        @options[:slow_operation_threshold] = threshold
-      end
-
-      parser.on("--slow-response-threshold=THRESHOLD",
-                Float,
-                "Use THRESHOLD seconds to detect slow operations.",
-                "(#{@options[:sloq_response_threshold]})") do |threshold|
-        @options[:sloq_response_threshold] = threshold
-      end
-
-      available_reporters = ["console", "json", "html"]
-      parser.on("--reporter=REPORTER",
-                available_reporters,
-                "Reports statistics by REPORTER.",
-                "available values: [#{available_reporters.join(', ')}]",
-                "(#{@options[:reporter]})") do |reporter|
-        @options[:reporter] = reporter
-      end
-
-      parser.on("--[no-]dynamic-sort",
-                "Sorts dynamically.",
-                "Memory and CPU usage reduced for large query log.",
-                "(#{@options[:dynamic_sort]})") do |sort|
-        @options[:dynamic_sort] = sort
-      end
-
-      parser.on("--[no-]stream",
-                "Outputs analyzed query on the fly.",
-                "NOTE: --n-entries and --order are ignored.",
-                "(#{@options[:stream]})") do |stream|
-        @options[:stream] = stream
-      end
-
-      parser.on("--[no-]report-summary",
-                "Reports summary at the end.",
-                "(#{@options[:report_summary]})") do |report_summary|
-        @options[:report_summary] = report_summary
-      end
-    end
-
-    def create_reporter(statistics)
-      case @options[:reporter]
-      when "json"
-        require 'json'
-        JSONQueryLogReporter.new(statistics)
-      when "html"
-        HTMLQueryLogReporter.new(statistics)
-      else
-        ConsoleQueryLogReporter.new(statistics)
-      end
-    end
-
-    def create_stream_reporter
-      case @options[:reporter]
-      when "json"
-        require 'json'
-        StreamJSONQueryLogReporter.new
-      when "html"
-        raise UnsupportedReporter, "HTML reporter doesn't support --stream."
-      else
-        StreamConsoleQueryLogReporter.new
-      end
-    end
-  end
-
-  class Command
-    class << self
-      @@registered_commands = {}
-      def register(name, klass)
-        @@registered_commands[name] = klass
-      end
-
-      def parse(input)
-        if input.start_with?("/d/")
-          parse_uri_path(input)
-        else
-          parse_command_line(input)
-        end
-      end
-
-      private
-      def parse_uri_path(path)
-        name, parameters_string = path.split(/\?/, 2)
-        parameters = {}
-        parameters_string.split(/&/).each do |parameter_string|
-          key, value = parameter_string.split(/\=/, 2)
-          parameters[key] = CGI.unescape(value)
-        end
-        name = name.gsub(/\A\/d\//, '')
-        name, output_type = name.split(/\./, 2)
-        parameters["output_type"] = output_type if output_type
-        command_class = @@registered_commands[name] || self
-        command_class.new(name, parameters)
-      end
-
-      def parse_command_line(command_line)
-        name, *options = Shellwords.shellwords(command_line)
-        parameters = {}
-        options.each_slice(2) do |key, value|
-          parameters[key.gsub(/\A--/, '')] = value
-        end
-        command_class = @@registered_commands[name] || self
-        command_class.new(name, parameters)
-      end
-    end
-
-    attr_reader :name, :parameters
-    def initialize(name, parameters)
-      @name = name
-      @parameters = parameters
-    end
-
-    def ==(other)
-      other.is_a?(self.class) and
-        @name == other.name and
-        @parameters == other.parameters
-    end
-  end
-
-  class SelectCommand < Command
-    register("select", self)
-
-    def sortby
-      @parameters["sortby"]
-    end
-
-    def scorer
-      @parameters["scorer"]
-    end
-
-    def query
-      @parameters["query"]
-    end
-
-    def filter
-      @parameters["filter"]
-    end
-
-    def conditions
-      @conditions ||= filter.split(/(?:&&|&!|\|\|)/).collect do |condition|
-        condition = condition.strip
-        condition = condition.gsub(/\A[\s\(]*/, '')
-        condition = condition.gsub(/[\s\)]*\z/, '') unless /\(/ =~ condition
-        condition
-      end
-    end
-
-    def drilldowns
-      @drilldowns ||= (@parameters["drilldown"] || "").split(/\s*,\s*/)
-    end
-
-    def output_columns
-      @parameters["output_columns"]
-    end
-  end
-
-  class Statistic
-    attr_reader :context_id, :start_time, :raw_command
-    attr_reader :elapsed, :return_code
-    attr_accessor :slow_operation_threshold, :slow_response_threshold
-    def initialize(context_id)
-      @context_id = context_id
-      @start_time = nil
-      @command = nil
-      @raw_command = nil
-      @operations = []
-      @elapsed = nil
-      @return_code = 0
-      @slow_operation_threshold = 0.1
-      @slow_response_threshold = 0.2
-    end
-
-    def start(start_time, command)
-      @start_time = start_time
-      @raw_command = command
-    end
-
-    def finish(elapsed, return_code)
-      @elapsed = elapsed
-      @return_code = return_code
-    end
-
-    def command
-      @command ||= Command.parse(@raw_command)
-    end
-
-    def elapsed_in_seconds
-      nano_seconds_to_seconds(@elapsed)
-    end
-
-    def last_time
-      @start_time + elapsed_in_seconds
-    end
-
-    def slow?
-      elapsed_in_seconds >= @slow_response_threshold
-    end
-
-    def each_operation
-      previous_elapsed = 0
-      ensure_parse_command
-      operation_context_context = {
-        :filter_index => 0,
-        :drilldown_index => 0,
-      }
-      @operations.each_with_index do |operation, i|
-        relative_elapsed = operation[:elapsed] - previous_elapsed
-        relative_elapsed_in_seconds = nano_seconds_to_seconds(relative_elapsed)
-        previous_elapsed = operation[:elapsed]
-        parsed_operation = {
-          :i => i,
-          :elapsed => operation[:elapsed],
-          :elapsed_in_seconds => nano_seconds_to_seconds(operation[:elapsed]),
-          :relative_elapsed => relative_elapsed,
-          :relative_elapsed_in_seconds => relative_elapsed_in_seconds,
-          :name => operation[:name],
-          :context => operation_context(operation[:name],
-                                        operation_context_context),
-          :n_records => operation[:n_records],
-          :slow? => slow_operation?(relative_elapsed_in_seconds),
-        }
-        yield parsed_operation
-      end
-    end
-
-    def add_operation(operation)
-      @operations << operation
-    end
-
-    def operations
-      _operations = []
-      each_operation do |operation|
-        _operations << operation
-      end
-      _operations
-    end
-
-    def select_command?
-      command.name == "select"
-    end
-
-    private
-    def nano_seconds_to_seconds(nano_seconds)
-      nano_seconds / 1000.0 / 1000.0 / 1000.0
-    end
-
-    def operation_context(label, context)
-      case label
-      when "filter"
-        if @select_command.query and context[:query_used].nil?
-          context[:query_used] = true
-          "query: #{@select_command.query}"
-        else
-          index = context[:filter_index]
-          context[:filter_index] += 1
-          @select_command.conditions[index]
-        end
-      when "sort"
-        @select_command.sortby
-      when "score"
-        @select_command.scorer
-      when "output"
-        @select_command.output_columns
-      when "drilldown"
-        index = context[:drilldown_index]
-        context[:drilldown_index] += 1
-        @select_command.drilldowns[index]
-      else
-        nil
-      end
-    end
-
-    def ensure_parse_command
-      return unless select_command?
-      @select_command = SelectCommand.parse(@raw_command)
-    end
-
-    def slow_operation?(elapsed)
-      elapsed >= @slow_operation_threshold
-    end
-  end
-
-  class SizedGroupedOperations < Array
-    def initialize
-      @max_size = 10
-      @sorter = create_sorter
-    end
-
-    def apply_options(options)
-      @max_size = options[:n_entries]
-    end
-
-    def each
-      i = 0
-      super do |grouped_operation|
-        break if i >= @max_size
-        i += 1
-        yield(grouped_operation)
-      end
-    end
-
-    def <<(operation)
-      each do |grouped_operation|
-        if grouped_operation[:name] == operation[:name] and
-            grouped_operation[:context] == operation[:context]
-          elapsed = operation[:relative_elapsed_in_seconds]
-          grouped_operation[:total_elapsed] += elapsed
-          grouped_operation[:n_operations] += 1
-          replace(sort_by(&@sorter))
-          return self
-        end
-      end
-
-      grouped_operation = {
-        :name => operation[:name],
-        :context => operation[:context],
-        :n_operations => 1,
-        :total_elapsed => operation[:relative_elapsed_in_seconds],
-      }
-      buffer_size = @max_size * 100
-      if size < buffer_size
-        super(grouped_operation)
-        replace(sort_by(&@sorter))
-      else
-        if****@sorte*****(grouped_operation) < @sorter.call(last)
-          super(grouped_operation)
-          sorted_operations = sort_by(&@sorter)
-          sorted_operations.pop
-          replace(sorted_operations)
-        end
-      end
-      self
-    end
-
-    private
-    def create_sorter
-      lambda do |grouped_operation|
-        -grouped_operation[:total_elapsed]
-      end
-    end
-  end
-
-  class SizedStatistics < Array
-    attr_reader :n_responses, :n_slow_responses, :n_slow_operations
-    attr_reader :slow_operations, :total_elapsed
-    attr_reader :start_time, :last_time
-    attr_accessor :slow_operation_threshold, :slow_response_threshold
-    def initialize
-      @max_size = 10
-      self.order = "-elapsed"
-      @slow_operation_threshold = 0.1
-      @slow_response_threshold = 0.2
-      @start_time = nil
-      @last_time = nil
-      @n_responses = 0
-      @n_slow_responses = 0
-      @n_slow_operations = 0
-      @slow_operations = SizedGroupedOperations.new
-      @total_elapsed = 0
-      @collect_slow_statistics = true
-    end
-
-    def order=(new_order)
-      @order = new_order
-      @sorter = create_sorter
-    end
-
-    def apply_options(options)
-      @max_size = options[:n_entries] || @max_size
-      self.order = options[:order] || @order
-      @slow_operation_threshold =
-        options[:slow_operation_threshold] || @slow_operation_threshold
-      @slow_response_threshold =
-        options[:slow_response_threshold] || @slow_response_threshold
-      unless options[:report_summary].nil?
-        @collect_slow_statistics = options[:report_summary]
-      end
-      @slow_operations.apply_options(options)
-    end
-
-    def <<(statistic)
-      update_statistic(statistic)
-      if size < @max_size
-        super(statistic)
-        replace(self)
-      else
-        if****@sorte*****(statistic) < @sorter.call(last)
-          super(statistic)
-          replace(self)
-        end
-      end
-      self
-    end
-
-    def replace(other)
-      sorted_other = other.sort_by(&@sorter)
-      if sorted_other.size > @max_size
-        super(sorted_other[0, @max_size])
-      else
-        super(sorted_other)
-      end
-    end
-
-    def responses_per_second
-      _period = period
-      if _period.zero?
-        0
-      else
-        @n_responses.to_f / _period
-      end
-    end
-
-    def slow_response_ratio
-      if @n_responses.zero?
-        0
-      else
-        (@n_slow_responses.to_f / @n_responses) * 100
-      end
-    end
-
-    def period
-      if @start_time and @last_time
-        @last_time - @start_time
-      else
-        0
-      end
-    end
-
-    def each_slow_operation
-      @slow_operations.each do |grouped_operation|
-        total_elapsed = grouped_operation[:total_elapsed]
-        n_operations = grouped_operation[:n_operations]
-        ratios = {
-          :total_elapsed_ratio => total_elapsed / @total_elapsed * 100,
-          :n_operations_ratio => n_operations / @n_slow_operations.to_f * 100,
-        }
-        yield(grouped_operation.merge(ratios))
-      end
-    end
-
-    private
-    def create_sorter
-      case @order
-      when "-elapsed"
-        lambda do |statistic|
-          -statistic.elapsed
-        end
-      when "elapsed"
-        lambda do |statistic|
-          statistic.elapsed
-        end
-      when "-start-time"
-        lambda do |statistic|
-          -statistic.start_time
-        end
-      else
-        lambda do |statistic|
-          statistic.start_time
-        end
-      end
-    end
-
-    def update_statistic(statistic)
-      statistic.slow_response_threshold = @slow_response_threshold
-      statistic.slow_operation_threshold = @slow_operation_threshold
-      @start_time ||= statistic.start_time
-      @start_time = [@start_time, statistic.start_time].min
-      @last_time ||= statistic.last_time
-      @last_time = [@last_time, statistic.last_time].max
-      @n_responses += 1
-      @total_elapsed += statistic.elapsed_in_seconds
-      return unless @collect_slow_statistics
-      if statistic.slow?
-        @n_slow_responses += 1
-        if statistic.select_command?
-          statistic.each_operation do |operation|
-            next unless operation[:slow?]
-            @n_slow_operations += 1
-            @slow_operations << operation
-          end
-        end
-      end
-    end
-  end
-
-  class QueryLogParser
-    def initialize
-      @mutex = Mutex.new
-    end
-
-    def parse(input, &block)
-      current_statistics = {}
-      input.each_line do |line|
-        case line
-        when /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)\.(\d+)\|(.+?)\|([>:<])/
-          year, month, day, hour, minutes, seconds, micro_seconds =
-            $1, $2, $3, $4, $5, $6, $7
-          context_id = $8
-          type = $9
-          rest = $POSTMATCH.strip
-          time_stamp = Time.local(year, month, day, hour, minutes, seconds,
-                                  micro_seconds)
-          parse_line(current_statistics,
-                     time_stamp, context_id, type, rest, &block)
-        end
-      end
-    end
-
-    private
-    def parse_line(current_statistics,
-                   time_stamp, context_id, type, rest, &block)
-      case type
-      when ">"
-        statistic = Statistic.new(context_id)
-        statistic.start(time_stamp, rest)
-        current_statistics[context_id] = statistic
-      when ":"
-        return unless /\A(\d+) (.+)\((\d+)\)/ =~ rest
-        elapsed = $1
-        name = $2
-        n_records = $3.to_i
-        statistic = current_statistics[context_id]
-        return if statistic.nil?
-        statistic.add_operation(:name => name,
-                                :elapsed => elapsed.to_i,
-                                :n_records => n_records)
-      when "<"
-        return unless /\A(\d+) rc=(\d+)/ =~ rest
-        elapsed = $1
-        return_code = $2
-        statistic = current_statistics.delete(context_id)
-        return if statistic.nil?
-        statistic.finish(elapsed.to_i, return_code.to_i)
-        block.call(statistic)
-      end
-    end
-  end
-
-  class Streamer
-    def initialize(reporter)
-      @reporter = reporter
-    end
-
-    def start
-      @reporter.start
-    end
-
-    def <<(statistic)
-      @reporter.report_statistic(statistic)
-    end
-
-    def finish
-      @reporter.finish
-    end
-  end
-
-  class QueryLogReporter
-    include Enumerable
-
-    attr_reader :output
-    def initialize(statistics)
-      @statistics = statistics
-      @report_summary = true
-      @output = $stdout
-    end
-
-    def apply_options(options)
-      self.output = options[:output] || @output
-      unless options[:report_summary].nil?
-        @report_summary = options[:report_summary]
-      end
-    end
-
-    def output=(output)
-      @output = output
-      @output = $stdout if @output == "-"
-    end
-
-    def each
-      @statistics.each do |statistic|
-        yield statistic
-      end
-    end
-
-    def report
-      setup do
-        report_summary if @report_summary
-        report_statistics
-      end
-    end
-
-    def report_statistics
-      each do |statistic|
-        report_statistic(statistic)
-      end
-    end
-
-    private
-    def setup
-      setup_output do
-        start
-        yield
-        finish
-      end
-    end
-
-    def setup_output
-      original_output = @output
-      if****@outpu*****_a?(String)
-        File.open(@output, "w") do |output|
-          @output = output
-          yield(@output)
-        end
-      else
-        yield(@output)
-      end
-    ensure
-      @output = original_output
-    end
-
-    def write(*args)
-      @output.write(*args)
-    end
-
-    def format_time(time)
-      if time.nil?
-        "NaN"
-      else
-        time.strftime("%Y-%m-%d %H:%M:%S.%u")
-      end
-    end
-  end
-
-  class ConsoleQueryLogReporter < QueryLogReporter
-    class Color
-      NAMES = ["black", "red", "green", "yellow",
-               "blue", "magenta", "cyan", "white"]
-
-      attr_reader :name
-      def initialize(name, options={})
-        @name = name
-        @foreground = options[:foreground]
-        @foreground = true if****@foreg*****?
-        @intensity = options[:intensity]
-        @bold = options[:bold]
-        @italic = options[:italic]
-        @underline = options[:underline]
-      end
-
-      def foreground?
-        @foreground
-      end
-
-      def intensity?
-        @intensity
-      end
-
-      def bold?
-        @bold
-      end
-
-      def italic?
-        @italic
-      end
-
-      def underline?
-        @underline
-      end
-
-      def ==(other)
-        self.class === other and
-          [name, foreground?, intensity?,
-           bold?, italic?, underline?] ==
-          [other.name, other.foreground?, other.intensity?,
-           other.bold?, other.italic?, other.underline?]
-      end
-
-      def sequence
-        sequence = []
-        if @name == "none"
-        elsif @name == "reset"
-          sequence << "0"
-        else
-          foreground_parameter = foreground? ? 3 : 4
-          foreground_parameter += 6 if intensity?
-          sequence << "#{foreground_parameter}#{NAMES.index(@name)}"
-        end
-        sequence << "1" if bold?
-        sequence << "3" if italic?
-        sequence << "4" if underline?
-        sequence
-      end
-
-      def escape_sequence
-        "\e[#{sequence.join(';')}m"
-      end
-
-      def +(other)
-        MixColor.new([self, other])
-      end
-    end
-
-    class MixColor
-      attr_reader :colors
-      def initialize(colors)
-        @colors = colors
-      end
-
-      def sequence
-        @colors.inject([]) do |result, color|
-          result + color.sequence
-        end
-      end
-
-      def escape_sequence
-        "\e[#{sequence.join(';')}m"
-      end
-
-      def +(other)
-        self.class.new([self, other])
-      end
-
-      def ==(other)
-        self.class === other and colors == other.colors
-      end
-    end
-
-    def initialize(statistics)
-      super
-      @color = :auto
-      @reset_color = Color.new("reset")
-      @color_schema = {
-        :elapsed => {:foreground => :white, :background => :green},
-        :time => {:foreground => :white, :background => :cyan},
-        :slow => {:foreground => :white, :background => :red},
-      }
-    end
-
-    def apply_options(options)
-      super
-      @color = options[:color] || @color
-    end
-
-    def report_statistics
-      write("\n")
-      write("Slow Queries:\n")
-      super
-    end
-
-    def report_statistic(statistic)
-      @index += 1
-      write("%*d) %s" % [@digit, @index, format_heading(statistic)])
-      report_parameters(statistic)
-      report_operations(statistic)
-    end
-
-    def start
-      @index = 0
-      if****@stati*****?
-        @digit = 1
-      else
-        @digit = Math.log10(@statistics.size).truncate + 1
-      end
-    end
-
-    def finish
-    end
-
-    private
-    def setup
-      super do
-        setup_color do
-          yield
-        end
-      end
-    end
-
-    def report_summary
-      write("Summary:\n")
-      write("  Threshold:\n")
-      write("    slow response     : #{@statistics.slow_response_threshold}\n")
-      write("    slow operation    : #{@statistics.slow_operation_threshold}\n")
-      write("  # of responses      : #{@statistics.n_responses}\n")
-      write("  # of slow responses : #{@statistics.n_slow_responses}\n")
-      write("  responses/sec       : #{@statistics.responses_per_second}\n")
-      write("  start time          : #{format_time(@statistics.start_time)}\n")
-      write("  last time           : #{format_time(@statistics.last_time)}\n")
-      write("  period(sec)         : #{@statistics.period}\n")
-      slow_response_ratio =****@stati*****_response_ratio
-      write("  slow response ratio : %5.3f%%\n" % slow_response_ratio)
-      write("  total response time : #{@statistics.total_elapsed}\n")
-      report_slow_operations
-    end
-
-    def report_slow_operations
-      write("  Slow Operations:\n")
-      total_elapsed_digit = nil
-      total_elapsed_decimal_digit = 6
-      n_operations_digit = nil
-      @statistics.each_slow_operation do |grouped_operation|
-        total_elapsed = grouped_operation[:total_elapsed]
-        total_elapsed_digit ||= Math.log10(total_elapsed).truncate + 1
-        n_operations = grouped_operation[:n_operations]
-        n_operations_digit ||= Math.log10(n_operations).truncate + 1
-        parameters = [total_elapsed_digit + 1 + total_elapsed_decimal_digit,
-                      total_elapsed_decimal_digit,
-                      total_elapsed,
-                      grouped_operation[:total_elapsed_ratio],
-                      n_operations_digit,
-                      n_operations,
-                      grouped_operation[:n_operations_ratio],
-                      grouped_operation[:name],
-                      grouped_operation[:context]]
-        write("    [%*.*f](%5.2f%%) [%*d](%5.2f%%) %9s: %s\n" % parameters)
-      end
-    end
-
-    def report_parameters(statistic)
-      command = statistic.command
-      write("  name: <#{command.name}>\n")
-      write("  parameters:\n")
-      command.parameters.each do |key, value|
-        write("    <#{key}>: <#{value}>\n")
-      end
-    end
-
-    def report_operations(statistic)
-      statistic.each_operation do |operation|
-        relative_elapsed_in_seconds = operation[:relative_elapsed_in_seconds]
-        formatted_elapsed = "%8.8f" % relative_elapsed_in_seconds
-        if operation[:slow?]
-          formatted_elapsed = colorize(formatted_elapsed, :slow)
-        end
-        operation_report = " %2d) %s: %10s" % [operation[:i] + 1,
-                                               formatted_elapsed,
-                                               operation[:name]]
-        if operation[:n_records]
-          operation_report << "(%6d)" % operation[:n_records]
-        else
-          operation_report << "(%6s)" % ""
-        end
-        context = operation[:context]
-        if context
-          context = colorize(context, :slow) if operation[:slow?]
-          operation_report << " " << context
-        end
-        write("#{operation_report}\n")
-      end
-      write("\n")
-    end
-
-    def guess_color_availability(output)
-      return false unless output.tty?
-      case ENV["TERM"]
-      when /term(?:-color)?\z/, "screen"
-        true
-      else
-        return true if ENV["EMACS"] == "t"
-        false
-      end
-    end
-
-    def setup_color
-      color = @color
-      @color = guess_color_availability(@output) if @color == :auto
-      yield
-    ensure
-      @color = color
-    end
-
-    def format_heading(statistic)
-      formatted_elapsed = colorize("%8.8f" % statistic.elapsed_in_seconds,
-                                   :elapsed)
-      "[%s-%s (%s)](%d): %s" % [format_time(statistic.start_time),
-                                format_time(statistic.last_time),
-                                formatted_elapsed,
-                                statistic.return_code,
-                                statistic.raw_command]
-    end
-
-    def format_time(time)
-      colorize(super, :time)
-    end
-
-    def colorize(text, schema_name)
-      return text unless @color
-      options = @color_schema[schema_name]
-      color = Color.new("none")
-      if options[:foreground]
-        color += Color.new(options[:foreground].to_s, :bold => true)
-      end
-      if options[:background]
-        color += Color.new(options[:background].to_s, :foreground => false)
-      end
-      "%s%s%s" % [color.escape_sequence, text, @reset_color.escape_sequence]
-    end
-  end
-
-  class JSONQueryLogReporter < QueryLogReporter
-    def report_statistic(statistic)
-      write(",") if @index > 0
-      write("\n")
-      write(format_statistic(statistic))
-      @index += 1
-    end
-
-    def start
-      @index = 0
-      write("[")
-    end
-
-    def finish
-      write("\n")
-      write("]\n")
-    end
-
-    def report_summary
-      # TODO
-    end
-
-    private
-    def format_statistic(statistic)
-      data = {
-        "start_time" => statistic.start_time.to_i,
-        "last_time" => statistic.last_time.to_i,
-        "elapsed" => statistic.elapsed_in_seconds,
-        "return_code" => statistic.return_code,
-      }
-      command = statistic.command
-      parameters = command.parameters.collect do |key, value|
-        {"key" => key, "value" => value}
-      end
-      data["command"] = {
-        "raw" => statistic.raw_command,
-        "name" => command.name,
-        "parameters" => parameters,
-      }
-      operations = []
-      statistic.each_operation do |operation|
-        operation_data = {}
-        operation_data["name"] = operation[:name]
-        operation_data["relative_elapsed"] = operation[:relative_elapsed_in_seconds]
-        operation_data["context"] = operation[:context]
-        operations << operation_data
-      end
-      data["operations"] = operations
-      JSON.generate(data)
-    end
-  end
-
-  class HTMLQueryLogReporter < QueryLogReporter
-    include ERB::Util
-
-    def report_statistic(statistic)
-      write(",") if @index > 0
-      write("\n")
-      write(format_statistic(statistic))
-      @index += 1
-    end
-
-    def start
-      write(header)
-    end
-
-    def finish
-      write(footer)
-    end
-
-    def report_summary
-      summary_html = erb(<<-EOH, __LINE__ + 1, binding)
-    <h2>Summary</h2>
-    <div class="summary">
-<%= analyze_parameters %>
-<%= metrics %>
-<%= slow_operations %>
-    </div>
-      EOH
-      write(summary_html)
-    end
-
-    def report_statistics
-      write(statistics_header)
-      super
-      write(statistics_footer)
-    end
-
-    def report_statistic(statistic)
-      command = statistic.command
-      statistic_html = erb(<<-EOH, __LINE__ + 1, binding)
-      <div class="statistic-heading">
-        <h3>Command</h3>
-        <div class="metrics">
-          [<%= format_time(statistic.start_time) %>
-           -
-           <%= format_time(statistic.last_time) %>
-           (<%= format_elapsed(statistic.elapsed_in_seconds,
-                               :slow? => statistic.slow?) %>)]
-          (<%= span({:class => "return-code"}, h(statistic.return_code)) %>)
-        </div>
-        <%= div({:class => "raw-command"}, h(statistic.raw_command)) %>
-      </div>
-      <div class="statistic-parameters">
-        <h3>Parameters</h3>
-        <dl>
-          <dt>name</dt>
-          <dd><%= h(command.name) %></dd>
-<% command.parameters.each do |key, value| %>
-          <dt><%= h(key) %></dt>
-          <dd><%= h(value) %></dd>
-<% end %>
-         </dl>
-      </div>
-      <div class="statistic-operations">
-        <h3>Operations</h3>
-        <ol>
-<% statistic.each_operation do |operation| %>
-          <li>
-            <%= format_elapsed(operation[:relative_elapsed_in_seconds],
-                               :slow? => operation[:slow?]) %>:
-            <%= span({:class => "name"}, h(operation[:name])) %>:
-            <%= span({:class => "context"}, h(operation[:context])) %>
-          </li>
-<% end %>
-        </ol>
-      </div>
-      EOH
-      write(statistic_html)
-    end
-
-    private
-    def erb(content, line, _binding=nil)
-      _erb = ERB.new(content, nil, "<>")
-      eval(_erb.src, _binding || binding, __FILE__, line)
-    end
-
-    def header
-      erb(<<-EOH, __LINE__ + 1)
-<html>
-  <head>
-    <title>groonga query analyzer</title>
-    <style>
-table,
-table tr,
-table tr th,
-table tr td
-{
-  border: 1px solid black;
-}
-
-span.slow
-{
-  color: red;
-}
-
-div.parameters
-{
-  float: left;
-  padding: 2em;
-}
-
-div.parameters h3
-{
-  text-align: center;
-}
-
-div.parameters table
-{
-  margin-right: auto;
-  margin-left: auto;
-}
-
-div.statistics
-{
-  clear: both;
-}
-
-td.elapsed,
-td.ratio,
-td.n
-{
-  text-align: right;
-}
-
-td.name
-{
-  text-align: center;
-}
-    </style>
-  </head>
-  <body>
-    <h1>groonga query analyzer</h1>
-      EOH
-    end
-
-    def footer
-      erb(<<-EOH, __LINE__ + 1)
-  </body>
-</html>
-      EOH
-    end
-
-    def statistics_header
-      erb(<<-EOH, __LINE__ + 1)
-    <h2>Slow Queries</h2>
-    <div>
-      EOH
-    end
-
-    def statistics_footer
-      erb(<<-EOH, __LINE__ + 1)
-    </div>
-      EOH
-    end
-
-    def analyze_parameters
-      erb(<<-EOH, __LINE__ + 1)
-      <div class="parameters">
-        <h3>Analyze Parameters</h3>
-        <table>
-          <tr><th>Name</th><th>Value</th></tr>
-          <tr>
-            <th>Slow response threshold</th>
-            <td><%= h(@statistics.slow_response_threshold) %>sec</td>
-          </tr>
-          <tr>
-            <th>Slow operation threshold</th>
-            <td><%= h(@statistics.slow_operation_threshold) %>sec</td>
-          </tr>
-        </table>
-      </div>
-      EOH
-    end
-
-    def metrics
-      erb(<<-EOH, __LINE__ + 1)
-      <div class="parameters">
-        <h3>Metrics</h3>
-        <table>
-          <tr><th>Name</th><th>Value</th></tr>
-          <tr>
-            <th># of responses</th>
-            <td><%= h(@statistics.n_responses) %></td>
-          </tr>
-          <tr>
-            <th># of slow responses</th>
-            <td><%= h(@statistics.n_slow_responses) %></td>
-          </tr>
-          <tr>
-            <th>responses/sec</th>
-            <td><%= h(@statistics.responses_per_second) %></td>
-          </tr>
-          <tr>
-            <th>start time</th>
-            <td><%= format_time(@statistics.start_time) %></td>
-          </tr>
-          <tr>
-            <th>last time</th>
-            <td><%= format_time(@statistics.last_time) %></td>
-          </tr>
-          <tr>
-            <th>period</th>
-            <td><%= h(@statistics.period) %>sec</td>
-          </tr>
-          <tr>
-            <th>slow response ratio</th>
-            <td><%= h(@statistics.slow_response_ratio) %>%</td>
-          </tr>
-          <tr>
-            <th>total response time</th>
-            <td><%= h(@statistics.total_elapsed) %>sec</td>
-          </tr>
-        </table>
-      </div>
-      EOH
-    end
-
-    def slow_operations
-      erb(<<-EOH, __LINE__ + 1)
-      <div class="statistics">
-        <h3>Slow Operations</h3>
-        <table class="slow-operations">
-          <tr>
-            <th>total elapsed(sec)</th>
-            <th>total elapsed(%)</th>
-            <th># of operations</th>
-            <th># of operations(%)</th>
-            <th>operation name</th>
-            <th>context</th>
-          </tr>
-<% @statistics.each_slow_operation do |grouped_operation| %>
-          <tr>
-            <td class="elapsed">
-              <%= format_elapsed(grouped_operation[:total_elapsed]) %>
-            </td>
-            <td class="ratio">
-              <%= format_ratio(grouped_operation[:total_elapsed_ratio]) %>
-            </td>
-            <td class="n">
-              <%= h(grouped_operation[:n_operations]) %>
-            </td>
-            <td class="ratio">
-              <%= format_ratio(grouped_operation[:n_operations_ratio]) %>
-            </td>
-            <td class="name"><%= h(grouped_operation[:name]) %></td>
-            <td class="context">
-              <%= format_context(grouped_operation[:context]) %>
-            </td>
-          </tr>
-<% end %>
-        </table>
-      </div>
-      EOH
-    end
-
-    def format_time(time)
-      span({:class => "time"}, h(super))
-    end
-
-    def format_elapsed(elapsed, options={})
-      formatted_elapsed = span({:class => "elapsed"}, h("%8.8f" % elapsed))
-      if options[:slow?]
-        formatted_elapsed = span({:class => "slow"}, formatted_elapsed)
-      end
-      formatted_elapsed
-    end
-
-    def format_ratio(ratio)
-      h("%5.2f%%" % ratio)
-    end
-
-    def format_context(context)
-      h(context).gsub(/,/, ",<wbr />")
-    end
-
-    def tag(name, attributes, content)
-      html = "<#{name}"
-      html_attributes = attributes.collect do |key, value|
-        "#{h(key)}=\"#{h(value)}\""
-      end
-      html << " #{html_attributes.join(' ')}" unless attributes.empty?
-      html << ">"
-      html << content
-      html << "</#{name}>"
-      html
-    end
-
-    def span(attributes, content)
-      tag("span", attributes, content)
-    end
-
-    def div(attributes, content)
-      tag("div", attributes, content)
-    end
-  end
-end
-
-if __FILE__ == $0
-  analyzer = GroongaQueryLogAnalyzer.new
-  begin
-    analyzer.run
-  rescue GroongaQueryLogAnalyzer::Error
-    $stderr.puts($!.message)
-    exit(false)
-  end
-end
-------------- next part --------------
HTML����������������������������...
Télécharger 



More information about the Groonga-commit mailing list
Back to archive index