statsd-rb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011 Matt Duncan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ statsd-rb
2
+ =========
3
+ A ruby client for [StatsD](https://github.com/etsy/statsd).
4
+
5
+ Usage
6
+ -----
7
+ Connecting to a StatsD instance:
8
+
9
+ require "statsd"
10
+ client = StatsD::Client.new
11
+
12
+ By default, clients will connect to `localhost:8125`. If you need to
13
+ connect to a remote server or a different port, use the `:hostname` and
14
+ `:port` options.
15
+
16
+ client = StatsD::Client.new(:hostname => "statsd", :port => 5000)
17
+
18
+ ### Commands
19
+ Once you have a client, sending statistics is easy.
20
+
21
+ Increment the downloads count:
22
+
23
+ client.incr :downloads
24
+
25
+ Increment the downloads count, telling StatsD that the counter is being
26
+ sampled every 10th time. All commands take an optional last argument
27
+ `sample_rate`.
28
+
29
+ client.incr :downloads, 0.1
30
+
31
+ Decrement the invites count by two:
32
+
33
+ client.decrby :invites, 2
34
+
35
+ Time the archive job:
36
+
37
+ client.time :archive do
38
+ # something
39
+ end
40
+
41
+ Send an already calculated timing:
42
+
43
+ client.timing :archive, 300 # milliseconds
44
+
45
+ TODO
46
+ ----
47
+
48
+ - Bulk updating
49
+
50
+ Author
51
+ ------
52
+ Matt Duncan | [mattduncan.org](http://mattduncan.org) | [matt@mattduncan.org](mailto:matt@mattduncan.org)
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ task :default => :spec
5
+
6
+ desc "Run all examples"
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.rspec_opts = %w[--color]
9
+ end
data/lib/statsd.rb ADDED
@@ -0,0 +1 @@
1
+ require 'statsd/client'
@@ -0,0 +1,48 @@
1
+ require 'benchmark'
2
+ require 'socket'
3
+
4
+ module StatsD
5
+ class Client
6
+ attr_reader :hostname, :port
7
+
8
+ def initialize(options = {})
9
+ @hostname = options[:hostname] || "localhost"
10
+ @port = (options[:port] || 8125).to_i
11
+ end
12
+
13
+ def time(key, sample_rate = 1, &block)
14
+ seconds = Benchmark.realtime { block.call }
15
+ timing(key, (seconds * 1000).round, sample_rate)
16
+ end
17
+
18
+ def timing(key, ms, sample_rate = 1)
19
+ send_data({ key => "#{ms}|ms" }, sample_rate)
20
+ end
21
+
22
+ def incr(key, sample_rate = 1)
23
+ incrby(key, 1, sample_rate)
24
+ end
25
+
26
+ def incrby(key, increment, sample_rate = 1)
27
+ send_data({ key => "#{increment}|c" }, sample_rate)
28
+ end
29
+
30
+ def decr(key, sample_rate = 1)
31
+ decrby(key, 1, sample_rate)
32
+ end
33
+
34
+ def decrby(key, decrement, sample_rate = 1)
35
+ incrby(key, -decrement, sample_rate)
36
+ end
37
+
38
+ def send_data(data, sample_rate = 1)
39
+ socket = UDPSocket.new
40
+ socket.bind("127.0.0.1", 0)
41
+ socket.connect(@hostname, @port)
42
+ data.each do |key, val|
43
+ val += "|@#{sample_rate}" if sample_rate != 1
44
+ socket.send "#{key}:#{val}", 0
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,3 @@
1
+ module StatsD
2
+ Version = VERSION = '0.1.0'
3
+ end
@@ -0,0 +1 @@
1
+ require 'statsd'
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+
3
+ describe StatsD::Client do
4
+ describe "initialize" do
5
+ it "defaults to localhost:8125" do
6
+ client = described_class.new
7
+ client.hostname.should == "localhost"
8
+ client.port.should == 8125
9
+ end
10
+
11
+ it "initializes hostname and port" do
12
+ client = described_class.new(:hostname => "statsd.local", :port => 6000)
13
+ client.hostname.should == "statsd.local"
14
+ client.port.should == 6000
15
+ end
16
+
17
+ it "allows port to be specified as a string" do
18
+ client = described_class.new(:port => "6000")
19
+ client.port.should == 6000
20
+ end
21
+ end
22
+
23
+ describe "send_data" do
24
+ describe "sending over socket" do
25
+ RSpec::Matchers.define :send_data do |expected|
26
+ match do |actual|
27
+ socket = UDPSocket.new
28
+ socket.bind("127.0.0.1", 9730)
29
+ actual.call
30
+ IO.select([socket])
31
+ req = socket.recvfrom_nonblock(100)
32
+ socket.close
33
+ req[0] == expected
34
+ end
35
+ end
36
+
37
+ it "sends single key and value" do
38
+ client = described_class.new(:port => 9730)
39
+ expect { client.send_data :hits => "1|c" }.to send_data "hits:1|c"
40
+ end
41
+ end
42
+
43
+ describe "socket connection" do
44
+ before :each do
45
+ @socket = double('socket')
46
+ [:bind, :connect].each { |m| @socket.stub m }
47
+ UDPSocket.stub(:new) { @socket }
48
+ @client = described_class.new(
49
+ :hostname => "statsd.local",
50
+ :port => 6000
51
+ )
52
+ end
53
+
54
+ it "binds to 127.0.0.1" do
55
+ @socket.should_receive(:bind).with("127.0.0.1", 0)
56
+ @client.send_data({})
57
+ end
58
+
59
+ it "connects to the client hostname and port" do
60
+ @socket.should_receive(:connect).with(
61
+ @client.hostname,
62
+ @client.port
63
+ )
64
+ @client.send_data({})
65
+ end
66
+
67
+ it "sends a single key and value" do
68
+ @socket.should_receive(:send).with("hits:1|c", 0)
69
+ @client.send_data :hits => "1|c"
70
+ end
71
+
72
+ it "sends multiple keys and values" do
73
+ @socket.should_receive(:send).with("hits:1|c", 0)
74
+ @socket.should_receive(:send).with("downloads:1|c", 0)
75
+ @client.send_data :hits => "1|c", :downloads => "1|c"
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "commands" do
81
+ before :each do
82
+ @client = described_class.new
83
+ end
84
+
85
+ describe "incr" do
86
+ it "sends the increment" do
87
+ @client.should_receive(:send_data).with({ :hits => "1|c" }, 1)
88
+ @client.incr :hits
89
+ end
90
+ end
91
+
92
+ describe "incrby" do
93
+ it "sends the specified increment value" do
94
+ @client.should_receive(:send_data).with({ :hits => "3|c" }, 1)
95
+ @client.incrby :hits, 3
96
+ end
97
+ end
98
+
99
+ describe "decr" do
100
+ it "sends the decrement" do
101
+ @client.should_receive(:send_data).with({ :invites => "-1|c" }, 1)
102
+ @client.decr :invites
103
+ end
104
+ end
105
+
106
+ describe "decrby" do
107
+ it "sends the specified decrement value" do
108
+ @client.should_receive(:send_data).with({ :tickets => "-4|c" }, 1)
109
+ @client.decrby :tickets, 4
110
+ end
111
+ end
112
+
113
+ describe "timing" do
114
+ it "sends the timing" do
115
+ @client.should_receive(:send_data).with({ :archive => "230|ms" }, 1)
116
+ @client.timing :archive, 230
117
+ end
118
+ end
119
+
120
+ describe "time" do
121
+ it "sends the time" do
122
+ @client.should_receive(:send_data).with({ :archive => "10|ms" }, 1)
123
+ @client.time(:archive) { sleep 0.01 }
124
+ end
125
+ end
126
+ end
127
+
128
+ describe "sampling" do
129
+ before :each do
130
+ @client = described_class.new
131
+ end
132
+
133
+ describe "incr" do
134
+ it "sends the sampleed increment" do
135
+ @client.should_receive(:send_data).with({ :hits => "1|c" }, 0.2)
136
+ @client.incr :hits, 0.2
137
+ end
138
+ end
139
+
140
+ describe "incrby" do
141
+ it "sends the sampled increment" do
142
+ @client.should_receive(:send_data).with({ :hits => "3|c" }, 0.2)
143
+ @client.incrby :hits, 3, 0.2
144
+ end
145
+ end
146
+
147
+ describe "decr" do
148
+ it "sends the sampled decrement" do
149
+ @client.should_receive(:send_data).with({ :invites => "-1|c" }, 0.5)
150
+ @client.decr :invites, 0.5
151
+ end
152
+ end
153
+
154
+ describe "decrby" do
155
+ it "sends the sampled decrement" do
156
+ @client.should_receive(:send_data).with({ :tickets => "-4|c" }, 0.5)
157
+ @client.decrby :tickets, 4, 0.5
158
+ end
159
+ end
160
+
161
+ describe "timing" do
162
+ it "sends the sampled timing" do
163
+ @client.should_receive(:send_data).with({ :archive => "230|ms" }, 0.1)
164
+ @client.timing :archive, 230, 0.1
165
+ end
166
+ end
167
+
168
+ describe "time" do
169
+ it "sends the sampled time" do
170
+ @client.should_receive(:send_data).with({ :archive => "10|ms" }, 0.1)
171
+ @client.time(:archive, 0.1) { sleep 0.01 }
172
+ end
173
+ end
174
+ end
175
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: statsd-rb
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Matt Duncan
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-21 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: " A ruby client for Etsy's StatsD statistics aggregator.\n"
23
+ email: matt@mattduncan.org
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - README.md
32
+ - Rakefile
33
+ - LICENSE
34
+ - lib/statsd/client.rb
35
+ - lib/statsd/version.rb
36
+ - lib/statsd.rb
37
+ - spec/spec_helper.rb
38
+ - spec/statsd/client_spec.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/mrduncan/statsd
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ hash: 3
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.6.2
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: A ruby client for StatsD.
73
+ test_files: []
74
+