graphite-api 0.0.2.0 → 0.0.2.1
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 +4 -4
- data/lib/graphite-api/buffer.rb +20 -17
- data/lib/graphite-api/client.rb +10 -15
- data/lib/graphite-api/connector.rb +3 -2
- data/lib/graphite-api/connector_group.rb +1 -1
- data/lib/graphite-api/logger.rb +4 -4
- data/lib/graphite-api/middleware.rb +4 -6
- data/lib/graphite-api/reactor.rb +0 -1
- data/lib/graphite-api/runner.rb +15 -0
- data/lib/graphite-api/utils.rb +21 -40
- data/lib/graphite-api/version.rb +1 -1
- data/tasks/tests.rake +2 -0
- metadata +2 -2
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# GraphiteAPI [
|
1
|
+
# GraphiteAPI ( [](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**
|
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
|
-
*
|
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
|
data/lib/graphite-api/buffer.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
@
|
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
|
-
|
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
|
-
!
|
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] ==
|
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
|
-
|
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
|
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
|
-
|
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,
|
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
|
data/lib/graphite-api/client.rb
CHANGED
@@ -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
|
-
|
64
|
-
|
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
|
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
|
-
|
85
|
+
include Utils
|
88
86
|
|
89
87
|
def initialize client
|
90
88
|
@client = client
|
91
89
|
@keys = []
|
92
90
|
end
|
93
91
|
|
94
|
-
|
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
|
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]
|
data/lib/graphite-api/logger.rb
CHANGED
@@ -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=
|
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
|
-
|
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
|
-
|
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
|
-
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
78
76
|
end # Middleware
|
79
77
|
end # GraphiteAPI
|
data/lib/graphite-api/reactor.rb
CHANGED
data/lib/graphite-api/runner.rb
CHANGED
@@ -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
|
data/lib/graphite-api/utils.rb
CHANGED
@@ -1,33 +1,29 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
1
3
|
module GraphiteAPI
|
2
4
|
module Utils
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
data/lib/graphite-api/version.rb
CHANGED
data/tasks/tests.rake
CHANGED
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.
|
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:
|
12
|
+
date: 2013-02-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|