simple-graphite 1.1.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.rdoc +10 -4
- data/lib/graphite/socket.rb +44 -0
- data/lib/simple-graphite.rb +22 -6
- data/spec/simple-graphite_spec.rb +155 -0
- data/spec/spec_helper.rb +52 -0
- metadata +60 -51
- data/test/simple-graphite_test.rb +0 -7
- data/test/test_helper.rb +0 -10
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dd5755e6f33393cf4462556dae8ec9f73eddac24
|
4
|
+
data.tar.gz: 6a1c7f28c36e69386d19bfdd877259bc6067e2e4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6771d947538cd1f4fe0a933dee1e9ceae3c0fbfcb3a4a9b0cc0938f0883606199e2c2b118282113042696564705489b140d1b345295414be816bfa6c5c653254
|
7
|
+
data.tar.gz: 4371d070f53c70e13267ead0f77c14584cee8bef111ee71720d1d0bbf64382e693612bfda1775d616545f92aa26953d2d8cc29030558563d9222343b24a4dda3
|
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= simple-graphite
|
2
2
|
|
3
|
-
A simple interface
|
3
|
+
A simple interface to {Graphite}[http://graphite.wikidot.com].
|
4
4
|
|
5
5
|
= How-to
|
6
6
|
|
@@ -12,10 +12,16 @@ or
|
|
12
12
|
g.port = 2003
|
13
13
|
|
14
14
|
To push data to Graphite:
|
15
|
-
g.push_to_graphite do |
|
16
|
-
|
15
|
+
g.push_to_graphite do |graphite|
|
16
|
+
graphite.puts "your.metric.name 3.1415926 #{g.time_now}"
|
17
17
|
end
|
18
18
|
|
19
|
+
Or:
|
20
|
+
g.send_metrics({
|
21
|
+
'foo.bar1' => 250,
|
22
|
+
'foo.bar2' => 114
|
23
|
+
})
|
24
|
+
|
19
25
|
== Note on Patches/Pull Requests
|
20
26
|
|
21
27
|
* Fork the project.
|
@@ -24,7 +30,7 @@ To push data to Graphite:
|
|
24
30
|
future version unintentionally.
|
25
31
|
* Commit, do not mess with rakefile, version, or history.
|
26
32
|
(if you want to have your own version, that is fine but
|
27
|
-
|
33
|
+
bump version in a commit by itself I can ignore when I pull)
|
28
34
|
* Send me a pull request. Bonus points for topic branches.
|
29
35
|
|
30
36
|
== Copyright
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
class Graphite
|
4
|
+
class Socket
|
5
|
+
attr_accessor :host, :port, :type, :socket
|
6
|
+
|
7
|
+
def initialize(host, port, socket_type)
|
8
|
+
@host = host
|
9
|
+
@port = port
|
10
|
+
@type = socket_type
|
11
|
+
@socket = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def puts(event)
|
15
|
+
socket.write(terminated_event(event.to_s))
|
16
|
+
close if @type == :udp
|
17
|
+
end
|
18
|
+
|
19
|
+
def close
|
20
|
+
@socket.close if @socket and !@socket.closed?
|
21
|
+
rescue => e
|
22
|
+
warn "#{self.class} - #{e.class} - #{e.message}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def socket
|
26
|
+
return @socket if @socket && !@socket.closed?
|
27
|
+
@socket = case @type
|
28
|
+
when :udp then UDPSocket.new.tap {|s| s.connect(@host, @port)}
|
29
|
+
when :tcp then TCPSocket.new(@host, @port)
|
30
|
+
else
|
31
|
+
raise NameError, "#{@type} is invalid; must be udp or tcp"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def terminated_event(event)
|
36
|
+
event =~ /\n$/ ? event : event + "\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Retained for compatibility
|
40
|
+
def connect
|
41
|
+
socket
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/simple-graphite.rb
CHANGED
@@ -1,21 +1,37 @@
|
|
1
1
|
require 'socket'
|
2
|
+
require 'graphite/socket'
|
2
3
|
|
3
4
|
class Graphite
|
4
|
-
|
5
|
+
|
6
|
+
attr_accessor :host, :type, :port, :time
|
7
|
+
|
5
8
|
def initialize(options = {})
|
6
9
|
@host = options[:host]
|
7
|
-
@
|
10
|
+
@type = options[:type] ||= :tcp
|
11
|
+
@port = options[:port] ||= @type.eql?(:tcp) ? 2003 : 8125
|
8
12
|
@time = Time.now.to_i
|
9
13
|
end
|
10
14
|
|
11
15
|
def push_to_graphite
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
raise "You need to provide a hostname" if @host.nil?
|
17
|
+
begin
|
18
|
+
socket = Graphite::Socket.new @host, @port, @type
|
19
|
+
yield socket
|
20
|
+
ensure
|
21
|
+
socket.close
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def send_metrics(metrics_hash)
|
26
|
+
current_time = time_now
|
27
|
+
push_to_graphite do |graphite|
|
28
|
+
graphite.puts((metrics_hash.map { |k,v| [k, v, current_time].join(' ') + "\n" }).join(''))
|
29
|
+
end
|
30
|
+
current_time
|
15
31
|
end
|
16
32
|
|
17
33
|
def hostname
|
18
|
-
Socket.gethostname
|
34
|
+
::Socket.gethostname
|
19
35
|
end
|
20
36
|
|
21
37
|
def self.time_now
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'socket'
|
3
|
+
require 'simple-graphite'
|
4
|
+
|
5
|
+
describe Graphite do
|
6
|
+
|
7
|
+
it "uses TCP by default" do
|
8
|
+
a = Graphite.new
|
9
|
+
a.port.should == 2003 && a.type.should == :tcp
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has a default TCP port" do
|
13
|
+
a = Graphite.new
|
14
|
+
a.port.should == 2003
|
15
|
+
end
|
16
|
+
|
17
|
+
it "has a default UDP port" do
|
18
|
+
a = Graphite.new :type => :udp
|
19
|
+
a.port.should == 8125
|
20
|
+
end
|
21
|
+
|
22
|
+
it "only accepts UDP or TCP as protocols" do
|
23
|
+
a = Graphite.new :host => 'localhost', :type => :fake
|
24
|
+
expect {a.push_to_graphite{|g| g.puts "hello world"}}.to raise_error(NameError, "fake is invalid; must be udp or tcp")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "requires a hostname" do
|
28
|
+
a = Graphite.new
|
29
|
+
expect {a.push_to_graphite}.to raise_error(RuntimeError, "You need to provide a hostname")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns time accurately" do
|
33
|
+
a = Graphite.new
|
34
|
+
a.time_now.should == Time.now.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "over TCP" do
|
38
|
+
before do
|
39
|
+
@ftcp = FakeTCPSocket.new
|
40
|
+
end
|
41
|
+
|
42
|
+
after do
|
43
|
+
@ftcp.close
|
44
|
+
end
|
45
|
+
|
46
|
+
it "sends individual metrics to graphite" do
|
47
|
+
a = Graphite.new(:host => 'localhost', :type => :tcp, :port => 12003)
|
48
|
+
a.push_to_graphite do |graphite|
|
49
|
+
graphite.puts "hello world\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
@ftcp.buffer.should == "hello world\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "terminates individual metrics with newlines" do
|
56
|
+
a = Graphite.new(:host => 'localhost', :type => :tcp, :port => 12003)
|
57
|
+
a.push_to_graphite do |graphite|
|
58
|
+
graphite.puts "hello world"
|
59
|
+
end
|
60
|
+
|
61
|
+
@ftcp.buffer.should == "hello world\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "sends multiple metrics to graphite" do
|
65
|
+
a = Graphite.new(:host => 'localhost', :type => :tcp, :port => 12003)
|
66
|
+
a.push_to_graphite do |graphite|
|
67
|
+
graphite.puts "hello\n"
|
68
|
+
graphite.puts "world\n"
|
69
|
+
end
|
70
|
+
|
71
|
+
@ftcp.buffer.should == "hello\nworld\n"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "terminates multiple metrics with newlines" do
|
75
|
+
a = Graphite.new(:host => 'localhost', :type => :tcp, :port => 12003)
|
76
|
+
a.push_to_graphite do |graphite|
|
77
|
+
graphite.puts "hello"
|
78
|
+
graphite.puts "world"
|
79
|
+
end
|
80
|
+
|
81
|
+
@ftcp.buffer.should == "hello\nworld\n"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "sends a hash of metrics to graphite" do
|
85
|
+
a = Graphite.new(:host => 'localhost', :type => :tcp, :port => 12003)
|
86
|
+
|
87
|
+
time = a.send_metrics({
|
88
|
+
'foo.bar' => 200,
|
89
|
+
'foo.test' => 10.2
|
90
|
+
})
|
91
|
+
|
92
|
+
@ftcp.buffer.should == "foo.bar 200 #{time}\nfoo.test 10.2 #{time}\n"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "over UDP" do
|
97
|
+
before do
|
98
|
+
@fudp = FakeUDPSocket.new
|
99
|
+
end
|
100
|
+
|
101
|
+
after do
|
102
|
+
@fudp.close
|
103
|
+
end
|
104
|
+
|
105
|
+
it "sends individual metrics to graphite" do
|
106
|
+
a = Graphite.new(:host => 'localhost', :type => :udp, :port => 18125)
|
107
|
+
a.push_to_graphite do |graphite|
|
108
|
+
graphite.puts "hello world\n"
|
109
|
+
end
|
110
|
+
|
111
|
+
@fudp.buffer.should == "hello world\n"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "terminates individual metrics with newlines" do
|
115
|
+
a = Graphite.new(:host => 'localhost', :type => :udp, :port => 18125)
|
116
|
+
a.push_to_graphite do |graphite|
|
117
|
+
graphite.puts "hello world"
|
118
|
+
end
|
119
|
+
|
120
|
+
@fudp.buffer.should == "hello world\n"
|
121
|
+
end
|
122
|
+
|
123
|
+
it "sends multiple metrics to graphite" do
|
124
|
+
a = Graphite.new(:host => 'localhost', :type => :udp, :port => 18125)
|
125
|
+
a.push_to_graphite do |graphite|
|
126
|
+
graphite.puts "hello\n"
|
127
|
+
graphite.puts "world\n"
|
128
|
+
end
|
129
|
+
|
130
|
+
@fudp.buffer.should == "hello\nworld\n"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "terminates multiple metrics with newlines" do
|
134
|
+
a = Graphite.new(:host => 'localhost', :type => :udp, :port => 18125)
|
135
|
+
a.push_to_graphite do |graphite|
|
136
|
+
graphite.puts "hello"
|
137
|
+
graphite.puts "world"
|
138
|
+
end
|
139
|
+
|
140
|
+
@fudp.buffer.should == "hello\nworld\n"
|
141
|
+
end
|
142
|
+
|
143
|
+
it "sends a hash of metrics to graphite" do
|
144
|
+
a = Graphite.new(:host => 'localhost', :type => :udp, :port => 18125)
|
145
|
+
|
146
|
+
time = a.send_metrics({
|
147
|
+
'foo.bar' => 200,
|
148
|
+
'foo.test' => 10.2
|
149
|
+
})
|
150
|
+
|
151
|
+
@fudp.buffer.should == "foo.bar 200 #{time}\nfoo.test 10.2 #{time}\n"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
if ENV["COVERAGE"]
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'socket'
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
10
|
+
config.run_all_when_everything_filtered = true
|
11
|
+
config.filter_run :focus
|
12
|
+
config.color_enabled = true
|
13
|
+
config.tty = true
|
14
|
+
config.formatter = :documentation # :progress, :html, :textmate
|
15
|
+
end
|
16
|
+
|
17
|
+
class FakeTCPSocket
|
18
|
+
def initialize
|
19
|
+
@sock = TCPServer.new(12003)
|
20
|
+
end
|
21
|
+
|
22
|
+
def buffer
|
23
|
+
buf = @sock.accept
|
24
|
+
buf.read_nonblock(65535)
|
25
|
+
end
|
26
|
+
|
27
|
+
def close
|
28
|
+
@sock.close
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class FakeUDPSocket
|
33
|
+
def initialize
|
34
|
+
@sock = UDPSocket.new
|
35
|
+
@sock.bind(nil, 18125)
|
36
|
+
end
|
37
|
+
|
38
|
+
def buffer
|
39
|
+
buf = Array.new
|
40
|
+
begin
|
41
|
+
while pkt = @sock.recvfrom_nonblock(65535)
|
42
|
+
buf << pkt
|
43
|
+
end
|
44
|
+
rescue IO::WaitReadable
|
45
|
+
end
|
46
|
+
buf.map{|p| p.first}.join()
|
47
|
+
end
|
48
|
+
|
49
|
+
def close
|
50
|
+
@sock.close
|
51
|
+
end
|
52
|
+
end
|
metadata
CHANGED
@@ -1,73 +1,82 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple-graphite
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease: false
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 1
|
9
|
-
- 1
|
10
|
-
version: 1.1.1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.1.0
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Ian Meyer
|
14
8
|
autorequire:
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
date: 2013-05-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec-mocks
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Simple methods for sending data to graphite over TCP or UDP
|
23
42
|
email: ianmmeyer@gmail.com
|
24
43
|
executables: []
|
25
|
-
|
26
44
|
extensions: []
|
27
|
-
|
28
|
-
extra_rdoc_files:
|
45
|
+
extra_rdoc_files:
|
29
46
|
- LICENSE
|
30
47
|
- README.rdoc
|
31
|
-
files:
|
48
|
+
files:
|
49
|
+
- lib/graphite/socket.rb
|
32
50
|
- lib/simple-graphite.rb
|
33
|
-
-
|
34
|
-
-
|
51
|
+
- spec/simple-graphite_spec.rb
|
52
|
+
- spec/spec_helper.rb
|
35
53
|
- LICENSE
|
36
54
|
- README.rdoc
|
37
|
-
has_rdoc: true
|
38
55
|
homepage: http://github.com/imeyer/simple-graphite
|
39
|
-
licenses:
|
40
|
-
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata: {}
|
41
59
|
post_install_message:
|
42
|
-
rdoc_options:
|
60
|
+
rdoc_options:
|
43
61
|
- --charset=UTF-8
|
44
|
-
require_paths:
|
62
|
+
require_paths:
|
45
63
|
- lib
|
46
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
none: false
|
57
|
-
requirements:
|
58
|
-
- - ">="
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
hash: 3
|
61
|
-
segments:
|
62
|
-
- 0
|
63
|
-
version: "0"
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
64
74
|
requirements: []
|
65
|
-
|
66
75
|
rubyforge_project:
|
67
|
-
rubygems_version:
|
76
|
+
rubygems_version: 2.0.3
|
68
77
|
signing_key:
|
69
|
-
specification_version:
|
78
|
+
specification_version: 4
|
70
79
|
summary: Simple hook into graphite
|
71
|
-
test_files:
|
72
|
-
-
|
73
|
-
-
|
80
|
+
test_files:
|
81
|
+
- spec/simple-graphite_spec.rb
|
82
|
+
- spec/spec_helper.rb
|
data/test/test_helper.rb
DELETED