graphiterb 0.1.5 → 0.2.0
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.
- 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
|