elastomer-cli 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/lib/elastomer/cli.rb +1 -0
- data/lib/elastomer/cli/application.rb +5 -0
- data/lib/elastomer/cli/shard_stats.rb +165 -0
- data/lib/elastomer/cli/version.rb +1 -1
- data/test/fixtures/vcr_cassettes/default.yml +62 -2
- data/test/shard_stats_test.rb +13 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 772a6ed6f013c952c66223437cd17fc820cacbe4
|
4
|
+
data.tar.gz: c8f8346f6209a636e714652792d2679f9c29debb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c2ff9ada4ac6515f836f36415a61e9316bdc9785a6827f67ca42f09e6399a72659cb026b534e3b91f05c67b1eddf2a1360dcbfbf6c290a2e843fac71152fba0
|
7
|
+
data.tar.gz: fb7ed301f832fea0378f085945c986102886ce0fa5af4215a16fe9c3df82559a6d301d1ef57abb0331037790868af71c8b2448ae1d0bff2cab0a01cbae82a2ca
|
data/CHANGELOG.md
CHANGED
data/lib/elastomer/cli.rb
CHANGED
@@ -17,6 +17,11 @@ module Elastomer
|
|
17
17
|
desc "snapshot SUBCOMMAND ...ARGS", "execute snapshot commands"
|
18
18
|
subcommand "snapshot", Snapshot
|
19
19
|
|
20
|
+
desc "shard_stats", "show shard count and disk usage for all indices across all nodes"
|
21
|
+
def shard_stats
|
22
|
+
puts ShardStats.table
|
23
|
+
end
|
24
|
+
|
20
25
|
desc "cat [COMMAND] [SCOPE] ...ARGS", "access the ES cat api"
|
21
26
|
long_desc <<-LONGDESC
|
22
27
|
Access the ES cat api. The cat api returns text formatted for humans.
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module Elastomer
|
2
|
+
module CLI
|
3
|
+
class ShardStats < Base
|
4
|
+
no_commands do
|
5
|
+
def self.table
|
6
|
+
self.new.table
|
7
|
+
end
|
8
|
+
|
9
|
+
def table
|
10
|
+
Terminal::Table.new do |table|
|
11
|
+
table << node_names.dup.unshift(nil)
|
12
|
+
table << generate_row("total", node_data)
|
13
|
+
table << :separator
|
14
|
+
|
15
|
+
index_data.keys.sort.each do |index_name|
|
16
|
+
table << generate_row(index_name, index_data[index_name])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_row(title, data)
|
22
|
+
row = node_names.map do |node_name|
|
23
|
+
|
24
|
+
total = total_disk_size_for_node(node_name)
|
25
|
+
data_for_node = data[node_name]
|
26
|
+
shards = data_for_node["shards"]
|
27
|
+
|
28
|
+
if shards > 0
|
29
|
+
usage = data_for_node["size"].to_f / total.to_f * 100.0
|
30
|
+
"%d : %.1f%" % [shards, usage]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
row.unshift title
|
35
|
+
row
|
36
|
+
end
|
37
|
+
|
38
|
+
# Collect data for each index broken down by node. This is a Hash keyed by
|
39
|
+
# index name. The value for each index is another Hash that contains shard
|
40
|
+
# information for each node in the cluster that holds shards for the index.
|
41
|
+
#
|
42
|
+
# {
|
43
|
+
# "index1" => {
|
44
|
+
# "storage1 => {
|
45
|
+
# "shards" => 2,
|
46
|
+
# "size" => 1024 # size in bytes
|
47
|
+
# },
|
48
|
+
# "storage2 => {
|
49
|
+
# "shards" => 1,
|
50
|
+
# "size" => 512 # size in bytes
|
51
|
+
# }
|
52
|
+
# },
|
53
|
+
# "index2" => {
|
54
|
+
# "storage2 => {
|
55
|
+
# "shards" => 1,
|
56
|
+
# "size" => 2048
|
57
|
+
# },
|
58
|
+
# "storage3 => {
|
59
|
+
# "shards" => 1,
|
60
|
+
# "size" => 2048
|
61
|
+
# }
|
62
|
+
# }
|
63
|
+
# ...
|
64
|
+
# }
|
65
|
+
#
|
66
|
+
# Only shards that are in the STARTED state will count towards these metrics.
|
67
|
+
def index_data
|
68
|
+
return @index_data if defined? @index_data
|
69
|
+
|
70
|
+
@index_data = Hash.new do |index_hash, index_name|
|
71
|
+
index_hash[index_name] = Hash.new do |node_hash, node_name|
|
72
|
+
node_hash[node_name] = {
|
73
|
+
"shards" => 0,
|
74
|
+
"size" => 0
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
client.get("/_cat/shards", :h => "index,state,store,node", :bytes => "b").body.split("\n").each do |row|
|
80
|
+
index, state, size, node = row.split(%r/\s+/)
|
81
|
+
next unless state == "STARTED"
|
82
|
+
|
83
|
+
node_stats_for_index = @index_data[index][node]
|
84
|
+
node_stats_for_index["shards"] += 1
|
85
|
+
node_stats_for_index["size"] += Integer(size)
|
86
|
+
end
|
87
|
+
|
88
|
+
@index_data
|
89
|
+
end
|
90
|
+
|
91
|
+
# Take the `index_data` and roll up shard counts and size at the node level.
|
92
|
+
# This information will be reported in the `node_data` method.
|
93
|
+
def shard_data_by_node
|
94
|
+
nodes = Hash.new do |hash, name|
|
95
|
+
hash[name] = {
|
96
|
+
"shards" => 0,
|
97
|
+
"size" => 0
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
index_data.values.each do |hash|
|
102
|
+
hash.each do |name, data|
|
103
|
+
nodes[name]["shards"] += data["shards"]
|
104
|
+
nodes[name]["size"] += data["size"]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
nodes
|
109
|
+
end
|
110
|
+
|
111
|
+
# Collect data about the file system usage and shard counts for each node in
|
112
|
+
# the cluster.
|
113
|
+
#
|
114
|
+
# {
|
115
|
+
# "storage1" => {
|
116
|
+
# "total" => 4294967296, # size in bytes
|
117
|
+
# "free" => 1073741824, # size in bytes
|
118
|
+
# "shards" => 17,
|
119
|
+
# "size" => 3221225472 # size in bytes
|
120
|
+
# },
|
121
|
+
# "storage2" => {
|
122
|
+
# "total" => 4294967296,
|
123
|
+
# "free" => 1073741824,
|
124
|
+
# "shards" => 17,
|
125
|
+
# "size" => 3221225472
|
126
|
+
# },
|
127
|
+
# ...
|
128
|
+
# }
|
129
|
+
#
|
130
|
+
def node_data
|
131
|
+
return @node_data if defined? @node_data
|
132
|
+
|
133
|
+
@node_data = {}
|
134
|
+
shard_data = shard_data_by_node
|
135
|
+
|
136
|
+
client.nodes.stats(:stats => "fs")["nodes"].values.each do |hash|
|
137
|
+
data_node = hash["attributes"]["data"]
|
138
|
+
next if data_node == "false" || data_node == false
|
139
|
+
|
140
|
+
name = hash["name"]
|
141
|
+
fs = hash["fs"]["total"]
|
142
|
+
|
143
|
+
@node_data[name] = {
|
144
|
+
"total" => fs["total_in_bytes"],
|
145
|
+
"free" => fs["available_in_bytes"]
|
146
|
+
}.merge(shard_data[name])
|
147
|
+
end
|
148
|
+
|
149
|
+
@node_data
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns the total size of the disk for the given cluster node.
|
153
|
+
def total_disk_size_for_node(name)
|
154
|
+
node_data[name]["total"]
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns the names of the nodes in the cluster sorted alphabetically.
|
158
|
+
def node_names
|
159
|
+
@node_names ||= node_data.keys.sort
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -527,7 +527,67 @@ http_interactions:
|
|
527
527
|
- '121'
|
528
528
|
body:
|
529
529
|
encoding: UTF-8
|
530
|
-
string:
|
530
|
+
string: '{"acknowledged":true,"persistent":{"cluster.routing.allocation.enable":"all","indices.ttl.interval":"70"},"transient":{}}'
|
531
531
|
http_version:
|
532
532
|
recorded_at: Thu, 18 Dec 2014 00:51:29 GMT
|
533
|
-
|
533
|
+
- request:
|
534
|
+
method: get
|
535
|
+
uri: http://127.0.0.1:19200/_cat/shards?bytes=b&h=index,state,store,node
|
536
|
+
body:
|
537
|
+
encoding: US-ASCII
|
538
|
+
string: ''
|
539
|
+
headers:
|
540
|
+
User-Agent:
|
541
|
+
- Faraday v0.9.2
|
542
|
+
Accept-Encoding:
|
543
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
544
|
+
Accept:
|
545
|
+
- "*/*"
|
546
|
+
response:
|
547
|
+
status:
|
548
|
+
code: 200
|
549
|
+
message: OK
|
550
|
+
headers:
|
551
|
+
Content-Type:
|
552
|
+
- text/plain; charset=UTF-8
|
553
|
+
Content-Length:
|
554
|
+
- '444'
|
555
|
+
body:
|
556
|
+
encoding: UTF-8
|
557
|
+
string: "hi STARTED 115 boxen \nbleh STARTED 115
|
558
|
+
boxen \nblog-1 STARTED 115 boxen \nusers-1 STARTED 115
|
559
|
+
boxen \nfoo STARTED 115 boxen \nshowcases-1 STARTED 115
|
560
|
+
boxen \naudit_log-2015-08 STARTED 115 boxen \nrepos-1 STARTED 115
|
561
|
+
boxen \nissues-1 STARTED 115 boxen \ncode-search-1 STARTED 115
|
562
|
+
boxen \ngists-1 STARTED 115 boxen \npull-requests-1 STARTED 115
|
563
|
+
boxen \n"
|
564
|
+
http_version:
|
565
|
+
recorded_at: Tue, 27 Oct 2015 23:40:41 GMT
|
566
|
+
- request:
|
567
|
+
method: get
|
568
|
+
uri: http://127.0.0.1:19200/_nodes/_all/stats/fs
|
569
|
+
body:
|
570
|
+
encoding: US-ASCII
|
571
|
+
string: ''
|
572
|
+
headers:
|
573
|
+
User-Agent:
|
574
|
+
- Faraday v0.9.2
|
575
|
+
Accept-Encoding:
|
576
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
577
|
+
Accept:
|
578
|
+
- "*/*"
|
579
|
+
response:
|
580
|
+
status:
|
581
|
+
code: 200
|
582
|
+
message: OK
|
583
|
+
headers:
|
584
|
+
Content-Type:
|
585
|
+
- application/json; charset=UTF-8
|
586
|
+
Content-Length:
|
587
|
+
- '899'
|
588
|
+
body:
|
589
|
+
encoding: UTF-8
|
590
|
+
string: '{"cluster_name":"elasticsearch_boxen_chrismwendt","nodes":{"ekfO1wDuQ8m1YLD-i39lhQ":{"timestamp":1445989241430,"name":"boxen","transport_address":"inet[/127.0.0.1:19300]","host":"Chriss-MacBook-Air.local","ip":["inet[/127.0.0.1:19300]","NONE"],"attributes":{"max_local_storage_nodes":"1"},"fs":{"timestamp":1445989241430,"total":{"total_in_bytes":499071844352,"free_in_bytes":407380561920,"available_in_bytes":407118417920,"disk_reads":0,"disk_writes":0,"disk_io_op":0,"disk_read_size_in_bytes":0,"disk_write_size_in_bytes":0,"disk_io_size_in_bytes":0},"data":[{"path":"/opt/boxen/data/elasticsearch/elasticsearch_boxen_chrismwendt/nodes/0","mount":"/","dev":"/dev/disk1","total_in_bytes":499071844352,"free_in_bytes":407380561920,"available_in_bytes":407118417920,"disk_reads":0,"disk_writes":0,"disk_io_op":0,"disk_read_size_in_bytes":0,"disk_write_size_in_bytes":0,"disk_io_size_in_bytes":0}]}}}}'
|
591
|
+
http_version:
|
592
|
+
recorded_at: Tue, 27 Oct 2015 23:40:41 GMT
|
593
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Elastomer::CLI::ShardStats do
|
4
|
+
describe 'shard_stats' do
|
5
|
+
it 'should show shard stats' do
|
6
|
+
VCR.use_cassette('default') do
|
7
|
+
elastomer 'shard_stats'
|
8
|
+
@out.must_match /total.*12/m
|
9
|
+
@out.must_match /audit_log/m
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastomer-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Grant Rodgers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -146,6 +146,7 @@ files:
|
|
146
146
|
- lib/elastomer/cli/index.rb
|
147
147
|
- lib/elastomer/cli/node.rb
|
148
148
|
- lib/elastomer/cli/repository.rb
|
149
|
+
- lib/elastomer/cli/shard_stats.rb
|
149
150
|
- lib/elastomer/cli/snapshot.rb
|
150
151
|
- lib/elastomer/cli/version.rb
|
151
152
|
- script/bootstrap
|
@@ -165,6 +166,7 @@ files:
|
|
165
166
|
- test/index_test.rb
|
166
167
|
- test/node_test.rb
|
167
168
|
- test/repository_test.rb
|
169
|
+
- test/shard_stats_test.rb
|
168
170
|
- test/snapshot_test.rb
|
169
171
|
- test/test_helper.rb
|
170
172
|
homepage: https://github.com/github/elastomer-cli
|
@@ -187,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
189
|
version: '0'
|
188
190
|
requirements: []
|
189
191
|
rubyforge_project:
|
190
|
-
rubygems_version: 2.2.
|
192
|
+
rubygems_version: 2.2.3
|
191
193
|
signing_key:
|
192
194
|
specification_version: 4
|
193
195
|
summary: Command line interface for elastomer
|
@@ -205,5 +207,7 @@ test_files:
|
|
205
207
|
- test/index_test.rb
|
206
208
|
- test/node_test.rb
|
207
209
|
- test/repository_test.rb
|
210
|
+
- test/shard_stats_test.rb
|
208
211
|
- test/snapshot_test.rb
|
209
212
|
- test/test_helper.rb
|
213
|
+
has_rdoc:
|