graphite-api 0.0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|