graphite-api 0.0.2.0 → 0.0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # GraphiteAPI [Beta]
1
+ # GraphiteAPI ( [![Gem Version](https://fury-badge.herokuapp.com/rb/graphite-api.png)](http://badge.fury.io/rb/graphite-api) )
2
2
  A Ruby API toolkit for [Graphite](http://graphite.wikidot.com/).
3
3
 
4
4
  ## Description
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).
5
+ **GraphiteAPI** 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
7
  ## Package Content
8
8
  * Includes a **simple** client for ruby.
@@ -129,11 +129,11 @@ example.middleware.value2 99 1334929231
129
129
  [root@graphite-middleware-node]
130
130
  ```
131
131
 
132
- * Send metrics via **GraphtieAPI client**
132
+ * Or via **GraphtieAPI client**
133
133
 
134
134
  ```ruby
135
135
  require 'graphite-api'
136
- client = GraphiteAPI::Client.new(:graphite => graphite-middleware-node)
136
+ client = GraphiteAPI::Client.new(:graphite => 'graphite-middleware-node:2005')
137
137
  client.example.middleware.value 10.2
138
138
  client.example.middleware.value2 27
139
139
  client.bla.bla.value2 27
@@ -16,25 +16,28 @@
16
16
  # ["mem.usage", 190.0, 1326842520]
17
17
  # ["shuki.tuki", 999.0, 1326842520]
18
18
  # -----------------------------------------------------
19
+ require 'set'
20
+
19
21
  module GraphiteAPI
20
22
  class Buffer
21
- include Utils
22
-
23
- attr_reader :options,:keys_to_send,:reanimation_mode, :streamer_buff
23
+ include Utils
24
+
25
+ CLOSING_STREAM = "\n" # end of message - when streaming to buffer obj
26
+ CHARS_TO_IGNORE = %w(\r) # skip these chars when parsing new message
27
+ FLOATS_ROUND_BY = 2 # round(x) after summing floats
24
28
 
25
- CLOSING_STREAM_CHAR = "\n" # end of message - when streaming to buffer obj
26
- CHARS_TO_IGNORE = ["\r"] # skip these chars when parsing new message
27
- FLOATS_ROUND_BY = 2 # round(x) after summing floats
28
- VALID_MESSAGE = /^[\w|\.]+ \d+(?:\.|\d)* \d+$/ # how a valid message should look like
29
+ VALID_MESSAGE = /^[\w|\.]+ \d+(?:\.|\d)* \d+$/
29
30
 
30
31
  def initialize options
31
32
  @options = options
32
- @keys_to_send = Hash.new {|h,k| h[k] = []}
33
+ @keys_to_sync = Hash.new { |h,k| h[k] = Set.new }
33
34
  @streamer_buff = Hash.new {|h,k| h[k] = ""}
34
35
  @reanimation_mode = !options[:reanimation_exp].nil?
35
36
  start_cleaner if reanimation_mode
36
37
  end
37
38
 
39
+ private_reader :options, :keys_to_sync, :reanimation_mode, :streamer_buff
40
+
38
41
  def push hash
39
42
  debug [:buffer,:add, hash]
40
43
  time = Utils.normalize_time(hash[:time],options[:slice])
@@ -44,7 +47,7 @@ module GraphiteAPI
44
47
  alias_method :<<, :push
45
48
 
46
49
  def stream message, client_id = nil
47
- message.each_char do |char|
50
+ message.gsub(/\t/,' ').each_char do |char|
48
51
  next if invalid_char? char
49
52
  streamer_buff[client_id] += char
50
53
 
@@ -59,7 +62,7 @@ module GraphiteAPI
59
62
 
60
63
  def pull as = nil
61
64
  Array.new.tap do |data|
62
- keys_to_send.each do |time,keys|
65
+ keys_to_sync.each do |time,keys|
63
66
  keys.each do |key|
64
67
  data.push cache_get(time, key, as)
65
68
  end
@@ -70,13 +73,13 @@ module GraphiteAPI
70
73
  end
71
74
 
72
75
  def new_records?
73
- !keys_to_send.empty?
76
+ !keys_to_sync.empty?
74
77
  end
75
78
 
76
79
  private
77
80
 
78
81
  def closed_stream? string
79
- string[-1,1] == CLOSING_STREAM_CHAR
82
+ string[-1,1] == CLOSING_STREAM
80
83
  end
81
84
 
82
85
  def invalid_char? char
@@ -85,24 +88,24 @@ module GraphiteAPI
85
88
 
86
89
  def cache_set time, key, value
87
90
  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
91
+ keys_to_sync[time].add key
89
92
  end
