class Elastomer::CLI::Shard

Public Instance Methods

generate_row(title, data) click to toggle source
# File lib/elastomer/cli/shard.rb, line 22
def generate_row(title, data)
  row = node_names.map do |node_name|

    total         = total_disk_size_for_node(node_name)
    data_for_node = data[node_name]
    shards        = data_for_node["shards"]

    if shards > 0
      usage  = data_for_node["size"].to_f / total.to_f * 100.0
      "%d : %.1f%" % [shards, usage]
    end
  end

  row.unshift title
  row
end
index_data() click to toggle source

Collect data for each index broken down by node. This is a Hash keyed by index name. The value for each index is another Hash that contains shard information for each node in the cluster that holds shards for the index.

{
  "index1" => {
    "storage1 => {
      "shards" => 2,
      "size"   => 1024    # size in bytes
    },
    "storage2 => {
      "shards" => 1,
      "size"   => 512     # size in bytes
    }
  },
  "index2" => {
    "storage2 => {
      "shards" => 1,
      "size"   => 2048
    },
    "storage3 => {
      "shards" => 1,
      "size"   => 2048
    }
  }
  ...
}

Only shards that are in the STARTED state will count towards these metrics.

# File lib/elastomer/cli/shard.rb, line 68
def index_data
  return @index_data if defined? @index_data

  @index_data = Hash.new do |index_hash, index_name|
    index_hash[index_name] = Hash.new do |node_hash, node_name|
      node_hash[node_name] = {
        "shards" => 0,
        "size"   => 0
      }
    end
  end

  client.get("/_cat/shards", :h => "index,state,store,node", :bytes => "b").body.split("\n").each do |row|
    index, state, size, node = row.split(%r/\s+/)
    next unless state == "STARTED"

    node_stats_for_index = @index_data[index][node]
    node_stats_for_index["shards"] += 1
    node_stats_for_index["size"]   += Integer(size)
  end

  @index_data
end
node_data() click to toggle source

Collect data about the file system usage and shard counts for each node in the cluster.

{
  "storage1" => {
    "total"  => 4294967296,   # size in bytes
    "free"   => 1073741824,   # size in bytes
    "shards" => 17,
    "size"   => 3221225472    # size in bytes
  },
  "storage2" => {
    "total"  => 4294967296,
    "free"   => 1073741824,
    "shards" => 17,
    "size"   => 3221225472
  },
  ...
}
# File lib/elastomer/cli/shard.rb, line 131
def node_data
  return @node_data if defined? @node_data

  @node_data = {}
  shard_data = shard_data_by_node

  client.nodes.stats(:stats => "fs")["nodes"].values.each do |hash|
    data_node = hash["attributes"]["data"]
    next if data_node == "false" || data_node == false

    name = hash["name"]
    fs   = hash["fs"]["total"]

    @node_data[name] = {
      "total" => fs["total_in_bytes"],
      "free"  => fs["available_in_bytes"]
    }.merge(shard_data[name])
  end

  @node_data
end
node_names() click to toggle source

Returns the names of the nodes in the cluster sorted alphabetically.

# File lib/elastomer/cli/shard.rb, line 159
def node_names
  @node_names ||= node_data.keys.sort
end
normalized_node_names() click to toggle source

Given the list of node names, extract the first unique name segment and use that as the normalized node name. The node name is divided into segments by splitting on the dash “-” character.

Given the followin node names:

["githubsearch3-storage1-cp1-prd", "githubsearch3-storage2-cp1-prd"]

the resulting normalized names would be:

["storage1", "storage2"]
# File lib/elastomer/cli/shard.rb, line 175
def normalized_node_names
  names = node_names
  return names if node_names.length == 1

  ary = node_names.map {|name| name.split("-")}

  ary.first.length.times do |col|
    name_part = ary.map {|row| row[col]}
    if name_part.uniq.length != 1
      names = name_part
      break
    end
  end

  names
end
shard_data_by_node() click to toggle source

Take the `index_data` and roll up shard counts and size at the node level. This information will be reported in the `node_data` method.

# File lib/elastomer/cli/shard.rb, line 94
def shard_data_by_node
  nodes = Hash.new do |hash, name|
    hash[name] = {
      "shards" => 0,
      "size"   => 0
    }
  end

  index_data.values.each do |hash|
    hash.each do |name, data|
      nodes[name]["shards"] += data["shards"]
      nodes[name]["size"]   += data["size"]
    end
  end

  nodes
end
stats() click to toggle source
# File lib/elastomer/cli/shard.rb, line 5
def stats
  puts stats_table
end
stats_table() click to toggle source
# File lib/elastomer/cli/shard.rb, line 10
def stats_table
  Terminal::Table.new do |table|
    table << [nil] + normalized_node_names
    table << generate_row("total", node_data)
    table << :separator

    index_data.keys.sort.each do |index_name|
      table << generate_row(index_name, index_data[index_name])
    end
  end
end
total_disk_size_for_node(name) click to toggle source

Returns the total size of the disk for the given cluster node.

# File lib/elastomer/cli/shard.rb, line 154
def total_disk_size_for_node(name)
  node_data[name]["total"]
end