graphite-api 0.0.0.21
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/README.md +80 -0
- data/Rakefile +11 -0
- data/bin/graphite-middleware +5 -0
- data/lib/graphite-api.rb +18 -0
- data/lib/graphite-api/buffer.rb +110 -0
- data/lib/graphite-api/client.rb +70 -0
- data/lib/graphite-api/connector.rb +41 -0
- data/lib/graphite-api/logger.rb +18 -0
- data/lib/graphite-api/middleware.rb +74 -0
- data/lib/graphite-api/runner.rb +69 -0
- data/lib/graphite-api/scheduler.rb +42 -0
- data/lib/graphite-api/utils.rb +26 -0
- data/lib/graphite-api/version.rb +22 -0
- data/tasks/build.rake +49 -0
- data/tasks/tests.rake +3 -0
- metadata +71 -0
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# GraphiteAPI
|
2
|
+
|
3
|
+
A Ruby API toolkit for [Graphite](http://graphite.wikidot.com/)
|
4
|
+
|
5
|
+
* Graphite ruby client.
|
6
|
+
* Graphite middleware server, a lightweight, event-driven, aggregator daemon.
|
7
|
+
|
8
|
+
## Why using it?
|
9
|
+
Written in ruby
|
10
|
+
Simple and light-width (only one gem dependency)
|
11
|
+
Comes with built-in middleware server
|
12
|
+
|
13
|
+
## Client Usage
|
14
|
+
```ruby
|
15
|
+
require 'graphite-api'
|
16
|
+
|
17
|
+
client = GraphiteAPI::Client.new(
|
18
|
+
:host => "graphite.example.com",
|
19
|
+
:port => 2003,
|
20
|
+
:prefix => ["example","prefix"], # add example.prefix to each key
|
21
|
+
:interval => 60 # send to graphite every 60 seconds
|
22
|
+
)
|
23
|
+
|
24
|
+
# Simple:
|
25
|
+
client.add_metrics("webServer.web01.loadAvg" => 10.7)
|
26
|
+
# => example.prefix.webServer.web01.loadAvg 10.7 time.now.stamp
|
27
|
+
|
28
|
+
# Multiple with time:
|
29
|
+
client.add_metrics({
|
30
|
+
"webServer.web01.loadAvg" => 10.7,
|
31
|
+
"webServer.web01.memUsage" => 40
|
32
|
+
},Time.at(1326067060))
|
33
|
+
# => example.prefix.webServer.web01.loadAvg 10.7 1326067060
|
34
|
+
# => example.prefix.webServer.web01.memUsage 40 1326067060
|
35
|
+
|
36
|
+
# Every 10 sec
|
37
|
+
client.every(10) do
|
38
|
+
client.add_metrics("webServer.web01.uptime" => `uptime`.split.first.to_i)
|
39
|
+
end
|
40
|
+
|
41
|
+
client.join # wait...
|
42
|
+
```
|
43
|
+
## Middleware Usage
|
44
|
+
|
45
|
+
`graphite-middleware --help`
|
46
|
+
|
47
|
+
```
|
48
|
+
Graphite Middleware Server
|
49
|
+
|
50
|
+
Usage: graphite-middleware [options]
|
51
|
+
-g, --graphite HOST graphite host
|
52
|
+
-p, --port PORT listening port (default 2003)
|
53
|
+
-l, --log-file FILE log file
|
54
|
+
-L, --log-level LEVEL log level (default warn)
|
55
|
+
-P, --pid-file FILE pid file (default /var/run/graphite-middleware.pid)
|
56
|
+
-d, --daemonize run in background
|
57
|
+
-i, --interval INT report every X seconds (default 60)
|
58
|
+
-s, --slice SECONDS send to graphite in X seconds slices (default is 60)
|
59
|
+
-c, --cache HOURS cache expiration time in hours (default is 12 hours)
|
60
|
+
```
|
61
|
+
|
62
|
+
## Installation
|
63
|
+
install the latest from github
|
64
|
+
|
65
|
+
```
|
66
|
+
git clone git://github.com/kontera-technologies/graphite-api.git
|
67
|
+
cd graphite-api
|
68
|
+
rake install
|
69
|
+
```
|
70
|
+
|
71
|
+
## Bugs
|
72
|
+
|
73
|
+
If you find a bug, feel free to report it @ our [issues tracker](https://github.com/kontera-technologies/graphite-api/issues) on github.
|
74
|
+
|
75
|
+
## License
|
76
|
+
|
77
|
+
It is free software, and may be redistributed under the terms specified in [LICENSE](https://github.com/kontera-technologies/graphite-api/blob/master/LICENSE).
|
78
|
+
|
79
|
+
## Warranty
|
80
|
+
This software is provided “as is” and without any express or implied warranties, including, without limitation, the implied warranties of merchantability and fitness for a particular purpose.
|
data/Rakefile
ADDED
data/lib/graphite-api.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module GraphiteAPI
|
2
|
+
ROOT = File.expand_path(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
autoload :Version, "#{ROOT}/graphite-api/version"
|
5
|
+
autoload :Client, "#{ROOT}/graphite-api/client"
|
6
|
+
autoload :Scheduler, "#{ROOT}/graphite-api/scheduler"
|
7
|
+
autoload :Connector, "#{ROOT}/graphite-api/connector"
|
8
|
+
autoload :Middleware, "#{ROOT}/graphite-api/middleware"
|
9
|
+
autoload :Runner, "#{ROOT}/graphite-api/runner"
|
10
|
+
autoload :Utils, "#{ROOT}/graphite-api/utils"
|
11
|
+
autoload :Buffer, "#{ROOT}/graphite-api/buffer"
|
12
|
+
autoload :Logger, "#{ROOT}/graphite-api/logger"
|
13
|
+
|
14
|
+
def self.version
|
15
|
+
GraphiteAPI::Version.string
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# -----------------------------------------------------
|
2
|
+
# Buffer Object
|
3
|
+
# Handle Socket & Client data streams
|
4
|
+
# -----------------------------------------------------
|
5
|
+
# Usage:
|
6
|
+
# buff = GraphiteAPI::Buffer.new(GraphiteAPI::Utils.default_options)
|
7
|
+
# buff << {:metric => {"load_avg" => 10},:time => Time.now}
|
8
|
+
# buff << {:metric => {"load_avg" => 30},:time => Time.now}
|
9
|
+
# buff.stream "mem.usage 1"
|
10
|
+
# buff.stream "90 1326842563\n"
|
11
|
+
# buff.stream "shuki.tuki 999 1326842563\n"
|
12
|
+
# buff.each {|o| p o}
|
13
|
+
#
|
14
|
+
# Produce:
|
15
|
+
# ["load_avg", 40.0, 1326881160]
|
16
|
+
# ["mem.usage", 190.0, 1326842520]
|
17
|
+
# ["shuki.tuki", 999.0, 1326842520]
|
18
|
+
# -----------------------------------------------------
|
19
|
+
module GraphiteAPI
|
20
|
+
class Buffer
|
21
|
+
attr_reader :leftovers,:options,:new_records,:in_cache_mode
|
22
|
+
|
23
|
+
def initialize(options)
|
24
|
+
@options = options
|
25
|
+
@leftovers = Hash.new {|h,k| h[k] = Array.new}
|
26
|
+
@new_records = []
|
27
|
+
@in_cache_mode = !options[:cache_exp].nil?
|
28
|
+
start_cleaner if in_cache_mode
|
29
|
+
end
|
30
|
+
|
31
|
+
def << hash
|
32
|
+
time = Utils.normalize_time(hash[:time],options[:slice])
|
33
|
+
hash[:metric].each do |k,v|
|
34
|
+
buffer[time][k] += v.to_f
|
35
|
+
new_records << [time,k]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def stream(data,client_id = nil)
|
40
|
+
got_leftovers = data[-1,1] != "\n"
|
41
|
+
data = data.split(/\n/)
|
42
|
+
unless leftovers[client_id].empty?
|
43
|
+
if (valid leftovers[client_id].last + data.first rescue nil)
|
44
|
+
data.unshift(leftovers[client_id].pop + data.shift)
|
45
|
+
end
|
46
|
+
leftovers[client_id].clear
|
47
|
+
end
|
48
|
+
|
49
|
+
leftovers[client_id] << data.pop if got_leftovers
|
50
|
+
data.each do |line|
|
51
|
+
next unless valid line
|
52
|
+
key,val,time = line.split
|
53
|
+
self << {:metric => {key => val},:time => (Time.at(time.to_i) rescue Time.now)}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def each
|
58
|
+
new_records.uniq.each do |time,key|
|
59
|
+
yield [prefix + key,buffer[time][key],time]
|
60
|
+
end and clear
|
61
|
+
end
|
62
|
+
|
63
|
+
def empty?
|
64
|
+
buffer.empty?
|
65
|
+
end
|
66
|
+
|
67
|
+
def got_new_records?
|
68
|
+
!new_records.empty?
|
69
|
+
end
|
70
|
+
|
71
|
+
def size
|
72
|
+
buffer.values.map(&:values).flatten.size
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def clear
|
77
|
+
new_records.clear
|
78
|
+
buffer.clear unless in_cache_mode
|
79
|
+
end
|
80
|
+
|
81
|
+
def valid(data)
|
82
|
+
data =~ /^[\w|\.]+ \d+(?:\.|\d)* \d+$/
|
83
|
+
end
|
84
|
+
|
85
|
+
def prefix
|
86
|
+
@prefix ||= options[:prefix].empty? ? String.new : prefix_to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
def prefix_to_s
|
90
|
+
[options[:prefix]].flatten.join('.') << "."
|
91
|
+
end
|
92
|
+
|
93
|
+
def buffer
|
94
|
+
@buffer ||= Hash.new {|h,k| h[k] = Hash.new {|h1,k1| h1[k1] = 0}}
|
95
|
+
end
|
96
|
+
|
97
|
+
def clean(age)
|
98
|
+
[buffer,new_records].each {|o| o.delete_if {|t,k| now - t > age}}
|
99
|
+
end
|
100
|
+
|
101
|
+
def now
|
102
|
+
Time.now.to_i
|
103
|
+
end
|
104
|
+
|
105
|
+
def start_cleaner
|
106
|
+
Scheduler.every(options[:cleaner_interval]) { clean options[:cache_exp] }
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# -----------------------------------------------------
|
2
|
+
# Graphite Client
|
3
|
+
# Send metrics to graphite (or to some kind of middleware/proxy)
|
4
|
+
# -----------------------------------------------------
|
5
|
+
# Usage
|
6
|
+
#
|
7
|
+
# client = GraphiteAPI::Client.new(
|
8
|
+
# :host => "graphite.example.com",
|
9
|
+
# :port => 2003,
|
10
|
+
# :prefix => ["example","prefix"], # add example.prefix to each key
|
11
|
+
# :interval => 60 # send to graphite every 60 seconds
|
12
|
+
# )
|
13
|
+
#
|
14
|
+
# # Simple:
|
15
|
+
# client.add_metrics("webServer.web01.loadAvg" => 10.7)
|
16
|
+
# # => example.prefix.webServer.web01.loadAvg 10.7 time.now.stamp
|
17
|
+
#
|
18
|
+
# # Multiple with time:
|
19
|
+
# client.add_metrics({
|
20
|
+
# "webServer.web01.loadAvg" => 10.7,
|
21
|
+
# "webServer.web01.memUsage" => 40
|
22
|
+
# },Time.at(1326067060))
|
23
|
+
# # => example.prefix.webServer.web01.loadAvg 10.7 1326067060
|
24
|
+
# # => example.prefix.webServer.web01.memUsage 40 1326067060
|
25
|
+
#
|
26
|
+
# # Every 10 sec
|
27
|
+
# client.every(10) do
|
28
|
+
# client.add_metrics("webServer.web01.uptime" => `uptime`.split.first.to_i)
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# client.join # wait...
|
32
|
+
# -----------------------------------------------------
|
33
|
+
module GraphiteAPI
|
34
|
+
class Client
|
35
|
+
attr_reader :options,:buffer,:connector
|
36
|
+
|
37
|
+
def initialize(opt)
|
38
|
+
@options = GraphiteAPI::Utils.default_options.merge opt
|
39
|
+
@buffer = GraphiteAPI::Buffer.new(options)
|
40
|
+
@connector = GraphiteAPI::Connector.new(*options.values_at(:host,:port))
|
41
|
+
start_scheduler
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_metrics(m,time = Time.now)
|
45
|
+
buffer << {:metric => m, :time => time}
|
46
|
+
end
|
47
|
+
|
48
|
+
def join
|
49
|
+
sleep 1 while buffer.got_new_records?
|
50
|
+
end
|
51
|
+
|
52
|
+
def stop
|
53
|
+
Scheduler.stop
|
54
|
+
end
|
55
|
+
|
56
|
+
def every(frequency,&block)
|
57
|
+
Scheduler.every(frequency,&block)
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
def start_scheduler
|
62
|
+
Scheduler.every(options[:interval]) {send_metrics}
|
63
|
+
end
|
64
|
+
|
65
|
+
def send_metrics
|
66
|
+
buffer.each {|arr| connector.puts arr.join(" ")}
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -----------------------------------------------------
|
2
|
+
# TCP Socket connection
|
3
|
+
# -----------------------------------------------------
|
4
|
+
# Usage:
|
5
|
+
# connector = GraphiteAPI::Connector.new("localhost",2003)
|
6
|
+
# connector.puts("my.metric 1092 1232123231")
|
7
|
+
#
|
8
|
+
# Socket:
|
9
|
+
# => my.metric 1092 1232123231\n
|
10
|
+
# -----------------------------------------------------
|
11
|
+
require 'socket'
|
12
|
+
module GraphiteAPI
|
13
|
+
class Connector
|
14
|
+
attr_reader :options
|
15
|
+
|
16
|
+
def initialize(host,port)
|
17
|
+
@host = host
|
18
|
+
@port = port
|
19
|
+
end
|
20
|
+
|
21
|
+
def puts(msg)
|
22
|
+
begin
|
23
|
+
Logger.debug msg
|
24
|
+
socket.puts(msg)
|
25
|
+
rescue Errno::EPIPE
|
26
|
+
@socket = nil
|
27
|
+
retry
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def socket
|
34
|
+
if @socket.nil? || @socket.closed?
|
35
|
+
@socket = TCPSocket.new(@host,@port)
|
36
|
+
end
|
37
|
+
@socket
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -----------------------------------------------------
|
2
|
+
# GraphiteAPI Logger
|
3
|
+
# -----------------------------------------------------
|
4
|
+
# Usage:
|
5
|
+
# Graphite::Logger.logger = ::Logger.new(STDOUT)
|
6
|
+
# Graphite::Logger.info "shuki tuki"
|
7
|
+
# Graphite::Logger.debug "hihi"
|
8
|
+
# -----------------------------------------------------
|
9
|
+
module GraphiteAPI
|
10
|
+
class Logger
|
11
|
+
class << self
|
12
|
+
attr_accessor :logger
|
13
|
+
def method_missing(m,*args,&block)
|
14
|
+
if logger.respond_to? m then logger.send(m,*args,&block) end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# -----------------------------------------------------
|
2
|
+
# Graphite Middleware Server
|
3
|
+
# Should be placed between graphite server and graphite clients
|
4
|
+
# - Data Aggregator
|
5
|
+
# - Caching
|
6
|
+
# - Data Manipulation
|
7
|
+
# -----------------------------------------------------
|
8
|
+
# Usage:
|
9
|
+
# GraphiteAPI::Middleware.start(options)
|
10
|
+
#
|
11
|
+
# Options:
|
12
|
+
# graphite_host target graphite hostname
|
13
|
+
# graphite_port target graphite listening port (default 2003)
|
14
|
+
# cache_exp cache lifetime in seconds (default is 43200 seconds)
|
15
|
+
# prefix add prefix to each key
|
16
|
+
# interval report to graphite every X seconds (default is 60)
|
17
|
+
# slice send to graphite in X seconds slices (default is 60)
|
18
|
+
# log_level info # TODO: move this to runner.rb
|
19
|
+
# -----------------------------------------------------
|
20
|
+
require 'rubygems'
|
21
|
+
require 'eventmachine'
|
22
|
+
require 'logger'
|
23
|
+
require 'socket'
|
24
|
+
|
25
|
+
module GraphiteAPI
|
26
|
+
class Middleware < EventMachine::Connection
|
27
|
+
|
28
|
+
attr_reader :logger,:buffer,:client_id
|
29
|
+
|
30
|
+
def initialize(logger,buffer)
|
31
|
+
@logger = logger
|
32
|
+
@buffer = buffer
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def post_init
|
37
|
+
logger.debug "Client connecting"
|
38
|
+
@client_id = Socket.unpack_sockaddr_in(get_peername).join(":")
|
39
|
+
end
|
40
|
+
|
41
|
+
def receive_data(data)
|
42
|
+
buffer.stream(data,client_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def unbind
|
46
|
+
logger.debug "Client disconnecting"
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.start(options)
|
50
|
+
EventMachine.run do
|
51
|
+
# Resources
|
52
|
+
GraphiteAPI::Logger.logger = ::Logger.new(options[:log_file] || STDOUT)
|
53
|
+
GraphiteAPI::Logger.level = eval "::Logger::#{options[:log_level].to_s.upcase}"
|
54
|
+
|
55
|
+
buffer = GraphiteAPI::Buffer.new(options)
|
56
|
+
connector = GraphiteAPI::Connector.new(*options.values_at(:graphite_host,:graphite_port))
|
57
|
+
|
58
|
+
# Starting server
|
59
|
+
EventMachine.start_server('0.0.0.0',options[:listening_port],self,GraphiteAPI::Logger.logger,buffer)
|
60
|
+
GraphiteAPI::Logger.info "Server running on port #{options[:listening_port]}"
|
61
|
+
|
62
|
+
# Send metrics to graphite every X seconds
|
63
|
+
GraphiteAPI::Scheduler.every(options[:interval]) do
|
64
|
+
if buffer.got_new_records?
|
65
|
+
Logger.debug "Sending #{buffer.size} records to graphite (@#{options[:graphite_host]}:#{options[:graphite_port]})"
|
66
|
+
buffer.each { |arr| connector.puts arr.join(" ") }
|
67
|
+
end # if got_new_records?
|
68
|
+
end # every
|
69
|
+
end # run
|
70
|
+
end # start
|
71
|
+
end # Middleware
|
72
|
+
end # GraphiteAPI
|
73
|
+
#require File.dirname(__FILE__) + "/../graphite-api"
|
74
|
+
#GraphiteAPI::Middleware.start(GraphiteAPI::Utils.default_options)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module GraphiteAPI
|
4
|
+
class Runner
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(argv)
|
8
|
+
parser.parse! argv
|
9
|
+
validate_options
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
if options[:daemonize]
|
14
|
+
fork do
|
15
|
+
Process.setsid
|
16
|
+
exit if fork
|
17
|
+
Dir.chdir('/tmp')
|
18
|
+
STDOUT.reopen('/dev/null','a')
|
19
|
+
STDIN.reopen('/dev/null')
|
20
|
+
STDERR.reopen('/dev/null','a')
|
21
|
+
write_pid
|
22
|
+
run!
|
23
|
+
end
|
24
|
+
else
|
25
|
+
run!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def options
|
31
|
+
@options ||= Utils.default_options
|
32
|
+
end
|
33
|
+
|
34
|
+
def write_pid
|
35
|
+
begin
|
36
|
+
File.open(options[:pid], 'w') { |f| f.write(Process.pid) }
|
37
|
+
rescue Exception
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def run!
|
42
|
+
GraphiteAPI::Middleware.start(options)
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_options
|
46
|
+
abort "You must specify graphite host" if options[:graphite_host].nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
def parser
|
50
|
+
OptionParser.new do |opts|
|
51
|
+
opts.banner = "Graphite Middleware Server"
|
52
|
+
opts.define_head "Usage: graphite-middleware [options]"
|
53
|
+
opts.define_head ""
|
54
|
+
opts.on("-g", "--graphite HOST","graphite host") {|v| options[:graphite_host] = v}
|
55
|
+
opts.on("-p", "--port PORT","listening port (default 2003)"){|v| options[:listening_port] = v}
|
56
|
+
opts.on("-l", "--log-file FILE","log file") {|v| options[:log_file] = File.expand_path(v)}
|
57
|
+
opts.on("-L", "--log-level LEVEL","log level (default warn)") {|v|options[:log_level] = v}
|
58
|
+
opts.on("-P", "--pid-file FILE","pid file (default /var/run/graphite-middleware.pid)"){|v|options[:pid] = v}
|
59
|
+
opts.on("-d", "--daemonize","run in background"){options[:daemonize] = true}
|
60
|
+
opts.on("-i", "--interval INT","report every X seconds (default 60)"){|v|options[:interval] = v.to_i unless v.to_i == 0}
|
61
|
+
opts.on("-s", "--slice SECONDS","send to graphite in X seconds slices (default is 60)") {|v| options[:slice] = v.to_i unless v.to_i == 0}
|
62
|
+
opts.on("-c", "--cache HOURS","cache expiration time in hours (default is 12 hours)") {|v| (options[:cache_exp] = v.to_i * 3600) unless v.to_i == 0}
|
63
|
+
opts.define_tail ""
|
64
|
+
opts.define_tail ""
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'eventmachine'
|
3
|
+
|
4
|
+
module GraphiteAPI
|
5
|
+
class Scheduler
|
6
|
+
@@wrapper = nil
|
7
|
+
@@timers = []
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def every(frequency,&block)
|
11
|
+
reactor_running? or start_reactor
|
12
|
+
timers << EventMachine::PeriodicTimer.new(frequency) { yield }
|
13
|
+
timers.last
|
14
|
+
end
|
15
|
+
|
16
|
+
def stop
|
17
|
+
timers.map(&:cancel)
|
18
|
+
wrapper and EventMachine.stop
|
19
|
+
end
|
20
|
+
|
21
|
+
def join
|
22
|
+
wrapper and wrapper.join
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def start_reactor
|
27
|
+
@@wrapper = Thread.new { EventMachine.run }
|
28
|
+
wrapper.abort_on_exception = true
|
29
|
+
Thread.pass until reactor_running?
|
30
|
+
end
|
31
|
+
|
32
|
+
def reactor_running?
|
33
|
+
EventMachine.reactor_running?
|
34
|
+
end
|
35
|
+
|
36
|
+
def wrapper;@@wrapper end
|
37
|
+
def timers; @@timers end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module GraphiteAPI
|
2
|
+
module Utils
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def normalize_time(time,slice = 60)
|
6
|
+
((time || Time.now).to_i / slice * slice).to_i
|
7
|
+
end
|
8
|
+
|
9
|
+
def default_options
|
10
|
+
{
|
11
|
+
:cleaner_interval => 43200,
|
12
|
+
:graphite_port => 2003,
|
13
|
+
:listening_port => 2003,
|
14
|
+
:log_level => :info,
|
15
|
+
:cache_exp => nil,
|
16
|
+
:host => "localhost",
|
17
|
+
:port => 2003,
|
18
|
+
:prefix => [],
|
19
|
+
:interval => 60,
|
20
|
+
:slice => 60,
|
21
|
+
:pid => "/var/run/graphite-middleware.pid"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module GraphiteAPI
|
2
|
+
class Version
|
3
|
+
PFILE = File.join(GraphiteAPI::ROOT,"..",".pre_version")
|
4
|
+
class << self
|
5
|
+
def string
|
6
|
+
[0,0,0,pre].join(".")
|
7
|
+
end
|
8
|
+
|
9
|
+
def increment_pre
|
10
|
+
new_version = pre + 1
|
11
|
+
File.open(PFILE,"w") { |f| f.puts new_version }
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def pre
|
16
|
+
File.read(PFILE).to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
data/tasks/build.rake
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems/package_task'
|
2
|
+
|
3
|
+
GraphiteAPI::GemSpec = Gem::Specification.new do |s|
|
4
|
+
s.name = "graphite-api"
|
5
|
+
s.version = GraphiteAPI.version
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.summary = "GraphiteAPI"
|
8
|
+
s.description = "GraphiteAPI - Graphite API tools"
|
9
|
+
s.author = "Eran Levi"
|
10
|
+
s.email = 'eran@kontera.com'
|
11
|
+
s.homepage = 'http://www.kontera.com'
|
12
|
+
s.executables = %w(graphite-middleware)
|
13
|
+
s.required_ruby_version = '>= 1.8.7'
|
14
|
+
s.rubyforge_project = "graphite-api"
|
15
|
+
s.files = %w(README.md Rakefile) + Dir.glob("{bin,lib,test,tasks}/**/*")
|
16
|
+
s.require_path = "lib"
|
17
|
+
s.bindir = "bin"
|
18
|
+
|
19
|
+
s.add_dependency 'eventmachine','>= 0.3.3'
|
20
|
+
end
|
21
|
+
|
22
|
+
task :gem => [:clobber_package]
|
23
|
+
Gem::PackageTask.new(GraphiteAPI::GemSpec) do |p|
|
24
|
+
p.gem_spec = GraphiteAPI::GemSpec
|
25
|
+
end
|
26
|
+
|
27
|
+
task :install => [:gem] do
|
28
|
+
sh "gem install pkg/graphite-api"
|
29
|
+
Rake::Task['clobber_package'].execute
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace :gem do
|
33
|
+
desc "Update GraphiteAPI gem version"
|
34
|
+
task :update_version do
|
35
|
+
GraphiteAPI::Version.increment_pre
|
36
|
+
msg "Incrementing version to #{GraphiteAPI::Version.string}..."
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Upload GraphiteAPI to Kontera's repo"
|
40
|
+
task :upload => [:build] do
|
41
|
+
sh "gem inabox --host http://gems.kontera.com pkg/graphite-api-#{GraphiteAPI.version}.gem"
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Update GraphiteAPI gem version and build gem"
|
45
|
+
task :build => [:test,:update_version] do
|
46
|
+
sh "rake gem"
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/tasks/tests.rake
ADDED
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: graphite-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0.21
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eran Levi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-27 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: eventmachine
|
16
|
+
requirement: &2152684380 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.3.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2152684380
|
25
|
+
description: GraphiteAPI - Graphite API tools
|
26
|
+
email: eran@kontera.com
|
27
|
+
executables:
|
28
|
+
- graphite-middleware
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- README.md
|
33
|
+
- Rakefile
|
34
|
+
- bin/graphite-middleware
|
35
|
+
- lib/graphite-api/buffer.rb
|
36
|
+
- lib/graphite-api/client.rb
|
37
|
+
- lib/graphite-api/connector.rb
|
38
|
+
- lib/graphite-api/logger.rb
|
39
|
+
- lib/graphite-api/middleware.rb
|
40
|
+
- lib/graphite-api/runner.rb
|
41
|
+
- lib/graphite-api/scheduler.rb
|
42
|
+
- lib/graphite-api/utils.rb
|
43
|
+
- lib/graphite-api/version.rb
|
44
|
+
- lib/graphite-api.rb
|
45
|
+
- tasks/build.rake
|
46
|
+
- tasks/tests.rake
|
47
|
+
homepage: http://www.kontera.com
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 1.8.7
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project: graphite-api
|
67
|
+
rubygems_version: 1.8.13
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: GraphiteAPI
|
71
|
+
test_files: []
|