simple-graphite 1.1.1 → 2.1.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.
- 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