class Flare::Tools::Cli::Stats

Description

Constants

HeaderConfigQpss
HeaderConfigs

Public Class Methods

new() click to toggle source
Calls superclass method
# File lib/flare/tools/cli/stats.rb, line 59
def initialize
  super
  @qps = false
  @wait = 1
  @count = 1
  @cont = true
  @delimiter = ' '
end

Public Instance Methods

execute(config, args) click to toggle source
# File lib/flare/tools/cli/stats.rb, line 73
def execute(config, args)
  parse_index_server(config, args)
  nodes = {}
  threads = {}

  Flare::Tools::IndexServer.open(config[:index_server_hostname], config[:index_server_port], @timeout) do |s|
    nodes = s.stats_nodes
    unless nodes
      error "Invalid index server."
      return S_NG
    end
    nodes = nodes.sort_by{|key,val| [val['partition'].to_i, val['role'], key]}
    threads = s.stats_threads_by_peer
  end

  worker_threads = []
  queue = {}

  nodes.each do |hostname_port,data|
    queue[hostname_port] = SizedQueue.new(1)
    worker_threads << Thread.new(queue[hostname_port]) do |q|
      enqueueing_node_stats(q, threads, config, hostname_port, data)
    end
  end

  query_prev = {} if @qps

  if @count > 1 || @qps
    interruptible {sleep 1}
  end

  s = Flare::Tools::IndexServer.open(
    @index_server_entity.host,
    @index_server_entity.port,
    @timeout
  )
  unless s
    error "Couldn't connect to the index server."
    return S_NG
  end

  (0...@count).each do |i|
    nodes = s.stats_nodes
    unless nodes
      error "Invalid index server."
      exit 1
    end
    nodes = nodes.sort_by{|key,val| [val['partition'].to_i, val['role'], key]}
    threads = s.stats_threads_by_peer

    break unless @cont
    max_nodekey_length = 25
    nodes.each do |k, n|
      max_nodekey_length = k.length if k.length > max_nodekey_length
    end
    r = records(args, nodes, queue, threads, query_prev)
    interruptible {
      wait_for_stats
    }
    table = Table.new
    add_header_to_table(table, header_configs)
    add_records_to_table(table, header_configs, r)
    puts table.prettify
  end
  s.close

  @cont = false

  queue.each do |k,q|
    q.pop until q.empty?
  end

  interruptible {
    worker_threads.each do |t|
      t.join
    end
  }

  S_OK
end
interrupt() click to toggle source
# File lib/flare/tools/cli/stats.rb, line 68
def interrupt
  puts "INTERRUPTED"
  @cont = false
end
setup() click to toggle source
Calls superclass method
# File lib/flare/tools/cli/stats.rb, line 50
def setup
  super
  set_option_index_server
  @optp.on("-q", '--qps',              "show qps")                             {|v| @qps = v}
  @optp.on("-w", '--wait=SECOND',      "specify wait time for repeat(second)") {|v| @wait = v.to_i}
  @optp.on("-c", '--count=REPEATTIME', "specify repeat count")                 {|v| @count = v.to_i}
  @optp.on("-d", '--delimiter=CHAR',   "specify delimiter")                    {|v| @delimiter = v}
end

Private Instance Methods

add_header_to_table(table, header_configs) click to toggle source
# File lib/flare/tools/cli/stats.rb, line 224
def add_header_to_table(table, header_configs)
  row = Row.new(:separator => @delimiter)
  header_configs.each do |header_config|
    row.add_column(Column.new(header_config[0]))
  end
  table.add_row(row)
end
add_records_to_table(table, header_configs, records) click to toggle source
# File lib/flare/tools/cli/stats.rb, line 232
def add_records_to_table(table, header_configs, records)
  records.each do |record|
    row = Row.new(:separator => @delimiter)
    header_configs.each_with_index do |header_config, index|
      row.add_column(Column.new(record[index], header_config[1]))
    end
    table.add_row(row)
  end
