[Groonga-commit] groonga/groonga [master] * add a munin plugin for query performance.

Zurück zum Archiv-Index

null+****@clear***** null+****@clear*****
2010年 6月 23日 (水) 11:43:52 JST


Kouhei Sutou	2010-06-23 02:43:52 +0000 (Wed, 23 Jun 2010)

  New Revision: 7676d3b64780128a03cd501fa727a1105beb8cef

  Log:
    * add a munin plugin for query performance.

  Added files:
    data/munin/groonga_query_performance
  Modified files:
    data/munin/Makefile.am

  Modified: data/munin/Makefile.am (+2 -1)
===================================================================
--- data/munin/Makefile.am    2010-06-22 13:38:30 +0000 (fbb58c7)
+++ data/munin/Makefile.am    2010-06-23 02:43:52 +0000 (6bfa8e3)
@@ -4,4 +4,5 @@ dist_munin_plugins_SCRIPTS =			\
 	groonga_cpu_time			\
 	groonga_status				\
 	groonga_memory				\
-	groonga_n_records
+	groonga_n_records			\
+	groonga_query_performance

  Added: data/munin/groonga_query_performance (+133 -0) 100755
===================================================================
--- /dev/null
+++ data/munin/groonga_query_performance    2010-06-23 02:43:52 +0000 (8081d02)
@@ -0,0 +1,133 @@
+#!/usr/bin/env ruby
+
+#%# family=auto
+#%# capabilities=autoconf
+
+require 'English'
+require 'strscan'
+
+label = ENV["label"]
+
+ @ log_path = ENV["log_path"]
+
+command = ARGV.shift
+
+case command
+when "autoconf", "detect"
+  if @log_path.nil?
+    puts "no (query log file path isn't specified by env.log_path)"
+    exit(false)
+  end
+  unless File.readable?(@log_path)
+    puts "no (query log file isn't readable: <#{@log_path}>)"
+    exit(false)
+  end
+  puts "yes"
+  exit(true)
+when "config"
+  if label.nil?
+    title = "groonga: query performance"
+  else
+    title = "groonga: #{label}: query performance"
+  end
+  puts <<EOF
+graph_title #{title}
+graph_vlabel seconds
+graph_category groonga
+graph_info groonga query performance
+
+longest.label Longest
+average.label Average
+median.label Median
+EOF
+  exit(true)
+end
+
+class ReverseLineReader
+  def initialize(io)
+    @io = io
+    @io.seek(0, IO::SEEK_END)
+    @buffer = ""
+    @data = ""
+  end
+
+  def each
+    separator = $/
+    separator_length = separator.length
+    while read_to_buffer
+      loop do
+        index =****@buffe*****(separator, @buffer.length - 1 - separator_length)
+        break if index.nil? or index.zero?
+        last_line =****@buffe*****!((index + separator_length)..-1)
+        yield(last_line)
+      end
+    end
+    yield(@buffer) unles****@buffe*****?
+  end
+
+  private
+  BYTES_PER_READ = 4096
+  def read
+    position =****@io*****
+    if position < BYTES_PER_READ
+      bytes_per_read = position
+    else
+      bytes_per_read = BYTES_PER_READ
+    end
+
+    if bytes_per_read.zero?
+      @data.replace("")
+    else
+      @io.seek(-bytes_per_read, IO::SEEK_CUR)
+      @io.read(bytes_per_read, @data)
+      @io.seek(-bytes_per_read, IO::SEEK_CUR)
+    end
+
+    @data
+  end
+
+  def read_to_buffer
+    data = read
+    if data.empty?
+      false
+    else
+      @buffer.insert(0, data)
+      true
+    end
+  end
+end
+
+span = 60 * 5 # 5min
+mega = 1_000_000.0
+now = Time.now
+elapsed_times = []
+File.open(@log_path) do |log_file|
+  ReverseLineReader.new(log_file).each do |line|
+    case line
+    when /\A(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)\.(\d+)\|([\da-f])+\|<(\d+) rc=0$/
+      _, year, month, day, hour, minutes, seconds, milliseconds,
+        context, elapsed = $LAST_MATCH_INFO.to_a
+      time_stamp = Time.local(year, month, day,
+                              hour, minutes, seconds, milliseconds)
+      difference = now - time_stamp
+      break if difference > span
+      elapsed_in_micro_seconds = elapsed.to_i / mega
+      elapsed_times << elapsed_in_micro_seconds
+    end
+  end
+end
+
+sorted_elapsed_times = elapsed_times.sort
+if sorted_elapsed_times.empty?
+  longest = 0
+  average = 0
+  median = 0
+else
+  longest = sorted_elapsed_times.last
+  average = sorted_elapsed_times.inject(&:+) / sorted_elapsed_times.size.to_f
+  median = sorted_elapsed_times[sorted_elapsed_times.size / 2]
+end
+
+puts "longest.value #{longest}"
+puts "average.value #{average}"
+puts "median.value #{median}"




Groonga-commit メーリングリストの案内
Zurück zum Archiv-Index