cassandra-utils 0.2.1 → 0.3.1.pre.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +20 -1
- data/bin/cass-util +15 -3
- data/lib/cassandra/tasks/autoclean.rb +257 -0
- data/lib/cassandra/tasks.rb +1 -0
- data/lib/cassandra/utils/cli/base.rb +2 -17
- data/lib/cassandra/utils/daemon.rb +22 -2
- data/lib/cassandra/utils/stats/cleanup.rb +4 -1
- data/lib/cassandra/utils/stats/compaction.rb +4 -1
- data/lib/cassandra/utils/stats/health.rb +73 -0
- data/lib/cassandra/utils/stats.rb +1 -0
- data/lib/cassandra/utils/statsd.rb +24 -0
- data/lib/cassandra/utils.rb +1 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e551a8b992a71ae2b24834faef52d77f61137eb
|
4
|
+
data.tar.gz: 002209ac50837ebd0e4a542b86bcdb442b2073be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2f744c06e90c15931aba8bd6a9bfdabd4dfef6f5469e83ccc681928f6bcbde06067e0ada434c774b8df9482af046c795d74708eb337186e89296822cf98af67
|
7
|
+
data.tar.gz: 982bb9611cc120b08493f160b07dcda482cda4022c361126d1999c63ab066babd4f94cd409388ea2219b19cf6788f5386ed8feec2d0e421086db96f9a0114e3c
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -3,6 +3,9 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in cassandra-utils.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
# TODO: Remove this when the next version of diplomat is released
|
7
|
+
gem 'diplomat', github: 'WeAreFarmGeek/diplomat', ref: 'e64b0dec3b3616ded40bb64139a388dfc1a68232'
|
8
|
+
|
6
9
|
group :development do
|
7
10
|
gem 'bundler', '~> 1.7'
|
8
11
|
gem 'thor-scmversion', '= 1.7.0'
|
data/Gemfile.lock
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/WeAreFarmGeek/diplomat.git
|
3
|
+
revision: e64b0dec3b3616ded40bb64139a388dfc1a68232
|
4
|
+
ref: e64b0dec3b3616ded40bb64139a388dfc1a68232
|
5
|
+
specs:
|
6
|
+
diplomat (1.1.0)
|
7
|
+
faraday (~> 0.9)
|
8
|
+
json
|
9
|
+
|
1
10
|
PATH
|
2
11
|
remote: .
|
3
12
|
specs:
|
@@ -10,10 +19,16 @@ PATH
|
|
10
19
|
GEM
|
11
20
|
remote: https://rubygems.org/
|
12
21
|
specs:
|
13
|
-
daemon_runner (0.
|
22
|
+
daemon_runner (0.4.1)
|
23
|
+
diplomat (~> 1.0)
|
14
24
|
logging (~> 2.1)
|
15
25
|
mixlib-shellout (~> 2.2)
|
26
|
+
retryable (~> 2.0)
|
27
|
+
rufus-scheduler (~> 3.2)
|
16
28
|
dogstatsd-ruby (1.6.0)
|
29
|
+
faraday (0.10.0)
|
30
|
+
multipart-post (>= 1.2, < 3)
|
31
|
+
json (2.0.2)
|
17
32
|
little-plugger (1.1.4)
|
18
33
|
logging (2.1.0)
|
19
34
|
little-plugger (~> 1.1)
|
@@ -21,7 +36,10 @@ GEM
|
|
21
36
|
minitest (5.9.0)
|
22
37
|
mixlib-shellout (2.2.7)
|
23
38
|
multi_json (1.12.1)
|
39
|
+
multipart-post (2.0.0)
|
24
40
|
rake (10.5.0)
|
41
|
+
retryable (2.0.4)
|
42
|
+
rufus-scheduler (3.2.2)
|
25
43
|
thor (0.19.1)
|
26
44
|
thor-scmversion (1.7.0)
|
27
45
|
mixlib-shellout
|
@@ -33,6 +51,7 @@ PLATFORMS
|
|
33
51
|
DEPENDENCIES
|
34
52
|
bundler (~> 1.7)
|
35
53
|
cassandra-utils!
|
54
|
+
diplomat!
|
36
55
|
minitest (~> 5.0)
|
37
56
|
rake (~> 10.0)
|
38
57
|
thor-scmversion (= 1.7.0)
|
data/bin/cass-util
CHANGED
@@ -1,17 +1,29 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require_relative '../lib/cassandra/utils'
|
3
|
+
require_relative '../lib/cassandra/tasks'
|
3
4
|
require 'thor'
|
4
5
|
|
5
6
|
class CassandraUtils < Thor
|
6
7
|
|
7
|
-
|
8
|
+
class_option :loop_sleep_time, type: :numeric,
|
8
9
|
required: true, default: 120,
|
9
10
|
desc: 'Frequency tasks are run'
|
10
|
-
|
11
|
-
|
11
|
+
class_option :cleanup_service_name, type: :string,
|
12
|
+
required: true, default: 'cassandra',
|
13
|
+
desc: 'Unique string to be used in obtaining a Semaphore. Example: cassandra-#{cluster_name}'
|
14
|
+
class_option :cleanup_lock_count, type: :numeric,
|
15
|
+
required: true, default: 1,
|
16
|
+
desc: 'Number of nodes that can obtain a Semaphore lock'
|
17
|
+
desc 'util', 'Perform various utilities'
|
18
|
+
def util
|
12
19
|
s = ::Cassandra::Utils::Daemon.new(options)
|
13
20
|
s.start!
|
14
21
|
end
|
22
|
+
# Backwards compatibility
|
23
|
+
desc 'stats', '[DEPRECATED - Use util] Write metrics to Datadog'
|
24
|
+
def stats
|
25
|
+
send(:util)
|
26
|
+
end
|
15
27
|
end
|
16
28
|
|
17
29
|
CassandraUtils.start
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'json'
|
3
|
+
require 'time'
|
4
|
+
require 'set'
|
5
|
+
require 'tmpdir'
|
6
|
+
require_relative '../utils/version'
|
7
|
+
|
8
|
+
module Cassandra
|
9
|
+
module Tasks
|
10
|
+
class Autoclean
|
11
|
+
include ::DaemonRunner::Logger
|
12
|
+
|
13
|
+
# @return [String] the path on disk where tokens will be cached
|
14
|
+
attr_reader :token_cache_path
|
15
|
+
|
16
|
+
# Create a new Autoclean task
|
17
|
+
#
|
18
|
+
# @param options [Object] optional configuration settings
|
19
|
+
# (see #token_cache_path)
|
20
|
+
#
|
21
|
+
# @return [Autoclean]
|
22
|
+
#
|
23
|
+
def initialize(options = {})
|
24
|
+
@token_cache_path = options[:token_cache_path]
|
25
|
+
@token_cache_path ||= File.join(Dir.tmpdir, 'autoclean-tokens.json')
|
26
|
+
@service_name = options[:cleanup_service_name]
|
27
|
+
@lock_count = options[:cleanup_lock_count]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Schedule the Cassandra cleanup process to run daily
|
31
|
+
#
|
32
|
+
def schedule
|
33
|
+
[:interval, '1d']
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return the status of the Cassandra node
|
37
|
+
#
|
38
|
+
# A node is considered up if it has a status of "Up" as reported by
|
39
|
+
# "nodetool status". If multiple nodes with this node's IP address show
|
40
|
+
# up in "nodetool status", this node is considered down.
|
41
|
+
#
|
42
|
+
# @return [:up, :down]
|
43
|
+
#
|
44
|
+
def status
|
45
|
+
return(:down).tap { logger.warn 'Cassandra node is DOWN' } if address.nil?
|
46
|
+
results = (nodetool_status || '').split("\n")
|
47
|
+
results.map! { |line| line.strip }
|
48
|
+
results.select! { |line| line.include? address }
|
49
|
+
results.map! { |line| line.split(/\s+/)[0] }
|
50
|
+
results.compact!
|
51
|
+
return(:down).tap do
|
52
|
+
logger.warn "Cannot find the Cassandra node (#{address}) in `nodetool status`"
|
53
|
+
end if results.size != 1
|
54
|
+
(results.first[0] == 'U') ? :up : :down
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return the state of the Cassandra node
|
58
|
+
#
|
59
|
+
# The returned state is reported by "nodetool netstats".
|
60
|
+
#
|
61
|
+
# @return [state, nil]
|
62
|
+
#
|
63
|
+
def state
|
64
|
+
results = (nodetool_netstats || '').split("\n")
|
65
|
+
results.map! { |line| line.strip }
|
66
|
+
results.select! { |line| line.include? 'Mode:' }
|
67
|
+
results.map! { |line| line.split(':')[1] }
|
68
|
+
results.compact!
|
69
|
+
return nil if results.size != 1
|
70
|
+
results.first.strip.downcase.to_sym
|
71
|
+
end
|
72
|
+
|
73
|
+
# Run the Cassandra cleanup process if necessary
|
74
|
+
#
|
75
|
+
def run!
|
76
|
+
return unless status == :up
|
77
|
+
return unless state == :normal
|
78
|
+
|
79
|
+
new_tokens = Set.new tokens
|
80
|
+
old_tokens = Set.new cached_tokens
|
81
|
+
return if new_tokens == old_tokens
|
82
|
+
|
83
|
+
::DaemonRunner::Semaphore.lock(@service_name, @lock_count) do
|
84
|
+
result = nodetool_cleanup
|
85
|
+
save_tokens if !result.nil? && result.exitstatus == 0
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Get the cached tokens this node owns
|
90
|
+
#
|
91
|
+
# @return [Array<String>] Cached tokens
|
92
|
+
#
|
93
|
+
def cached_tokens
|
94
|
+
data = token_cache.read
|
95
|
+
data = JSON.parse data
|
96
|
+
return [] unless data['version'] == ::Cassandra::Utils::VERSION
|
97
|
+
|
98
|
+
tokens = data['tokens']
|
99
|
+
return [] if tokens.nil?
|
100
|
+
return [] unless tokens.respond_to? :each
|
101
|
+
|
102
|
+
tokens.sort!
|
103
|
+
tokens
|
104
|
+
# Token file could not be opend or parsed
|
105
|
+
rescue Errno::ENOENT, JSON::ParserError
|
106
|
+
[]
|
107
|
+
end
|
108
|
+
|
109
|
+
# Save the list of tokens this node owns to disk
|
110
|
+
# These can be read by `cached_tokens`
|
111
|
+
#
|
112
|
+
def save_tokens
|
113
|
+
data = {
|
114
|
+
:timestamp => Time.now.iso8601,
|
115
|
+
:tokens => tokens,
|
116
|
+
:version => ::Cassandra::Utils::VERSION
|
117
|
+
}
|
118
|
+
|
119
|
+
token_cache.write data.to_json
|
120
|
+
token_cache.flush
|
121
|
+
end
|
122
|
+
|
123
|
+
# Get the tokens this node owns
|
124
|
+
#
|
125
|
+
# The "nodetool ring" command returns
|
126
|
+
#
|
127
|
+
# Address Rack Status State Load Size Owns Token
|
128
|
+
# 127.0.0.1 r1 Up Normal 10 GB 33% 123456789
|
129
|
+
#
|
130
|
+
# @return [Array<String>] Tokens owned by this node
|
131
|
+
#
|
132
|
+
def tokens
|
133
|
+
return [] if address.nil?
|
134
|
+
results = (nodetool_ring || '').split("\n")
|
135
|
+
results.map! { |line| line.strip }
|
136
|
+
results.select! { |line| line.start_with? address }
|
137
|
+
results.map! { |line| line.split(/\s+/)[7] }
|
138
|
+
results.compact!
|
139
|
+
results.sort
|
140
|
+
end
|
141
|
+
|
142
|
+
# Get the IP address of this node
|
143
|
+
#
|
144
|
+
# @return [String, nil] IP address of this node
|
145
|
+
#
|
146
|
+
def address
|
147
|
+
if @address.nil?
|
148
|
+
addr = Socket.ip_address_list.find { |addr| addr.ipv4_private? }
|
149
|
+
@address = addr.ip_address unless addr.nil?
|
150
|
+
end
|
151
|
+
@address
|
152
|
+
end
|
153
|
+
|
154
|
+
def task_id
|
155
|
+
['autoclean', 'nodetool']
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
# Run the "nodetool ring" command and return the output
|
161
|
+
#
|
162
|
+
# @return [String, nil] Output from the "nodetool ring" command
|
163
|
+
#
|
164
|
+
def nodetool_ring
|
165
|
+
@nodetool_ring ||= DaemonRunner::ShellOut.new(command: 'nodetool ring', timeout: 300)
|
166
|
+
@nodetool_ring.run!
|
167
|
+
@nodetool_ring.stdout
|
168
|
+
end
|
169
|
+
|
170
|
+
# Run the "nodetool status' command and return the output
|
171
|
+
#
|
172
|
+
# @return [String, nil] Output from the "nodetool status" command
|
173
|
+
#
|
174
|
+
def nodetool_status
|
175
|
+
@nodetool_status ||= DaemonRunner::ShellOut.new(command: 'nodetool status', timeout: 300)
|
176
|
+
@nodetool_status.run!
|
177
|
+
@nodetool_status.stdout
|
178
|
+
end
|
179
|
+
|
180
|
+
# Run the "nodetool netstats' command and return the output
|
181
|
+
#
|
182
|
+
# @return [String, nil] Output from the "nodetool netstats" command
|
183
|
+
#
|
184
|
+
def nodetool_netstats
|
185
|
+
@nodetool_netstats ||= DaemonRunner::ShellOut.new(command: 'nodetool netstats', timeout: 300)
|
186
|
+
@nodetool_netstats.run!
|
187
|
+
@nodetool_netstats.stdout
|
188
|
+
end
|
189
|
+
|
190
|
+
# Get the status of a "nodetool cleanup" command
|
191
|
+
#
|
192
|
+
# This will atempt to track a running "nodetool cleanup" process if one's
|
193
|
+
# found. If a running process isn't found, a new process will be launched.
|
194
|
+
#
|
195
|
+
# @return [Process::Status, nil]
|
196
|
+
#
|
197
|
+
def nodetool_cleanup
|
198
|
+
pid = find_nodetool_cleanup
|
199
|
+
if pid
|
200
|
+
logger.debug "Found nodetool cleanup process #{pid} already running"
|
201
|
+
Utils::Statsd.new('cassandra.cleanup.running').push!(1)
|
202
|
+
end
|
203
|
+
pid = exec_nodetool_cleanup
|
204
|
+
if pid
|
205
|
+
logger.debug "Started nodetool cleanup process #{pid}"
|
206
|
+
Utils::Statsd.new('cassandra.cleanup.running').push!(1)
|
207
|
+
status = wait_nodetool_cleanup pid
|
208
|
+
logger.debug "Completed nodetool cleanup process #{pid}"
|
209
|
+
end
|
210
|
+
status
|
211
|
+
end
|
212
|
+
|
213
|
+
# Get the ID of the first running "nodetool cleanup" process found
|
214
|
+
#
|
215
|
+
# @return [Integer, nil]
|
216
|
+
#
|
217
|
+
def find_nodetool_cleanup
|
218
|
+
@pgrep_nodetool_cleanup ||= ::DaemonRunner::ShellOut.new(command: 'pgrep -f "NodeCmd.+cleanu[p]"', valid_exit_codes: [0,1])
|
219
|
+
@pgrep_nodetool_cleanup.run!
|
220
|
+
pids = @pgrep_nodetool_cleanup.stdout.strip.split "\n"
|
221
|
+
return nil if pids.empty?
|
222
|
+
pids.first.to_i
|
223
|
+
end
|
224
|
+
|
225
|
+
# Run "nodetool cleanup" command
|
226
|
+
#
|
227
|
+
# @return [Integer] ID of the "nodetool cleanup" command
|
228
|
+
#
|
229
|
+
def exec_nodetool_cleanup
|
230
|
+
# The `pgroup: true` option spawns cleanup in its own process group.
|
231
|
+
# So if this process dies, cleanup continues to run.
|
232
|
+
@nodetool_cleanup ||= ::DaemonRunner::ShellOut.new(command: 'nodetool cleanup', wait: false)
|
233
|
+
@nodetool_cleanup.run!
|
234
|
+
end
|
235
|
+
|
236
|
+
# Wait for a "nodetool cleanup" process to exit
|
237
|
+
#
|
238
|
+
# This handles the `SystemCallError` that's raised if no child process is
|
239
|
+
# found. In that case, the returned status will be `nil`.
|
240
|
+
#
|
241
|
+
# @return [Process::Status, nil] status
|
242
|
+
#
|
243
|
+
def wait_nodetool_cleanup pid
|
244
|
+
logger.debug "Waiting for nodetool cleanup process #{pid} to complete"
|
245
|
+
::DaemonRunner::ShellOut.wait2(pid, Process::WUNTRACED)
|
246
|
+
end
|
247
|
+
|
248
|
+
# Get the cache tokens wil be saved in
|
249
|
+
#
|
250
|
+
# @return [File] File where tokens wil be saved
|
251
|
+
#
|
252
|
+
def token_cache
|
253
|
+
File.new(token_cache_path, 'w+')
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'tasks/autoclean'
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'mixlib/shellout'
|
2
|
-
require 'statsd'
|
3
2
|
|
4
3
|
module Cassandra
|
5
4
|
module Utils
|
@@ -12,7 +11,7 @@ module Cassandra
|
|
12
11
|
end
|
13
12
|
|
14
13
|
def timeout
|
15
|
-
|
14
|
+
300
|
16
15
|
end
|
17
16
|
|
18
17
|
def runner
|
@@ -29,23 +28,9 @@ module Cassandra
|
|
29
28
|
@command.error!
|
30
29
|
@stdout = @command.stdout
|
31
30
|
out = output
|
32
|
-
|
31
|
+
Utils::Statsd.new(metric_name).to_dd(out).push!
|
33
32
|
out
|
34
33
|
end
|
35
|
-
|
36
|
-
protected
|
37
|
-
|
38
|
-
def statsd
|
39
|
-
@statsd ||= ::Statsd.new('localhost', 8125)
|
40
|
-
end
|
41
|
-
|
42
|
-
def push_metric(value)
|
43
|
-
statsd.gauge(metric_name, value)
|
44
|
-
end
|
45
|
-
|
46
|
-
def to_dd(out)
|
47
|
-
out == true ? 1 : 0
|
48
|
-
end
|
49
34
|
end
|
50
35
|
end
|
51
36
|
end
|
@@ -6,10 +6,30 @@ module Cassandra
|
|
6
6
|
|
7
7
|
def tasks
|
8
8
|
[
|
9
|
-
[
|
10
|
-
[
|
9
|
+
[auto_clean_task, 'run!'],
|
10
|
+
[health_stat, 'run!'],
|
11
|
+
[compaction_stat, 'run!'],
|
12
|
+
[cleanup_stat, 'run!']
|
11
13
|
]
|
12
14
|
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def auto_clean_task
|
19
|
+
@auto_clean_task ||= ::Cassandra::Tasks::Autoclean.new(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def health_stat
|
23
|
+
@health_stat ||= ::Cassandra::Utils::Stats::Health.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def compaction_stat
|
27
|
+
@compaction_stat ||= ::Cassandra::Utils::Stats::Compaction.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def cleanup_stat
|
31
|
+
@cleanup_stat ||= ::Cassandra::Utils::Stats::Cleanup.new
|
32
|
+
end
|
13
33
|
end
|
14
34
|
end
|
15
35
|
end
|
@@ -9,12 +9,15 @@ module Cassandra
|
|
9
9
|
|
10
10
|
def output
|
11
11
|
cleanup = stdout.lines.any? { |l| l.include?('Cleanup') }
|
12
|
-
to_dd(cleanup)
|
13
12
|
end
|
14
13
|
|
15
14
|
def metric_name
|
16
15
|
'cassandra.cleanup.running'
|
17
16
|
end
|
17
|
+
|
18
|
+
def task_id
|
19
|
+
['cleanup', 'nodetool']
|
20
|
+
end
|
18
21
|
end
|
19
22
|
end
|
20
23
|
end
|
@@ -9,12 +9,15 @@ module Cassandra
|
|
9
9
|
|
10
10
|
def output
|
11
11
|
compaction = stdout.lines.any? { |l| l.include?('Compaction') }
|
12
|
-
to_dd(compaction)
|
13
12
|
end
|
14
13
|
|
15
14
|
def metric_name
|
16
15
|
'cassandra.compaction.running'
|
17
16
|
end
|
17
|
+
|
18
|
+
def task_id
|
19
|
+
['compaction', 'nodetool']
|
20
|
+
end
|
18
21
|
end
|
19
22
|
end
|
20
23
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Cassandra
|
2
|
+
module Utils
|
3
|
+
module Stats
|
4
|
+
class Health < Utils::CLI::Base
|
5
|
+
def run!
|
6
|
+
running = true
|
7
|
+
if state == :normal
|
8
|
+
running &&= nodetool_statusgossip.strip == 'running'
|
9
|
+
running &&= nodetool_statusthrift.strip == 'running'
|
10
|
+
end
|
11
|
+
Utils::Statsd.new(metric_name).to_dd(running).push!
|
12
|
+
running
|
13
|
+
end
|
14
|
+
|
15
|
+
def metric_name
|
16
|
+
'cassandra.service.running'
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return the state of the Cassandra node
|
20
|
+
#
|
21
|
+
# The returned state is reported by "nodetool netstats".
|
22
|
+
#
|
23
|
+
# @return [state, nil]
|
24
|
+
#
|
25
|
+
def state
|
26
|
+
results = (nodetool_netstats || '').split("\n")
|
27
|
+
results.map! { |line| line.strip }
|
28
|
+
results.select! { |line| line.include? 'Mode:' }
|
29
|
+
results.map! { |line| line.split(':')[1] }
|
30
|
+
results.compact!
|
31
|
+
return nil if results.size != 1
|
32
|
+
results.first.strip.downcase.to_sym
|
33
|
+
end
|
34
|
+
|
35
|
+
def task_id
|
36
|
+
['health', 'nodetool']
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# Run the "nodetool statusgossip' command and return the output
|
42
|
+
#
|
43
|
+
# @return [String, nil] Output from the "nodetool statusgossip" command
|
44
|
+
#
|
45
|
+
def nodetool_statusgossip
|
46
|
+
@nodetool_statusgossip ||= DaemonRunner::ShellOut.new(command: 'nodetool statusgossip')
|
47
|
+
@nodetool_statusgossip.run!
|
48
|
+
@nodetool_statusgossip.stdout
|
49
|
+
end
|
50
|
+
|
51
|
+
# Run the "nodetool statusthrift' command and return the output
|
52
|
+
#
|
53
|
+
# @return [String, nil] Output from the "nodetool statusthrift" command
|
54
|
+
#
|
55
|
+
def nodetool_statusthrift
|
56
|
+
@nodetool_statusthrift||= DaemonRunner::ShellOut.new(command: 'nodetool statusthrift')
|
57
|
+
@nodetool_statusthrift.run!
|
58
|
+
@nodetool_statusthrift.stdout
|
59
|
+
end
|
60
|
+
|
61
|
+
# Run the "nodetool netstats' command and return the output
|
62
|
+
#
|
63
|
+
# @return [String, nil] Output from the "nodetool netstats" command
|
64
|
+
#
|
65
|
+
def nodetool_netstats
|
66
|
+
@nodetool_netstats ||= DaemonRunner::ShellOut.new(command: 'nodetool netstats', timeout: 300)
|
67
|
+
@nodetool_netstats.run!
|
68
|
+
@nodetool_netstats.stdout
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'statsd'
|
2
|
+
|
3
|
+
module Cassandra
|
4
|
+
module Utils
|
5
|
+
class Statsd
|
6
|
+
attr_reader :statsd, :metric_name, :value
|
7
|
+
|
8
|
+
def initialize(metric_name)
|
9
|
+
@statsd ||= ::Statsd.new('localhost', 8125)
|
10
|
+
@metric_name = metric_name
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_dd(value)
|
15
|
+
@value = (value == true ? 1 : 0)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def push!(value = @value)
|
20
|
+
statsd.gauge(metric_name, value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/cassandra/utils.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cassandra-utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1.pre.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Thompson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mixlib-shellout
|
@@ -129,12 +129,16 @@ files:
|
|
129
129
|
- bin/console
|
130
130
|
- bin/setup
|
131
131
|
- cassandra-utils.gemspec
|
132
|
+
- lib/cassandra/tasks.rb
|
133
|
+
- lib/cassandra/tasks/autoclean.rb
|
132
134
|
- lib/cassandra/utils.rb
|
133
135
|
- lib/cassandra/utils/cli/base.rb
|
134
136
|
- lib/cassandra/utils/daemon.rb
|
135
137
|
- lib/cassandra/utils/stats.rb
|
136
138
|
- lib/cassandra/utils/stats/cleanup.rb
|
137
139
|
- lib/cassandra/utils/stats/compaction.rb
|
140
|
+
- lib/cassandra/utils/stats/health.rb
|
141
|
+
- lib/cassandra/utils/statsd.rb
|
138
142
|
- lib/cassandra/utils/version.rb
|
139
143
|
homepage: https://github.com/rapid7/cassandra-utils
|
140
144
|
licenses:
|
@@ -151,9 +155,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
151
155
|
version: '0'
|
152
156
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
157
|
requirements:
|
154
|
-
- - "
|
158
|
+
- - ">"
|
155
159
|
- !ruby/object:Gem::Version
|
156
|
-
version:
|
160
|
+
version: 1.3.1
|
157
161
|
requirements: []
|
158
162
|
rubyforge_project:
|
159
163
|
rubygems_version: 2.4.3
|