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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  = simple-graphite
2
2
 
3
- A simple interface into [Graphite](http://graphite.wikidot.com).
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 |socket|
16
- socket.puts "your.metric.name 3.1415926 #{g.time_now}"
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
- bump version in a commit by itself I can ignore when I pull)
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
@@ -1,21 +1,37 @@
1
1
  require 'socket'
2
+ require 'graphite/socket'
2
3
 
3
4
  class Graphite
4
- attr_accessor :host, :port, :time
5
+
6
+ attr_accessor :host, :type, :port, :time
7
+
5
8
  def initialize(options = {})
6
9
  @host = options[:host]
7
- @port = options[:port]
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
- socket = TCPSocket.new(@host, @port)
13
- yield socket
14
- socket.close
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
@@ -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
- hash: 17
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
- date: 2010-06-21 00:00:00 +00:00
19
- default_executable:
20
- dependencies: []
21
-
22
- description: Exposes methods to send data to graphite
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
- - test/simple-graphite_test.rb
34
- - test/test_helper.rb
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
- none: false
48
- requirements:
49
- - - ">="
50
- - !ruby/object:Gem::Version
51
- hash: 3
52
- segments:
53
- - 0
54
- version: "0"
55
- required_rubygems_version: !ruby/object:Gem::Requirement
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: 1.3.7
76
+ rubygems_version: 2.0.3
68
77
  signing_key:
69
- specification_version: 3
78
+ specification_version: 4
70
79
  summary: Simple hook into graphite
71
- test_files:
72
- - test/test_helper.rb
73
- - test/simple-graphite_test.rb
80
+ test_files:
81
+ - spec/simple-graphite_spec.rb
82
+ - spec/spec_helper.rb
@@ -1,7 +0,0 @@
1
- require 'test_helper'
2
-
3
- class EtsyGraphiteTest < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
6
- end
7
- end
@@ -1,10 +0,0 @@
1
- require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
4
-
5
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
- $LOAD_PATH.unshift(File.dirname(__FILE__))
7
- require 'simple-graphite'
8
-
9
- class Test::Unit::TestCase
10
- end