end
enqueueing_node_stats(q, threads, config, hostname_port, data) click to toggle source
# File lib/flare/tools/cli/stats.rb, line 166
def enqueueing_node_stats(q, threads, config, hostname_port, data)
  hostname, port = hostname_port.split(":", 2)
  s = nil
  while @cont
    stats_data = nil
    begin
      s = Flare::Tools::Stats.open(hostname, data['port'], @timeout)
      stats = s.stats
      time = Time.now
      behind = threads[hostname_port].has_key?('behind') ? threads[hostname_port]['behind'] : "-"
      uptime_short = short_desc_of_second(stats['uptime'])
      hit_rate = if stats.has_key?('cmd_get') && stats['cmd_get'] != "0"
                   cmd_get = stats['cmd_get'].to_f
                   get_hits = stats['get_hits'].to_f
                   (get_hits / cmd_get * 100.0).round
                 else
                   "-"
                 end
      size =  stats['bytes'] == "0" ? "-" : (stats['bytes'].to_i / 1024 / 1024 / 1024) # gigabyte
      stats_data = {
        :hostname   => hostname,
        :port       => port,
        :hostname_port => "#{hostname}:#{port}",
        :state      => data['state'],
        :role       => data['role'],
        :partition  => data['partition'] == "-1" ? "-" : data['partition'],
        :balance    => data['balance'],
        :items      => stats['curr_items'],
        :conn       => stats['curr_connections'],
        :behind     => behind,
        :hit_rate   => hit_rate,
        :size       => size,
        :uptime     => stats['uptime'],
        :uptime_short => uptime_short,
        :version    => stats['version'],
        :cmd_get    => stats['cmd_get'],
        :cmd_set    => stats['cmd_set'],
        :time       => time,
      }
    rescue Errno::ECONNREFUSED => e
    rescue Timeout::Error, StandardError => e
      begin
        s.close unless s.nil?
      rescue => close_error
        error "Socket close failed: #{close_error.inspect}"
      end
      s = nil
    end
    if stats_data.nil?
      stats_data = {
        :hostname_port => "#{hostname}:#{port}",
      }
    end
    q.push stats_data
  end
  s.close unless s.nil?
end
header_configs() click to toggle source

You can override this method to extend stats infos.

# File lib/flare/tools/cli/stats.rb, line 287
def header_configs
  configs = Marshal.load(Marshal.dump(HeaderConfigs))
  configs += Marshal.load(Marshal.dump(HeaderConfigQpss)) if @qps
  configs
end
record(stats_data, node, behind, query_prev, index) click to toggle source

You can override this method to extend stats infos.

# File lib/flare/tools/cli/stats.rb, line 253
def record(stats_data, node, behind, query_prev, index)
  stats_data[:state] = node['state']
  stats_data[:role] = node['role']
  stats_data[:partition] = node['partition']
  stats_data[:balance] = node['balance']
  stats_data[:behind] = behind
  output = [:hostname_port, :state, :role, :partition, :balance, :items,
            :conn, :behind, :hit_rate, :size, :uptime_short, :version].map {|x| stats_data[x]}
  if @qps
    query = {}
    query[:query] = stats_data[:cmd_get].to_i+stats_data[:cmd_set].to_i
    query[:query_r] = stats_data[:cmd_get].to_i
    query[:query_w] = stats_data[:cmd_set].to_i
    query[:time] = time = stats_data[:time]
    if query_prev.has_key?(index)
      duration = (time-query_prev[index][:time]).to_f
      [:query, :query_r, :query_w].each do |x|
        diff = (query[x]-query_prev[index][x]).to_f
        qps = if diff > 0
                sprintf("%.1f", diff/duration)
              else
                '-'
              end
        output << qps
      end
    else
      output << '-' << '-' << '-'
    end
    query_prev[index] = query.dup
  end
  output
end
records(args, nodes, queue, threads, query_prev) click to toggle source

You can override this method to extend stats infos.

# File lib/flare/tools/cli/stats.rb, line 243
def records(args, nodes, queue, threads, query_prev)
  nodes.map do |k, node|
    stats_data = queue[k].pop
    next if (args.size > 0 && !args.include?(k))
    behind = (threads.has_key?(k) || threads[k].has_key?('behind')) ? threads[k]['behind'] : "-"
    record(stats_data, node, behind, query_prev, k)
  end
end
wait_for_stats() click to toggle source
# File lib/flare/tools/cli/stats.rb, line 156
def wait_for_stats
  if @qps || @count > 1
    wait = @wait
    while wait > 0 && @cont
      sleep 1
      wait -= 1
    end
  end
end