graphite-api 0.0.1.4 → 0.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/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