90
93
 
91
94
  def sum float1, float2
92
- ("%.#{FLOATS_ROUND_BY}f" % (float1 + float2)).to_f # can't use round on 1.8.X
95
+ ("%.#{FLOATS_ROUND_BY}f" % (float1 + float2)).to_f
93
96
  end
94
97
 
95
98
  def cache_get time, key, as
96
99
  metric = [prefix + key,buffer_cache[time][key],time]
97
100
  as == :string ? metric.join(" ") : metric
98
101
  end
99
-
102
+
100
103
  def build_metric key, value, time
101
104
  { :metric => { key => value },:time => Time.at(time.to_i) }
102
105
  end
103
106
 
104
107
  def clear
105
- keys_to_send.clear
108
+ keys_to_sync.clear
106
109
  buffer_cache.clear unless reanimation_mode
107
110
  end
108
111
 
@@ -123,7 +126,7 @@ module GraphiteAPI
123
126
  end
124
127
 
125
128
  def clean age
126
- [buffer_cache,keys_to_send].each {|o| o.delete_if {|t,k| Time.now.to_i - t > age}}
129
+ [buffer_cache,keys_to_sync].each {|o| o.delete_if {|t,k| Time.now.to_i - t > age}}
127
130
  end
128
131
 
129
132
  def start_cleaner
@@ -46,9 +46,7 @@ require File.expand_path '../utils', __FILE__
46
46
  module GraphiteAPI
47
47
  class Client
48
48
  include Utils
49
-
50
- extend Utils::ClassMethods
51
-
49
+
52
50
  def initialize opt
53
51
  @options = build_options validate opt.clone
54
52
  @buffer = GraphiteAPI::Buffer.new options
@@ -60,13 +58,13 @@ module GraphiteAPI
60
58
 
61
59
  end
62
60
 
63
- attr_private_reader :options, :buffer, :connectors
64
- delegate :loop, :stop, :to => :Reactor
61
+ private_reader :options, :buffer, :connectors
62
+
63
+ def_delegator :"GraphiteAPI::Reactor", :loop
64
+ def_delegator :"GraphiteAPI::Reactor", :stop
65
65
 
66
66
  def every interval, &block
67
- Reactor.every interval do
68
- block.call self
69
- end
67
+ Reactor.every( interval ) { block.call self }
70
68
  end
71
69
 
72
70
  def metrics metric, time = Time.now
@@ -84,24 +82,21 @@ module GraphiteAPI
84
82
  protected
85
83
 
86
84
  class Proxy
87
- extend Utils::ClassMethods
85
+ include Utils
88
86
 
89
87
  def initialize client
90
88
  @client = client
91
89
  @keys = []
92
90
  end
93
91
 
94
- attr_private_reader :client, :keys
92
+ private_reader :client, :keys
95
93
 
96
94
  def method_missing m, *args, &block
97
95
  keys.push m
98
96
  if keys.size > 10 # too deep
99
97
  super
100
- elsif !args.empty?
101
- client.metrics(
102
- Hash[keys.join("."),args.first],
103
- *args[1..-1]
104
- )
98
+ elsif args.any?
99
+ client.metrics(Hash[keys.join("."),args.first],*args[1..-1])
105
100
  else
106
101
  self
107
102
  end
@@ -12,14 +12,15 @@ require 'socket'
12
12
 
13
13
  module GraphiteAPI
14
14
  class Connector
15
-
16
- attr_reader :options, :host, :port
15
+ include Utils
17
16
 
18
17
  def initialize host, port
19
18
  @host = host
20
19
  @port = port
21
20
  end
22
21
 
22
+ private_reader :host, :port
23
+
23
24
  def puts message
24
25
  begin
25
26
  Logger.debug [:connector,:puts,[host,port].join(":"),message]
@@ -2,7 +2,7 @@ module GraphiteAPI
2
2
  class ConnectorGroup
3
3
  include Utils
4
4
 
5
- attr_reader :options, :connectors
5
+ private_reader :options, :connectors
6
6
 
7
7
  def initialize options
8
8
  @options = options
@@ -22,12 +22,12 @@ module GraphiteAPI
22
22
  # :std => out|err|file-name
23
23
  def init(options)
24
24
  self.logger = ::Logger.new(options[:std] || STDOUT)
25
- self.logger.level= eval "::Logger::#{options[:level].to_s.upcase}"
25
+ self.logger.level= ::Logger.const_get "#{options[:level].to_s.upcase}"
26
26
  end
27
27
 
28
28
  def method_missing(m,*args,&block)
