graphiterb 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/graphiterb.gemspec +17 -9
- data/lib/graphiterb/monitors/directory_tree.rb +123 -0
- data/lib/graphiterb/monitors/disk_space.rb +29 -0
- data/lib/graphiterb/monitors.rb +160 -0
- data/lib/graphiterb/{graphite_script.rb → script.rb} +1 -4
- data/lib/graphiterb/{graphite_sender.rb → sender.rb} +5 -13
- data/lib/graphiterb/utils/extensions.rb +7 -0
- data/lib/graphiterb/utils/log.rb +16 -0
- data/lib/graphiterb/utils/system.rb +17 -0
- data/lib/graphiterb/utils.rb +17 -0
- data/lib/graphiterb.rb +8 -7
- data/spec/graphiterb_spec.rb +1 -1
- metadata +34 -15
- data/lib/graphiterb/graphite_logger.rb +0 -42
- data/lib/graphiterb/graphite_system_logger.rb +0 -5
data/Rakefile
CHANGED
@@ -10,6 +10,7 @@ begin
|
|
10
10
|
gem.email = "info@infochimps.org"
|
11
11
|
gem.homepage = "http://github.com/infochimps/graphiterb"
|
12
12
|
gem.authors = ["Philip (flip) Kromer (@mrflip)"]
|
13
|
+
gem.add_dependency "configliere", ">= 0"
|
13
14
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
15
|
gem.add_development_dependency "yard", ">= 0"
|
15
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/graphiterb.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{graphiterb}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Philip (flip) Kromer (@mrflip)"]
|
12
|
-
s.date = %q{2010-08-
|
12
|
+
s.date = %q{2010-08-17}
|
13
13
|
s.description = %q{Uses http://github.com/mrflip/configliere and http://graphite.wikidot.com}
|
14
14
|
s.email = %q{info@infochimps.org}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -32,10 +32,15 @@ Gem::Specification.new do |s|
|
|
32
32
|
"examples/toy.rb",
|
33
33
|
"graphiterb.gemspec",
|
34
34
|
"lib/graphiterb.rb",
|
35
|
-
"lib/graphiterb/
|
36
|
-
"lib/graphiterb/
|
37
|
-
"lib/graphiterb/
|
38
|
-
"lib/graphiterb/
|
35
|
+
"lib/graphiterb/monitors.rb",
|
36
|
+
"lib/graphiterb/monitors/directory_tree.rb",
|
37
|
+
"lib/graphiterb/monitors/disk_space.rb",
|
38
|
+
"lib/graphiterb/script.rb",
|
39
|
+
"lib/graphiterb/sender.rb",
|
40
|
+
"lib/graphiterb/utils.rb",
|
41
|
+
"lib/graphiterb/utils/extensions.rb",
|
42
|
+
"lib/graphiterb/utils/log.rb",
|
43
|
+
"lib/graphiterb/utils/system.rb",
|
39
44
|
"spec/graphiterb_spec.rb",
|
40
45
|
"spec/spec.opts",
|
41
46
|
"spec/spec_helper.rb"
|
@@ -48,11 +53,11 @@ Gem::Specification.new do |s|
|
|
48
53
|
s.test_files = [
|
49
54
|
"spec/graphiterb_spec.rb",
|
50
55
|
"spec/spec_helper.rb",
|
56
|
+
"examples/toy.rb",
|
51
57
|
"examples/storage_monitor.rb",
|
52
|
-
"examples/api_call_monitor.rb",
|
53
58
|
"examples/loadavg_graphite_sender.rb",
|
54
|
-
"examples/
|
55
|
-
"examples/
|
59
|
+
"examples/file_monitor.rb",
|
60
|
+
"examples/api_call_monitor.rb"
|
56
61
|
]
|
57
62
|
|
58
63
|
if s.respond_to? :specification_version then
|
@@ -60,13 +65,16 @@ Gem::Specification.new do |s|
|
|
60
65
|
s.specification_version = 3
|
61
66
|
|
62
67
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
68
|
+
s.add_runtime_dependency(%q<configliere>, [">= 0"])
|
63
69
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
64
70
|
s.add_development_dependency(%q<yard>, [">= 0"])
|
65
71
|
else
|
72
|
+
s.add_dependency(%q<configliere>, [">= 0"])
|
66
73
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
67
74
|
s.add_dependency(%q<yard>, [">= 0"])
|
68
75
|
end
|
69
76
|
else
|
77
|
+
s.add_dependency(%q<configliere>, [">= 0"])
|
70
78
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
71
79
|
s.add_dependency(%q<yard>, [">= 0"])
|
72
80
|
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module Graphiterb
|
2
|
+
module Monitors
|
3
|
+
|
4
|
+
# A class for monitoring the contents of a directory.
|
5
|
+
#
|
6
|
+
# Will only monitor files modified within the last hour by
|
7
|
+
# default.
|
8
|
+
class DirectoryTree < Graphiterb::Monitors::PeriodicMonitor
|
9
|
+
|
10
|
+
# The root of the directory tree being monitored.
|
11
|
+
attr_accessor :root
|
12
|
+
|
13
|
+
# A regular expression filter that must be matched by files
|
14
|
+
# within the root directory to be counted.
|
15
|
+
attr_accessor :filter_re
|
16
|
+
|
17
|
+
def initialize main_scope, root, options={}
|
18
|
+
super(main_scope, options)
|
19
|
+
self.root = File.expand_path(root)
|
20
|
+
self.filter_re = self.options[:filter_re] || /.*/
|
21
|
+
end
|
22
|
+
|
23
|
+
def dirs
|
24
|
+
@dirs ||= Dir[File.join(root, '*')].select{|d| File.directory?(d) }.map { |path| Directory.new(path, filter_re) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_metrics metrics, since
|
28
|
+
recent = Directory.recency_filter
|
29
|
+
dirs.each do |dir|
|
30
|
+
metrics << [scope(dir.name, 'num_files', hostname), dir.num_files(&recent) ]
|
31
|
+
metrics << [scope(dir.name, 'size', hostname), dir.size(&recent) ]
|
32
|
+
metrics << [scope(dir.name, 'lines', hostname), dir.line_counts(&recent) ]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# A class for monitoring the contents of a directory.
|
37
|
+
class Directory
|
38
|
+
|
39
|
+
# Path to sample for files
|
40
|
+
attr_accessor :path
|
41
|
+
|
42
|
+
# Wildcard sequence for files under the current directory.
|
43
|
+
attr_accessor :filter_re
|
44
|
+
|
45
|
+
# A recent file was modified within this window.
|
46
|
+
attr_accessor :recent_window
|
47
|
+
|
48
|
+
# Only consider the last this-many files.
|
49
|
+
MAX_FILES = 30
|
50
|
+
|
51
|
+
def initialize path, filter_re=/.*/, options={}
|
52
|
+
self.path = path
|
53
|
+
self.filter_re = filter_re
|
54
|
+
end
|
55
|
+
|
56
|
+
# Name for this pool, suitable for inclusion in a Graphite
|
57
|
+
# target.
|
58
|
+
#
|
59
|
+
# @return [String]
|
60
|
+
def name
|
61
|
+
path.gsub(/\./,'_').gsub(%r{/}, '.').gsub(%r{(^\.|\.$)},'')
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Lists all files in the pool
|
66
|
+
# @param filter_block files only keeps filenames that pass this filter
|
67
|
+
#
|
68
|
+
def files &filter_block
|
69
|
+
Dir[File.join(path, '**/*')].
|
70
|
+
reject{|f| File.directory?(f) }.
|
71
|
+
select{|f| f =~ filter_re }.
|
72
|
+
sort.reverse[0..MAX_FILES].
|
73
|
+
select(&filter_block)
|
74
|
+
end
|
75
|
+
|
76
|
+
def num_files &filter_block
|
77
|
+
files(&filter_block).count
|
78
|
+
end
|
79
|
+
|
80
|
+
def sizes &filter_block
|
81
|
+
files(&filter_block).map{|f| File.size(f) rescue nil }.compact
|
82
|
+
end
|
83
|
+
|
84
|
+
def size &filter_block
|
85
|
+
sizes(&filter_block).sum
|
86
|
+
end
|
87
|
+
|
88
|
+
def avg_size &filter_block
|
89
|
+
sizes(&filter_block).sum.to_f / num_files(&filter_block).to_f
|
90
|
+
end
|
91
|
+
|
92
|
+
def lines_in_result_of command, *args
|
93
|
+
begin
|
94
|
+
escaped_args = args.map{|f| "'#{f}'" }
|
95
|
+
result = `#{command} #{escaped_args.join(" ")}`.chomp
|
96
|
+
result.split(/[\r\n]+/)
|
97
|
+
rescue StandardError => e ; warn(e.backtrace, e) ; return nil ; end
|
98
|
+
end
|
99
|
+
|
100
|
+
def wc
|
101
|
+
@wc ||= `which wc`.chomp
|
102
|
+
end
|
103
|
+
|
104
|
+
def line_counts &filter_block
|
105
|
+
files = files(&filter_block) ; return 0 if files.blank?
|
106
|
+
result = lines_in_result_of(wc, '-l', *files) or return 0
|
107
|
+
counts = result.map{|string| string =~ /^\s*(\d+)\s+/ and $1 }.compact
|
108
|
+
counts.map(&:to_i).sum
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.recent? file
|
112
|
+
(Time.now - File.mtime(file)) < 3600
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.recency_filter
|
116
|
+
Proc.new{|file| recent?(file) }
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Graphiterb
|
2
|
+
module Monitors
|
3
|
+
|
4
|
+
# A monitor for how much space is available on a node.
|
5
|
+
class DiskSpace < Graphiterb::Monitors::PeriodicMonitor
|
6
|
+
|
7
|
+
# Runs and parses `df'.
|
8
|
+
#
|
9
|
+
# disk_space.df
|
10
|
+
# #=> [["/dev/sda", "39373712", "20488716", "16884908", "55%", "/"], ["/dev/sdb", "920090332", "397413344", "475939088", "46%", "/home"]]
|
11
|
+
#
|
12
|
+
# @return [Array<Array>]
|
13
|
+
def df
|
14
|
+
`/bin/df`.chomp.split("\n").
|
15
|
+
grep(%r{^/dev/}).
|
16
|
+
map{|line| line.split(/\s+/) } rescue []
|
17
|
+
end
|
18
|
+
|
19
|
+
# Calls +df+ and adds the space available metric.
|
20
|
+
def get_metrics metrics, since
|
21
|
+
# "/dev/sdb1", "39373712", "20488716", "16884908", "55%", "/"
|
22
|
+
df.each do |handle, size, spaceused, spacefree, percentfree, location|
|
23
|
+
disk_name = handle.gsub(/^\//, '').split('/')
|
24
|
+
metrics << [scope(hostname, disk_name, 'available'), spacefree.to_i]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module Graphiterb
|
2
|
+
module Monitors
|
3
|
+
|
4
|
+
autoload :DiskSpace, 'graphiterb/monitors/disk_space'
|
5
|
+
autoload :DirectoryTree, 'graphiterb/monitors/directory_tree'
|
6
|
+
|
7
|
+
# Accepts a lightweight call every iteration.
|
8
|
+
#
|
9
|
+
# Once either a time or an iteration criterion is met, executes the block
|
10
|
+
# and resets the timer until next execution.
|
11
|
+
#
|
12
|
+
# Note that the +time_interval+ is measured *excution to execution* and not
|
13
|
+
# in multiples of iter_interval. Say I set a time_interval of 300s, and
|
14
|
+
# happen to iterate at 297s and 310s after start. Then the monitor will
|
15
|
+
# execute at 310s, and the next execution will happen on or after 610s.
|
16
|
+
#
|
17
|
+
# Also note that when *either* criterion is met, *both* criteria are
|
18
|
+
# reset. Say I set a time interval of 300s and an +iter_interval+ of 10_000;
|
19
|
+
# and that at 250s I reach iteration 10_000. Then the monitor will execute
|
20
|
+
# on or after 20_000 iteration or 550s, whichever happens first.
|
21
|
+
#
|
22
|
+
# Stolen from Monkeyshines::Monitor::PeriodicMonitor
|
23
|
+
class PeriodicMonitor
|
24
|
+
|
25
|
+
# The main scope under which the monitor's metrics will be
|
26
|
+
# written.
|
27
|
+
attr_accessor :main_scope
|
28
|
+
|
29
|
+
# Maximum number of seconds that should elapse between running
|
30
|
+
# the monitor.
|
31
|
+
attr_accessor :time_interval
|
32
|
+
|
33
|
+
# Maximum number of internal "iterations" that should elapse between running the monitor
|
34
|
+
attr_accessor :iter_interval
|
35
|
+
|
36
|
+
# The options hash the monitor was created with.
|
37
|
+
attr_accessor :options
|
38
|
+
|
39
|
+
# Internal metrics stored by the monitor.
|
40
|
+
attr_accessor :last_time, :current_iter, :iter, :started_at
|
41
|
+
|
42
|
+
# Provides methods for finding out about the node this code is
|
43
|
+
# running on.
|
44
|
+
include Graphiterb::Utils::SystemInfo
|
45
|
+
|
46
|
+
# Create a new PeriodicMonitor
|
47
|
+
def initialize main_scope, options={}
|
48
|
+
self.main_scope = main_scope
|
49
|
+
self.started_at = Time.now.utc.to_f
|
50
|
+
self.last_time = started_at
|
51
|
+
self.iter = 0
|
52
|
+
self.current_iter = 0
|
53
|
+
self.options = options
|
54
|
+
self.time_interval = options[:time] || 30
|
55
|
+
self.iter_interval = options[:iters] || 30
|
56
|
+
end
|
57
|
+
|
58
|
+
# The Graphiterb::Sender used to communicate with the Graphite
|
59
|
+
# server.
|
60
|
+
#
|
61
|
+
# @return [Graphiterb::Sender]
|
62
|
+
def sender
|
63
|
+
@sender ||= Graphiterb::Sender.new
|
64
|
+
end
|
65
|
+
|
66
|
+
# True if more than +iter_interval+ has elapsed since last
|
67
|
+
# execution.
|
68
|
+
def enough_iterations?
|
69
|
+
iter % iter_interval == 0 if iter_interval
|
70
|
+
end
|
71
|
+
|
72
|
+
# True if more than +time_interval+ has elapsed since last execution.
|
73
|
+
def enough_time? now
|
74
|
+
(now - last_time) > time_interval if time_interval
|
75
|
+
end
|
76
|
+
|
77
|
+
# Time since monitor was created
|
78
|
+
#
|
79
|
+
# @return [Time]
|
80
|
+
def since
|
81
|
+
Time.now.utc.to_f - started_at
|
82
|
+
end
|
83
|
+
|
84
|
+
# Overall iterations per second
|
85
|
+
#
|
86
|
+
# @return [Float]
|
87
|
+
def rate
|
88
|
+
iter.to_f / since.to_f
|
89
|
+
end
|
90
|
+
|
91
|
+
# "Instantaneous" iterations per second
|
92
|
+
#
|
93
|
+
# @return [Float]
|
94
|
+
def inst_rate now
|
95
|
+
current_iter.to_f / (now-last_time).to_f
|
96
|
+
end
|
97
|
+
|
98
|
+
# Return the scope built from this monitor's +main_scope+ and
|
99
|
+
# the given +names+.
|
100
|
+
#
|
101
|
+
# monitor.main_scope
|
102
|
+
# #=> 'system.parameters'
|
103
|
+
# monitor.scope 'disk', 'space'
|
104
|
+
# #=> 'system.paramters.disk.space'
|
105
|
+
#
|
106
|
+
# @param [Array<String>] names
|
107
|
+
# @return [String]
|
108
|
+
def scope *names
|
109
|
+
[main_scope, *names].flatten.reject(&:blank?).join('.')
|
110
|
+
end
|
111
|
+
|
112
|
+
# If the interval conditions are met, executes block; otherwise
|
113
|
+
# just does bookkeeping and returns.
|
114
|
+
#
|
115
|
+
# @yield [Array<String>, Time]
|
116
|
+
def periodically &block
|
117
|
+
self.iter += 1
|
118
|
+
self.current_iter += 1
|
119
|
+
now = Time.now.utc.to_f
|
120
|
+
if enough_iterations? || enough_time?(now)
|
121
|
+
metrics = []
|
122
|
+
block.call(metrics, (now-last_time))
|
123
|
+
sender.send(*metrics)
|
124
|
+
self.last_time = now
|
125
|
+
self.current_iter = 0
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Add metrics to the +metrics+ array.
|
130
|
+
#
|
131
|
+
# This method is meant to be overridden by a sub-class (indeed,
|
132
|
+
# it will raise an error if called directly).
|
133
|
+
#
|
134
|
+
# It should take an array of metrics and a time interval since
|
135
|
+
# last ran and insert metrics into the array.")
|
136
|
+
#
|
137
|
+
# @param [Array<String>] metrics
|
138
|
+
# @param [Time] since the last time the monitor ran
|
139
|
+
def get_metrics metrics, since
|
140
|
+
raise Graphiterb::NotImplementedError.new("Override the get_metrics method of the #{self.class} class")
|
141
|
+
end
|
142
|
+
|
143
|
+
# Run this monitor.
|
144
|
+
#
|
145
|
+
# Sleep for 1 second and then wake up and check if either enough
|
146
|
+
# time (+time_interval+) or enough iterations (+iter_interval+)
|
147
|
+
# have passed run +get_metrics+ if so.
|
148
|
+
def run!
|
149
|
+
loop do
|
150
|
+
periodically do |metrics, since|
|
151
|
+
get_metrics metrics, since
|
152
|
+
end
|
153
|
+
sleep 1
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'graphiterb'
|
3
|
-
require 'wukong/extensions'
|
4
|
-
Configliere.use :commandline, :config_file, :define
|
5
3
|
|
4
|
+
Configliere.use :commandline, :config_file, :define
|
6
5
|
Log = ::Logger.new($stderr) unless defined?(Log)
|
7
|
-
|
8
|
-
Settings.read 'graphite.yaml'
|
9
6
|
Settings.resolve!
|
@@ -1,23 +1,15 @@
|
|
1
1
|
module Graphiterb
|
2
|
-
|
3
|
-
# @example:
|
4
|
-
# # in initialize, perhaps
|
5
|
-
# self.sender = GraphiteSender
|
6
|
-
#
|
7
|
-
# # ... somewhere else ...
|
8
|
-
# sender.send( ['webserver.pages', pages_this_hour], ['webserver.errors', errors_this_hour] )
|
9
|
-
#
|
10
|
-
class GraphiteSender
|
2
|
+
class Sender
|
11
3
|
def initialize
|
12
4
|
open!
|
13
5
|
end
|
14
6
|
|
15
7
|
def open!
|
16
8
|
begin
|
17
|
-
|
9
|
+
Graphiterb.log.warn "Connecting to server #{Settings.carbon_server} port #{Settings.carbon_port}"
|
18
10
|
@socket = TCPSocket.new(Settings.carbon_server, Settings.carbon_port)
|
19
11
|
rescue StandardError => e
|
20
|
-
|
12
|
+
Graphiterb.log.warn "Couldn't connect to server #{Settings.carbon_server} port #{Settings.carbon_port}: #{e.class} #{e}"
|
21
13
|
$stderr
|
22
14
|
end
|
23
15
|
end
|
@@ -30,7 +22,7 @@ module Graphiterb
|
|
30
22
|
begin
|
31
23
|
block.call
|
32
24
|
rescue StandardError => e
|
33
|
-
|
25
|
+
Graphiterb.log.warn "Sleeping #{Settings.on_error_delay}: #{e.class} #{e}"
|
34
26
|
sleep Settings.on_error_delay
|
35
27
|
@socket = nil
|
36
28
|
return nil
|
@@ -46,7 +38,7 @@ module Graphiterb
|
|
46
38
|
safely do
|
47
39
|
message = metrics.map{|metric, val, ts| [metric, val, (ts||now)].join(" ") }.join("\n")+"\n"
|
48
40
|
socket.puts(message)
|
49
|
-
|
41
|
+
Graphiterb.log.info message.gsub(/\n+/, "\t")
|
50
42
|
end
|
51
43
|
end
|
52
44
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Graphiterb
|
4
|
+
|
5
|
+
class << self; attr_accessor :log end
|
6
|
+
|
7
|
+
# Create a Logger and point it at Graphiterb::LOG_FILE_DESTINATION which is
|
8
|
+
# set in ~/.imwrc and defaults to STDERR.
|
9
|
+
def self.instantiate_logger!
|
10
|
+
Graphiterb.log ||= Logger.new(Settings[:log])
|
11
|
+
Graphiterb.log.datetime_format = "%Y%m%d-%H:%M:%S "
|
12
|
+
Graphiterb.log.level = Logger::INFO
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
Graphiterb.instantiate_logger!
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Graphiterb
|
2
|
+
module Utils
|
3
|
+
|
4
|
+
# A module which provides information about the node this code is
|
5
|
+
# executing on.
|
6
|
+
#
|
7
|
+
# Maybe it's worth bringing Ohai into this. I'm not sure.
|
8
|
+
module SystemInfo
|
9
|
+
|
10
|
+
def hostname
|
11
|
+
@hostname ||= `hostname`.chomp.gsub(".","_")
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'socket'
|
3
|
+
require 'configliere'
|
4
|
+
|
5
|
+
require 'graphiterb/utils/log'
|
6
|
+
require 'graphiterb/utils/extensions'
|
7
|
+
|
8
|
+
module Graphiterb
|
9
|
+
|
10
|
+
Error = Class.new(StandardError)
|
11
|
+
NotImplementedError = Class.new(Error)
|
12
|
+
|
13
|
+
module Utils
|
14
|
+
autoload :SystemInfo, 'graphiterb/utils/system'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/lib/graphiterb.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
|
-
require '
|
2
|
-
require 'logger'
|
1
|
+
require 'graphiterb/utils'
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
Settings.use :define, :config_file
|
4
|
+
|
5
|
+
Settings.define :log, :default => STDOUT, :description => "Log output for Graphiterb"
|
6
6
|
Settings.define :carbon_server, :default => 'localhost', :description => "Host address for carbon database server", :required => true
|
7
7
|
Settings.define :carbon_port, :default => '2003', :description => "Port for carbon database server", :required => true
|
8
8
|
Settings.define :update_delay, :default => 30, :description => "How long to wait between updates. Must be faster than the value in the graphite/conf/storage-schemas", :required => true, :type => Integer
|
9
9
|
Settings.define :on_error_delay, :default => 0.1, :description => "How long to wait on connect errors", :required => true, :type => Float
|
10
10
|
|
11
|
-
|
11
|
+
Settings.read '/etc/graphiterb/graphiterb.yaml' if File.exist? '/etc/graphiterb/graphiterb.yaml'
|
12
|
+
|
12
13
|
module Graphiterb
|
13
|
-
autoload :
|
14
|
-
autoload :
|
14
|
+
autoload :Monitors, 'graphiterb/monitors'
|
15
|
+
autoload :Sender, 'graphiterb/sender'
|
15
16
|
end
|
data/spec/graphiterb_spec.rb
CHANGED
@@ -2,6 +2,6 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
3
3
|
describe "Graphiterb" do
|
4
4
|
it "fails" do
|
5
|
-
fail "hey buddy, you should probably rename this file and start specing for real"
|
5
|
+
fail "hey buddy, you should probably rename this file and start specing for real. seriously."
|
6
6
|
end
|
7
7
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphiterb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Philip (flip) Kromer (@mrflip)
|
@@ -15,13 +15,27 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-17 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
22
|
+
name: configliere
|
23
23
|
prerelease: false
|
24
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
25
39
|
none: false
|
26
40
|
requirements:
|
27
41
|
- - ">="
|
@@ -33,11 +47,11 @@ dependencies:
|
|
33
47
|
- 9
|
34
48
|
version: 1.2.9
|
35
49
|
type: :development
|
36
|
-
version_requirements: *
|
50
|
+
version_requirements: *id002
|
37
51
|
- !ruby/object:Gem::Dependency
|
38
52
|
name: yard
|
39
53
|
prerelease: false
|
40
|
-
requirement: &
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
55
|
none: false
|
42
56
|
requirements:
|
43
57
|
- - ">="
|
@@ -47,7 +61,7 @@ dependencies:
|
|
47
61
|
- 0
|
48
62
|
version: "0"
|
49
63
|
type: :development
|
50
|
-
version_requirements: *
|
64
|
+
version_requirements: *id003
|
51
65
|
description: Uses http://github.com/mrflip/configliere and http://graphite.wikidot.com
|
52
66
|
email: info@infochimps.org
|
53
67
|
executables: []
|
@@ -73,10 +87,15 @@ files:
|
|
73
87
|
- examples/toy.rb
|
74
88
|
- graphiterb.gemspec
|
75
89
|
- lib/graphiterb.rb
|
76
|
-
- lib/graphiterb/
|
77
|
-
- lib/graphiterb/
|
78
|
-
- lib/graphiterb/
|
79
|
-
- lib/graphiterb/
|
90
|
+
- lib/graphiterb/monitors.rb
|
91
|
+
- lib/graphiterb/monitors/directory_tree.rb
|
92
|
+
- lib/graphiterb/monitors/disk_space.rb
|
93
|
+
- lib/graphiterb/script.rb
|
94
|
+
- lib/graphiterb/sender.rb
|
95
|
+
- lib/graphiterb/utils.rb
|
96
|
+
- lib/graphiterb/utils/extensions.rb
|
97
|
+
- lib/graphiterb/utils/log.rb
|
98
|
+
- lib/graphiterb/utils/system.rb
|
80
99
|
- spec/graphiterb_spec.rb
|
81
100
|
- spec/spec.opts
|
82
101
|
- spec/spec_helper.rb
|
@@ -117,8 +136,8 @@ summary: Fast Ubiquitous Dashboard Logs with Graphite (http://graphite.wikidot.c
|
|
117
136
|
test_files:
|
118
137
|
- spec/graphiterb_spec.rb
|
119
138
|
- spec/spec_helper.rb
|
139
|
+
- examples/toy.rb
|
120
140
|
- examples/storage_monitor.rb
|
121
|
-
- examples/api_call_monitor.rb
|
122
141
|
- examples/loadavg_graphite_sender.rb
|
123
|
-
- examples/toy.rb
|
124
142
|
- examples/file_monitor.rb
|
143
|
+
- examples/api_call_monitor.rb
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'monkeyshines/monitor'
|
2
|
-
|
3
|
-
module Graphiterb
|
4
|
-
class GraphiteLogger < Monkeyshines::Monitor::PeriodicMonitor
|
5
|
-
# Connection to graphite server
|
6
|
-
attr_reader :sender
|
7
|
-
# the leading segment for sent metrics -- eg 'scrapers' or 'api_calls'
|
8
|
-
attr_reader :main_scope
|
9
|
-
|
10
|
-
def initialize main_scope, *args
|
11
|
-
super *args
|
12
|
-
self.time_interval ||= Settings.update_delay
|
13
|
-
@sender = GraphiteSender.new
|
14
|
-
@main_scope = main_scope
|
15
|
-
end
|
16
|
-
|
17
|
-
def periodically &block
|
18
|
-
super do |iter, since|
|
19
|
-
metrics = []
|
20
|
-
block.call(metrics, iter, since)
|
21
|
-
sender.send *metrics
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def hostname
|
26
|
-
@host ||= `hostname`.chomp.gsub(".","_")
|
27
|
-
end
|
28
|
-
|
29
|
-
def scope_name *scope
|
30
|
-
[main_scope, scope].flatten.reject(&:blank?).join('.')
|
31
|
-
end
|
32
|
-
|
33
|
-
def run!
|
34
|
-
loop do
|
35
|
-
periodically do |metrics, iter, since|
|
36
|
-
get_metrics metrics, iter, since
|
37
|
-
end
|
38
|
-
sleep 1
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|