cassandra-utils 0.2.1 → 0.3.1.pre.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|