29
- if logger.respond_to? m then logger.send(m,*args,&block) end
30
- end
29
+ logger.send m, *args, &block if logger.respond_to? m
30
+ end
31
31
  end
32
32
  end
33
- end
33
+ end
@@ -17,7 +17,6 @@
17
17
  # log_level info
18
18
  # -----------------------------------------------------
19
19
 
20
- require 'rubygems'
21
20
  require 'eventmachine'
22
21
  require 'socket'
23
22
  require File.expand_path '../utils', __FILE__
@@ -26,13 +25,12 @@ module GraphiteAPI
26
25
  class Middleware < EventMachine::Connection
27
26
 
28
27
  include Utils
29
- extend Utils::ClassMethods
30
28
 
31
29
  def initialize buffer
32
30
  @buffer = buffer and super
33
31
  end
34
32
 
35
- attr_private_reader :buffer,:client_id
33
+ private_reader :buffer, :client_id
36
34
 
37
35
  def post_init
38
36
  @client_id = peername
@@ -72,8 +70,8 @@ module GraphiteAPI
72
70
  GraphiteAPI::Reactor.every options[:interval], &block
73
71
  GraphiteAPI::Reactor.add_shutdown_hook &block
74
72
  end
75
- end
76
-
77
- end # start
73
+ end
74
+ end
75
+
78
76
  end # Middleware
79
77
  end # GraphiteAPI
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'eventmachine'
3
2
 
4
3
  module GraphiteAPI
@@ -16,6 +16,21 @@ module GraphiteAPI
16
16
 
17
17
  private
18
18
 
19
+ def daemonize pid
20
+ block_given? or raise ArgumentError.new "the block is missing..."
21
+
22
+ fork do
23
+ Process.setsid
24
+ exit if fork
25
+ Dir.chdir '/tmp'
26
+ STDIN.reopen('/dev/null')
27
+ STDOUT.reopen('/dev/null','a')
28
+ STDERR.reopen('/dev/null','a')
29
+ File.open(pid,'w') { |f| f.write(Process.pid) } rescue nil
30
+ yield
31
+ end
32
+ end
33
+
19
34
  def run!
20
35
  begin
21
36
  Middleware.start options
@@ -1,33 +1,29 @@
1
+ require 'forwardable'
2
+
1
3
  module GraphiteAPI
2
4
  module Utils
3
- module ClassMethods
4
- def attr_private_reader *args
5
- args.each { |o| attr_reader o or private o }
5
+
6
+ def self.included base
7
+ base.extend ClassUtils
8
+ base.extend Forwardable
9
+ base.__send__ :include, LoggerUtils
10
+ end
11
+
12
+ module LoggerUtils
13
+ [:info,:error,:warn,:debug].each do |m|
14
+ define_method m do |*args,&block|
15
+ Logger.send m, *args, &block
16
+ end
6
17
  end
18
+ end
7
19
 
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
24
-
25
- [:info,:error,:warn,:debug].each do |m|
26
- define_method(m) do |*args,&block|
27
- Logger.send(m,*args,&block)
20
+ module ClassUtils
21
+ def private_reader *args
22
+ attr_reader *args
23
+ private *args
28
24
  end
29
- end
30
-
25
+ end
26
+
31
27
  module_function
32
28
 
33
29
  def normalize_time time, slice = 60
@@ -54,21 +50,6 @@ module GraphiteAPI
54
50
  :pid => "/tmp/graphite-middleware.pid"
55
51
  }
56
52
  end
57
-
58
- def daemonize pid
59
- block_given? or raise ArgumentError.new "the block is missing..."
60
-
61
- fork do
62
- Process.setsid
63
- exit if fork
64
- Dir.chdir '/tmp'
65
- STDIN.reopen('/dev/null')
66
- STDOUT.reopen('/dev/null','a')
67
- STDERR.reopen('/dev/null','a')
68
- File.open(pid,'w') { |f| f.write(Process.pid) } rescue nil
69
- yield
70
- end
71
- end
72
53
 
73
54
  end
74
55
  end
@@ -1,5 +1,5 @@
1
1
  module GraphiteAPI
2
2
  class Version
3
- VERSION = "0.0.2.0"
3
+ VERSION = "0.0.2.1"
4
4
  end
5
5
  end
@@ -1,5 +1,7 @@
1
1
  require "rake/testtask"
2
2
 
3
+ task(:test) { ENV['with_coverage'] = "true" }
4
+
3
5
  Rake::TestTask.new(:test) do |t|
4
6
  t.libs << "tests"
5
7
  t.pattern = "tests/**/*_test.rb"
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.2.0
4
+ version: 0.0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-25 00:00:00.000000000 Z
12
+ date: 2013-02-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine