graphite-api 0.0.1.4 → 0.0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,50 +2,90 @@
2
2
  A Ruby API toolkit for [Graphite](http://graphite.wikidot.com/).
3
3
 
4
4
  ## Description
5
- Graphite client and utilities for ruby
5
+ **GraphiteAPI** is a library written in Ruby that provides two ways for interacting with **Graphite's Carbon Daemon**, the first is for Ruby applications using the **GraphiteAPI::Client**, the second is through **GraphiteAPI-Middleware** daemon, both methods implements Graphite's [plaintext protocol](http://graphite.readthedocs.org/en/1.0/feeding-carbon.html).
6
6
 
7
- * **Simple** client for ruby.
7
+ ## Package Content
8
+ * Includes a **simple** client for ruby.
8
9
  * Ships with a **GraphiteAPI-Middleware**, which is a lightweight, event-driven, aggregator daemon.
9
10
  * only one dependency (EventMachine).
10
11
  * Utilities like scheduling and caching.
11
12
 
12
- ## Features
13
- * Multiple Graphite Servers Support - GraphiteAPI-Middleware supports sending aggregated data to multiple graphite servers, useful for large data centers and backup purposes
14
- * Reanimation mode - support cases which the same keys (same timestamps as well) can be received simultaneously and asynchronously from multiple input sources, in these cases GraphiteAPI-Middleware will "reanimate" old records (records that were already sent to Graphite server), and will send the sum of the reanimated record value + the value of the record that was just received to the graphite server; this new summed record should override the key with the new value on Graphite database.
13
+ ## Key Features
14
+ * **Multiple Graphite Servers Support** - GraphiteAPI-Middleware supports sending aggregated data to multiple graphite servers, useful for large data centers and backup purposes
15
+ * **Reanimation mode** - support cases which the same keys (same timestamps as well) can be received simultaneously and asynchronously from multiple input sources, in these cases GraphiteAPI-Middleware will "reanimate" old records (records that were already sent to Graphite server), and will send the sum of the reanimated record value + the value of the record that was just received to the graphite server; this new summed record should override the key with the new value on Graphite database.
16
+
17
+ ## Installation
18
+ Install stable version
19
+
20
+ ```
21
+ gem install graphite-api
22
+ ```
23
+
24
+ Install the latest from github
25
+
26
+ ```
27
+ git clone git://github.com/kontera-technologies/graphite-api.git
28
+ cd graphite-api
29
+ rake install
30
+ ```
15
31
 
16
32
  ## Client Usage
17
33
  ```ruby
18
- require 'graphite-api'
19
-
20
- client = GraphiteAPI::Client.new(
21
- :graphite => "graphite.example.com:2003",
22
- :prefix => ["example","prefix"], # add example.prefix to each key
23
- :interval => 60 # send to graphite every 60 seconds
24
- )
25
-
26
- # Simple:
27
- client.metrics("webServer.web01.loadAvg" => 10.7)
28
- # => example.prefix.webServer.web01.loadAvg 10.7 time.now.stamp
29
-
30
- # Multiple with time:
31
- client.metrics({
32
- "webServer.web01.loadAvg" => 10.7,
33
- "webServer.web01.memUsage" => 40
34
- },Time.at(1326067060))
35
- # => example.prefix.webServer.web01.loadAvg 10.7 1326067060
36
- # => example.prefix.webServer.web01.memUsage 40 1326067060
37
-
38
- # Every 10 sec
39
- client.every(10) do
40
- client.metrics("webServer.web01.uptime" => `uptime`.split.first.to_i)
41
- end
42
-
43
- client.join # wait...
34
+ require 'graphite-api'
35
+ require 'logger'
36
+
37
+ # Turn on the logging ( optional )
38
+ GraphiteAPI::Logger.logger = ::Logger.new(STDOUT)
39
+ GraphiteAPI::Logger.logger.level = ::Logger::DEBUG
40
+
41
+ # Setup client
42
+ client = GraphiteAPI::Client.new(
43
+ :graphite => "graphite.example.com:2003",
44
+ :prefix => ["example","prefix"], # add example.prefix to each key
45
+ :slice => 60.seconds # results are aggregated in 60 seconds slices
46
+ :interval => 60.seconds # send to graphite every 60 seconds
47
+ )
48
+
49
+ # Simple
50
+ client.webServer.web01.loadAvg 10.7
51
+ # => example.prefix.webServer.web01.loadAvg 10.7 time.now.to_i
52
+
53
+ # "Same Same But Different" ( http://en.wikipedia.org/wiki/Tinglish )
54
+ client.metrics "webServer.web01.loadAvg" => 10.7
55
+ # => example.prefix.webServer.web01.loadAvg 10.7 time.now.to_i
56
+
57
+ # With event time
58
+ client.webServer.web01.blaBlaBla(29.1, Time.at(9999999999))
59
+ # => example.prefix.webServer.web01.blaBlaBla 29.1 9999999999
60
+
61
+ # Multiple with event time
62
+ client.metrics({
63
+ "webServer.web01.loadAvg" => 10.7,
64
+ "webServer.web01.memUsage" => 40
65
+ },Time.at(1326067060))
66
+ # => example.prefix.webServer.web01.loadAvg 10.7 1326067060
67
+ # => example.prefix.webServer.web01.memUsage 40 1326067060
68
+
69
+ # Timers
70
+ client.every 10.seconds do |c|
71
+ c.webServer.web01.uptime `uptime`.split.first.to_i
72
+ # => example.prefix.webServer.web01.uptime 40 1326067060
73
+ end
74
+
75
+ client.every 52.minutes do |c|
76
+ c.abcd.efghi.jklmnop.qrst 12
77
+ # => example.prefix.abcd.efghi.jklmnop.qrst 12 1326067060
78
+ end
79
+
80
+ client.join # wait...
44
81
  ```
82
+ > more examples can be found [here](https://github.com/kontera-technologies/graphite-api/tree/master/examples).
83
+
45
84
  ## GraphiteAPI-Middleware Usage
85
+ * After installing GraphiteAPI gem, the `graphite-middleware` command should be available.
46
86
 
47
87
  ```
48
- [root@someplace]# graphite-middleware --help
88
+ [root@graphite-middleware-node]# graphite-middleware --help
49
89
 
50
90
  GraphiteAPI Middleware Server
51
91
 
@@ -63,21 +103,57 @@ Usage: graphite-middleware [options]
63
103
  More Info @ https://github.com/kontera-technologies/graphite-api
64
104
  ```
65
105
 
66
- ## Installation
67
- Install stable version
106
+ * launch **GraphiteAPI-Middleware** daemon
68
107
 
69
108
  ```
70
- gem install graphite-api
109
+ [root@graphite-middleware-node]# graphite-middleware \
110
+ --port 2005 \
111
+ --interval 60 \
112
+ --log-level debug \
113
+ --log-file /tmp/graphite-middleware.out \
114
+ --daemonize \
115
+ --graphite graphite-server:2003 \
116
+ --graphite graphite-backup-server:2003
71
117
  ```
72
118
 
73
- Install the latest from github
119
+ * Send metrics via **UDP/TCP sockets**
74
120
 
75
121
  ```
76
- git clone git://github.com/kontera-technologies/graphite-api.git
77
- cd graphite-api
78
- rake install
122
+ [root@graphite-middleware-node] telnet localhost 2005
123
+ Trying 127.0.0.1...
124
+ Connected to localhost.
125
+ Escape character is '^]'.
126
+ example.middleware.value 10.2 1335008343
127
+ example.middleware.value2 99 1334929231
128
+ ^C
129
+ [root@graphite-middleware-node]
79
130
  ```
80
131
 
132
+ * Send metrics via **GraphtieAPI client**
133
+
134
+ ```ruby
135
+ require 'graphite-api'
136
+ client = GraphiteAPI::Client.new(:graphite => graphite-middleware-node)
137
+ client.example.middleware.value 10.2
138
+ client.example.middleware.value2 27
139
+ client.bla.bla.value2 27
140
+ ```
141
+
142
+ > more examples can be found [here](https://github.com/kontera-technologies/graphite-api/tree/master/examples).
143
+
144
+
145
+ ## Recommended Topologies
146
+ <br/>
147
+
148
+ <img src="https://raw.github.com/kontera-technologies/graphite-api/master/examples/graphite-middleware-star.jpg" align="center">
149
+
150
+ <hr/>
151
+ <br/>
152
+
153
+ <img src="https://raw.github.com/kontera-technologies/graphite-api/master/examples/graphite-middleware-mesh.jpg" align="center">
154
+
155
+ <hr/>
156
+
81
157
  ## TODO:
82
158
  * Documentation
83
159
  * Use Redis
@@ -0,0 +1,20 @@
1
+ class Numeric
2
+ {
3
+ :year => 365 * 24 * 3600,
4
+ :month => 30 * 24 * 3600,
5
+ :week => 7 * 24 * 3600,
6
+ :day => 24 * 3600,
7
+ :hour => 3600,
8
+ :minute => 60,
9
+ :second => 1
10
+ }.each do |m,val|
11
+ respond_to? m or define_method m do
12
+ self * val
13
+ end
14
+
15
+ "#{m}s".tap do |plural|
16
+ respond_to? plural or alias_method plural, m
17
+ end
18
+
19
+ end
20
+ end
@@ -17,4 +17,5 @@ module GraphiteAPI
17
17
  GraphiteAPI::Version::VERSION
18
18
  end
19
19
 
20
+ Dir.glob( "#{ROOT}/core-extensions/**" ).each &method( :require )
20
21
  end
@@ -23,7 +23,7 @@ module GraphiteAPI
23
23
  attr_reader :options,:keys_to_send,:reanimation_mode, :streamer_buff
24
24
 
25
25
  CLOSING_STREAM_CHAR = "\n" # end of message - when streaming to buffer obj
26
- IGNORING_CHARS = "\r" # skip these chars when parsing new message
26
+ CHARS_TO_IGNORE = ["\r"] # skip these chars when parsing new message
27
27
  FLOATS_ROUND_BY = 2 # round(x) after summing floats
28
28
  VALID_MESSAGE = /^[\w|\.]+ \d+(?:\.|\d)* \d+$/ # how a valid message should look like
29
29
 
@@ -36,30 +36,37 @@ module GraphiteAPI
36
36
  end
37
37
 
38
38
  def push hash
39
- debug [:buffer,:add,hash]
40
- time = Utils::normalize_time(hash[:time],options[:slice])
39
+ debug [:buffer,:add, hash]
40
+ time = Utils.normalize_time(hash[:time],options[:slice])
41
41
  hash[:metric].each { |k,v| cache_set(time,k,v) }
42
42
  end
43
43
 
44
- alias :<< :push
44
+ alias_method :<<, :push
45
45
 
46
46
  def stream message, client_id = nil
47
47
  message.each_char do |char|
48
48
  next if invalid_char? char
49
- streamer_buff[client_id] << char
49
+ streamer_buff[client_id] += char
50
50
 
51
51
  if closed_stream? streamer_buff[client_id]
52
- push build_metric(*streamer_buff[client_id].split) if valid streamer_buff[client_id]
52
+ if valid streamer_buff[client_id]
53
+ push build_metric *streamer_buff[client_id].split
54
+ end
53
55
  streamer_buff.delete client_id
54
56
  end
55
-
56
57
  end
57
58
  end
58
59
 
59
- def pull(as = nil)
60
- [].tap do |data|
61
- keys_to_send.each { |t, k| k.each { |o| data.push cache_get(t, o, as) } } and clear
60
+ def pull as = nil
61
+ Array.new.tap do |data|
62
+ keys_to_send.each do |time,keys|
63
+ keys.each do |key|
64
+ data.push cache_get(time, key, as)
65
+ end
66
+ end
67
+ clear
62
68
  end
69
+
63
70
  end
64
71
 
65
72
  def new_records?
@@ -67,21 +74,22 @@ module GraphiteAPI
67
74
  end
68
75
 
69
76
  private
77
+
70
78
  def closed_stream? string
71
79
  string[-1,1] == CLOSING_STREAM_CHAR
72
80
  end
73
81
 
74
82
  def invalid_char? char
75
- IGNORING_CHARS.include? char
83
+ CHARS_TO_IGNORE.include? char
76
84
  end
77
85
 
78
86
  def cache_set time, key, value
79
- buffer_cache[time][key] = sum(buffer_cache[time][key],value.to_f)
80
- keys_to_send[time].push(key) unless keys_to_send[time].include?(key)
87
+ buffer_cache[time][key] = sum buffer_cache[time][key], value.to_f
88
+ keys_to_send[time].push key unless keys_to_send[time].include? key
81
89
  end
82
90
 
83
91
  def sum float1, float2
84
- ("%.#{FLOATS_ROUND_BY}f" % (float1 + float2)).to_f # can't use round on 1.8.7
92
+ ("%.#{FLOATS_ROUND_BY}f" % (float1 + float2)).to_f # can't use round on 1.8.X
85
93
  end
86
94
 
87
95
  def cache_get time, key, as
@@ -1,4 +1,5 @@
1
1
  require 'optparse'
2
+
2
3
  module GraphiteAPI
3
4
  class CLI
4
5
 
@@ -4,83 +4,120 @@
4
4
  # -----------------------------------------------------
5
5
  # Usage
6
6
  #
7
- # client = GraphiteAPI::Client.new(
8
- # :graphite => "graphite.example.com:2003",
9
- # :prefix => ["example","prefix"], # add example.prefix to each key
10
- # :interval => 60 # send to graphite every 60 seconds
11
- # )
7
+ # client = GraphiteAPI::Client.new(
8
+ # :graphite => "graphite.example.com:2003",
9
+ # :prefix => ["example","prefix"], # add example.prefix to each key
10
+ # :slice => 60.seconds # results are aggregated in 60 seconds slices
11
+ # :interval => 60.seconds # send to graphite every 60 seconds
12
+ # )
12
13
  #
13
- # # Simple:
14
- # client.metrics("webServer.web01.loadAvg" => 10.7)
15
- # # => example.prefix.webServer.web01.loadAvg 10.7 time.now.stamp
14
+ # # Simple
15
+ # client.webServer.web01.loadAvg 10.7
16
+ # # => example.prefix.webServer.web01.loadAvg 10.7 time.now.to_i
17
+
18
+ # # "Same Same But Different" ( http://en.wikipedia.org/wiki/Tinglish )
19
+ # client.metrics "webServer.web01.loadAvg" => 10.7
20
+ # # => example.prefix.webServer.web01.loadAvg 10.7 time.now.to_i
16
21
  #
17
- # # Multiple with time:
22
+ # # Multiple with event time
18
23
  # client.metrics({
19
- # "webServer.web01.loadAvg" => 10.7,
20
- # "webServer.web01.memUsage" => 40
24
+ # "webServer.web01.loadAvg" => 10.7,
25
+ # "webServer.web01.memUsage" => 40
21
26
  # },Time.at(1326067060))
22
27
  # # => example.prefix.webServer.web01.loadAvg 10.7 1326067060
23
28
  # # => example.prefix.webServer.web01.memUsage 40 1326067060
24
- #
25
- # # Every 10 sec
26
- # client.every(10) do
27
- # client.metrics("webServer.web01.uptime" => `uptime`.split.first.to_i)
28
- # end
29
- #
30
- # client.join # wait...
29
+ #
30
+ # # Timers
31
+ # client.every 10.seconds do |c|
32
+ # c.webServer.web01.uptime `uptime`.split.first.to_i
33
+ # # => example.prefix.webServer.web01.uptime 40 1326067060
34
+ # end
35
+ #
36
+ # client.every 52.minutes do |c|
37
+ # c.abcd.efghi.jklmnop.qrst 12
38
+ # # => example.prefix.abcd.efghi.jklmnop.qrst 12 1326067060
39
+ # end
40
+ #
41
+ # client.join # wait...
31
42
  # -----------------------------------------------------
43
+
44
+ require File.expand_path '../utils', __FILE__
45
+
32
46
  module GraphiteAPI
33
47
  class Client
34
48
  include Utils
35
49
 
36
- attr_reader :options,:buffer,:connectors
37
-
50
+ extend Utils::ClassMethods
51
+
38
52
  def initialize opt
39
- @options = build_options(validate(opt.clone))
40
- @buffer = GraphiteAPI::Buffer.new(options)
41
- @connectors = GraphiteAPI::ConnectorGroup.new(options)
42
- start_scheduler
53
+ @options = build_options validate opt.clone
54
+ @buffer = GraphiteAPI::Buffer.new options
55
+ @connectors = GraphiteAPI::ConnectorGroup.new options
56
+
57
+ every options.fetch :interval do
58
+ connectors.publish buffer.pull :string if buffer.new_records?
59
+ end
60
+
43
61
  end
44
62
 
45
- def add_metrics(m,time = Time.now)
46
- buffer.push(:metric => m, :time => time)
47
- end
48
- alias :metrics :add_metrics
63
+ attr_private_reader :options, :buffer, :connectors
64
+ delegate :loop, :stop, :to => :Reactor
49
65
 
50
- def join
51
- sleep 0.1 while buffer.new_records?
66
+ def every interval, &block
67
+ Reactor.every interval do
68
+ block.call self
69
+ end
52
70
  end
53
71
 
54
- def loop
55
- Reactor.loop
72
+ def metrics metric, time = Time.now
73
+ buffer.push :metric => metric, :time => time
56
74
  end
57
-
58
- def stop
59
- Reactor.stop
75
+
76
+ def join
77
+ sleep while buffer.new_records?
60
78
  end
61
79
 
62
- def every(frequency,&block)
63
- Reactor.every(frequency,&block)
80
+ def method_missing m, *args, &block
81
+ Proxy.new( self ).send m, *args, &block
64
82
  end
65
-
66
- protected
67
83
 
68
- def start_scheduler
69
- Reactor::every(options[:interval]) { send_metrics }
70
- end
84
+ protected
71
85
 
72
- def send_metrics
73
- connectors.publish buffer.pull(:string) if buffer.new_records?
86
+ class Proxy
87
+ extend Utils::ClassMethods
88
+
89
+ def initialize client
90
+ @client = client
91
+ @keys = []
92
+ end
93
+
94
+ attr_private_reader :client, :keys
95
+
96
+ def method_missing m, *args, &block
97
+ keys.push m
98
+ if keys.size > 10 # too deep
99
+ super
100
+ elsif !args.empty?
101
+ client.metrics(
102
+ Hash[keys.join("."),args.first],
103
+ *args[1..-1]
104
+ )
105
+ else
106
+ self
107
+ end
108
+ end
109
+
74
110
  end
75
-
76
- def validate opt
77
- raise ArgumentError.new ":graphite must be specified" if opt[:graphite].nil?
78
- opt
111
+
112
+ def validate options
113
+ options.tap do |opt|
114
+ raise ArgumentError.new ":graphite must be specified" if opt[:graphite].nil?
115
+ end
79
116
  end
80
117
 
81
118
  def build_options opt
82
119
  default_options.tap do |options_hash|
83
- options_hash[:backends] << expand_host(opt.delete(:graphite))
120
+ options_hash[:backends].push expand_host opt.delete :graphite
84
121
  options_hash.merge! opt
85
122
  options_hash.freeze
86
123
  end
@@ -15,7 +15,7 @@ module GraphiteAPI
15
15
 
16
16
  attr_reader :options, :host, :port
17
17
 
18
- def initialize(host,port)
18
+ def initialize host, port
19
19
  @host = host
20
20
  @port = port
21
21
  end
@@ -38,7 +38,7 @@ module GraphiteAPI
38
38
 
39
39
  def socket
40
40
  if @socket.nil? || @socket.closed?
41
- @socket = ::TCPSocket.new(host,port)
41
+ @socket = ::TCPSocket.new host, port
42
42
  end
43
43
  @socket
44
44
  end
@@ -5,6 +5,11 @@
5
5
  # Graphite::Logger.logger = ::Logger.new(STDOUT)
6
6
  # Graphite::Logger.info "shuki tuki"
7
7
  # Graphite::Logger.debug "hihi"
8
+ #
9
+ # Or:
10
+ # Graphite::Logger.init :level => :debug
11
+ # Graphite::Logger.info "shuki tuki"
12
+ # Graphite::Logger.debug "hihi"
8
13
  # -----------------------------------------------------
9
14
  require 'logger'
10
15
 
@@ -20,51 +20,60 @@
20
20
  require 'rubygems'
21
21
  require 'eventmachine'
22
22
  require 'socket'
23
+ require File.expand_path '../utils', __FILE__
23
24
 
24
25
  module GraphiteAPI
25
26
  class Middleware < EventMachine::Connection
26
- include GraphiteAPI::Utils
27
-
28
- attr_reader :logger,:buffer,:client_id
29
27
 
28
+ include Utils
29
+ extend Utils::ClassMethods
30
+
30
31
  def initialize buffer
31
- @buffer = buffer
32
- super
32
+ @buffer = buffer and super
33
33
  end
34
-
34
+
35
+ attr_private_reader :buffer,:client_id
36
+
35
37
  def post_init
36
- @client_id = Socket.unpack_sockaddr_in(get_peername).reverse.join(":")
37
- debug [:middleware,:connecting,client_id]
38
+ @client_id = peername
39
+ debug [:middleware, :connecting, client_id]
38
40
  end
39
41
 
40
42
  def receive_data data
41
- debug [:middleware,:message,client_id,data]
43
+ debug [:middleware, :message, client_id, data]
42
44
  buffer.stream data, client_id
43
45
  end
44
46
 
45
47
  def unbind
46
- debug [:middleware,:disconnecting,client_id]
48
+ debug [:middleware, :disconnecting, client_id]
47
49
  end
48
-
50
+
51
+ def peername
52
+ port, *ip = get_peername[2,6].unpack "nC4"
53
+ [ip.join("."),port].join ":"
54
+ end
55
+
56
+ private :peername
57
+
49
58
  def self.start options
50
59
  EventMachine.run do
51
- buffer = GraphiteAPI::Buffer.new(options)
52
- connectors = GraphiteAPI::ConnectorGroup.new(options)
53
-
54
- # Starting server
55
- EventMachine.start_server('0.0.0.0',options[:port],self,buffer)
56
60
  GraphiteAPI::Logger.info "Server running on port #{options[:port]}"
57
61
 
58
- # Send metrics to graphite every X seconds
59
- GraphiteAPI::Reactor::every( options[:interval] ) do
60
- connectors.publish buffer.pull(:string) if buffer.new_records?
61
- end # every
62
+ buffer = GraphiteAPI::Buffer.new options
63
+ group = GraphiteAPI::ConnectorGroup.new options
62
64
 
63
- GraphiteAPI::Reactor::add_shutdown_hook do
64
- connectors.publish buffer.pull(:string)
65
+ # Starting server
66
+ [:start_server, :open_datagram_socket].each do |m|
67
+ EventMachine.send(m,'0.0.0.0',options[:port],self,buffer)
65
68
  end
66
-
67
- end # run
69
+
70
+ # Send metrics to graphite every X seconds
71
+ proc { group.publish buffer.pull :string if buffer.new_records? }.tap do |block|
72
+ GraphiteAPI::Reactor.every options[:interval], &block
73
+ GraphiteAPI::Reactor.add_shutdown_hook &block
74
+ end
75
+ end
76
+
68
77
  end # start
69
78
  end # Middleware
70
79
  end # GraphiteAPI
@@ -8,7 +8,7 @@ module GraphiteAPI
8
8
  class << self
9
9
  def every(frequency,&block)
10
10
  reactor_running? or start_reactor
11
- timers << EventMachine::PeriodicTimer.new(frequency) { yield }
11
+ timers << EventMachine::PeriodicTimer.new(frequency.to_i) { yield }
12
12
  timers.last
13
13
  end
14
14
 
@@ -4,29 +4,29 @@ module GraphiteAPI
4
4
  class Runner
5
5
  include Utils
6
6
 
7
- def initialize(argv)
8
- GraphiteAPI::CLI::parse(argv,options)
7
+ def initialize argv
8
+ CLI.parse argv, options
9
9
  validate_options
10
10
  end
11
11
 
12
12
  def run
13
+ Logger.init Hash[[:std,:level].zip options.values_at(:log_file, :log_level) ]
13
14
  options[:daemonize] ? daemonize(options[:pid]) { run! } : run!
14
15
  end
15
16
 
16
17
  private
17
18
 
18
19
  def run!
19
- GraphiteAPI::Logger.init(:std => options[:log_file], :level => options[:log_level])
20
20
  begin
21
- Middleware::start options
21
+ Middleware.start options
22
22
  rescue Interrupt
23
- GraphiteAPI::Logger.info "Shutting down..."
24
- GraphiteAPI::Reactor::stop
23
+ Logger.info "Shutting down..."
24
+ Reactor.stop
25
25
  end
26
26
  end
27
27
 
28
28
  def options
29
- @options ||= Utils::default_options
29
+ @options ||= Utils.default_options
30
30
  end
31
31
 
32
32
  def validate_options
@@ -1,5 +1,26 @@
1
1
  module GraphiteAPI
2
2
  module Utils
3
+ module ClassMethods
4
+ def attr_private_reader *args
5
+ args.each { |o| attr_reader o or private o }
6
+ end
7
+
8
+ def delegate *sources, options
9
+ instance_eval do
10
+ options.fetch(:to).tap do |target|
11
+ sources.each do |source|
12
+ define_method source do |*args, &block|
13
+ if target.is_a? Symbol
14
+ eval String target
15
+ else
16
+ target
17
+ end.send source,*args, &block
18
+ end # define
19
+ end # sources
20
+ end # options
21
+ end # instance_eval
22
+ end # def delegate
23
+ end # ClassMethods
3
24
 
4
25
  [:info,:error,:warn,:debug].each do |m|
5
26
  define_method(m) do |*args,&block|
@@ -9,7 +30,7 @@ module GraphiteAPI
9
30
 
10
31
  module_function
11
32
 
12
- def normalize_time(time,slice = 60)
33
+ def normalize_time time, slice = 60
13
34
  ((time || Time.now).to_i / slice * slice).to_i
14
35
  end
15
36
 
@@ -30,12 +51,13 @@ module GraphiteAPI
30
51
  :prefix => [],
31
52
  :interval => 60,
32
53
  :slice => 60,
33
- :pid => "/var/run/graphite-middleware.pid"
54
+ :pid => "/tmp/graphite-middleware.pid"
34
55
  }
35
56
  end
36
57
 
37
58
  def daemonize pid
38
59
  block_given? or raise ArgumentError.new "the block is missing..."
60
+
39
61
  fork do
40
62
  Process.setsid
41
63
  exit if fork
@@ -43,10 +65,10 @@ module GraphiteAPI
43
65
  STDIN.reopen('/dev/null')
44
66
  STDOUT.reopen('/dev/null','a')
45
67
  STDERR.reopen('/dev/null','a')
46
- File.open(pid,'w') { |f| f.write(Process.pid) } rescue
68
+ File.open(pid,'w') { |f| f.write(Process.pid) } rescue nil
47
69
  yield
48
70
  end
49
71
  end
50
-
72
+
51
73
  end
52
74
  end
@@ -1,5 +1,5 @@
1
1
  module GraphiteAPI
2
2
  class Version
3
- VERSION = "0.0.1.4"
3
+ VERSION = "0.0.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphite-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.4
4
+ version: 0.0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-30 00:00:00.000000000 Z
12
+ date: 2012-11-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
16
- requirement: &70249458332220 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,12 @@ dependencies:
21
21
  version: 0.3.3
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70249458332220
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.3.3
25
30
  description: Graphite API - A Simple ruby client, aggregator daemon and API tools
26
31
  email: eran@kontera.com
27
32
  executables:
@@ -32,6 +37,7 @@ files:
32
37
  - README.md
33
38
  - Rakefile
34
39
  - bin/graphite-middleware
40
+ - lib/core-extensions/numeric.rb
35
41
  - lib/graphite-api/buffer.rb
36
42
  - lib/graphite-api/cli.rb
37
43
  - lib/graphite-api/client.rb
@@ -66,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
72
  version: '0'
67
73
  requirements: []
68
74
  rubyforge_project: graphite-api
69
- rubygems_version: 1.8.17
75
+ rubygems_version: 1.8.24
70
76
  signing_key:
71
77
  specification_version: 3
72
78
  summary: Graphite Ruby Client