lookout-statsd 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c46d6d96b1086ab6165a4254009cfdd9e3dc7dfa
4
- data.tar.gz: a3d8a60d8abbc04a730e281edf58015d638eb587
3
+ metadata.gz: 09edd7854e30fe524a21a82dd325487e96c83a3b
4
+ data.tar.gz: f7d047db68333414a84ec0bbdce59f0fcde041b1
5
5
  SHA512:
6
- metadata.gz: aad201320598de48a5002b876d0738981784e7acb82216b37e30b1f796aa5886f535fa6935b0de71ba89d7ca3dae7014f125752e8ea90f73fc23ff1cea551e51
7
- data.tar.gz: 5050801e669c08aa9a12d2d6ac5da237eef48996f5af5edcb1b2799060dc40812a1f1f44d26cac613437cb16f81eddc790826af6186dc0ab4b5df4ba81be1f8d
6
+ metadata.gz: 53190cf6ac482c34bde75b18f727f1b74904a5ef1bb837c3299e487bea532d164114a9625c5185254379c6a97ef8fec794d83e3fab89e0a10d4068e87909f0bd
7
+ data.tar.gz: 36d9ce3ed7906da7d80226d9978a03873fe9502744eb234a3a73adbfe81af75ba159694c174566d5b75e3264014161ebbe13d08428dcf9aa1749a7441668bf5a
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ rvm:
3
+ - jruby
4
+ - 2.1
5
+ - 1.9.3
6
+ deploy:
7
+ provider: rubygems
8
+ api_key: 701b3f137a894afa3dca9390da8b3afe
9
+ gem: lookout-statsd
10
+ on:
11
+ repo: lookout/statsd
12
+ install:
13
+ - gem install bundler
14
+ - bundle install --jobs=3 --retry=3
data/README.md CHANGED
@@ -11,7 +11,7 @@ In your client code:
11
11
 
12
12
  require 'rubygems'
13
13
  require 'statsd'
14
- STATSD = Statsd::Client.new('localhost',8125)
14
+ STATSD = Statsd::Client.new(:host => 'localhost', :port => 8125)
15
15
 
16
16
  STATSD.increment('some_counter') # basic incrementing
17
17
  STATSD.increment('system.nested_counter', 0.1) # incrementing with sampling (10%)
@@ -22,6 +22,27 @@ In your client code:
22
22
  STATSD.timing('some_job_time', 20) # reporting job that took 20ms
23
23
  STATSD.timing('some_job_time', 20, 0.05) # reporting job that took 20ms with sampling (5% sampling)
24
24
 
25
+ There is an option for reduced DNS lookups, you can specify an additional
26
+ constructor option `:resolve_always` and set it to `false`. By default, the
27
+ client will always resolve the address unless `host` is set to 'localhost' or
28
+ '127.0.0.1'.
29
+
30
+ require 'rubygems'
31
+ require 'statsd'
32
+
33
+ STATSD = Statsd::Client.new(:host => 'specialstats.host.example',
34
+ :port => '8125',
35
+ :resolve_always => false)
36
+
37
+ STATSD.increment('some_counter') # basic incrementing
38
+
39
+ #### Note about thread-safety
40
+
41
+ Since class variables and instance variables are not thread-safe on
42
+ initialization, there is a potential for multiple UDP sockets being opened upon
43
+ if you are using a truly multithreaded ruby, i.e. JRuby. Make sure to take that
44
+ in to account when initializing this library.
45
+
25
46
  Guts
26
47
  ----
27
48
 
data/lib/statsd.rb CHANGED
@@ -15,12 +15,17 @@ module Statsd
15
15
  end
16
16
 
17
17
  class Client
18
- attr_accessor :host, :port, :prefix
18
+ attr_accessor :host, :port, :prefix, :resolve_always, :batch_size
19
19
 
20
20
  def initialize(opts={})
21
21
  @host = opts[:host] || 'localhost'
22
22
  @port = opts[:port] || 8125
23
+ @batch_size = opts[:batch_size] || 10
23
24
  @prefix = opts[:prefix]
25
+ # set resolve_always to true unless localhost or specified
26
+ @resolve_always = opts.fetch(:resolve_always, !is_localhost?)
27
+ @socket = UDPSocket.new
28
+ @send_data = send_method
24
29
  end
25
30
 
26
31
  def host_ip_addr
@@ -77,6 +82,22 @@ module Statsd
77
82
  })
78
83
  end
79
84
 
85
+ # Creates and yields a Batch that can be used to batch instrument reports into
86
+ # larger packets. Batches are sent either when the packet is "full" (defined
87
+ # by batch_size), or when the block completes, whichever is the sooner.
88
+ #
89
+ # Good artists copy https://github.com/reinh/statsd/blob/master/lib/statsd.rb#L410
90
+ #
91
+ # @yield [Batch] a statsd subclass that collects and batches instruments
92
+ # @example Batch two instument operations:
93
+ # $statsd.batch do |batch|
94
+ # batch.increment 'sys.requests'
95
+ # batch.gauge('user.count', User.count)
96
+ # end
97
+ def batch(&block)
98
+ Batch.new(self).easy(&block)
99
+ end
100
+
80
101
  private
81
102
 
82
103
  def send_stats(data, sample_rate = 1)
@@ -98,17 +119,105 @@ module Statsd
98
119
  raise "host and port must be set" unless host && port
99
120
 
100
121
  begin
101
- sock = UDPSocket.new
102
122
  data.each do |d|
103
- sock.send(d, 0, host, port)
123
+ @send_data[d]
104
124
  end
105
125
  rescue # silent but deadly
106
- ensure
107
- sock.close
108
126
  end
109
127
  true
110
128
  end
111
129
 
130
+ def socket_connect!
131
+ @socket.connect(@host, @port)
132
+ end
133
+
134
+ # Curries the send based on if we need to lookup dns every time we send
135
+ def send_method
136
+ if resolve_always
137
+ lambda {|data| @socket.send(data, 0, @host, @port)}
138
+ else
139
+ socket_connect!
140
+ lambda {|data| @socket.send(data, 0)}
141
+ end
142
+ end
143
+
144
+ def is_localhost?
145
+ @host == 'localhost' || @host == '127.0.0.1'
146
+ end
147
+ end
148
+
149
+ # Some more unabashed borrowing: https://github.com/reinh/statsd/blob/master/lib/statsd.rb#L410
150
+ # The big difference between this implementation and reinh's is that we don't support namespaces,
151
+ # and we have a bunch of hacks for introducing prefixes to the namespaces we're acting against.
152
+ # = Batch: A batching statsd proxy
153
+ #
154
+ # @example Batch a set of instruments using Batch and manual flush:
155
+ # $statsd = Statsd.new 'localhost', 8125
156
+ # batch = Statsd::Batch.new($statsd)
157
+ # batch.increment 'garets'
158
+ # batch.timing 'glork', 320
159
+ # batch.gauge 'bork', 100
160
+ # batch.flush
161
+ #
162
+ # Batch is a subclass of Statsd, but with a constructor that proxies to a
163
+ # normal Statsd instance. It has it's own batch_size parameters
164
+ # (that inherit defaults from the supplied Statsd instance). It is recommended
165
+ # that some care is taken if setting very large batch sizes. If the batch size
166
+ # exceeds the allowed packet size for UDP on your network, communication
167
+ # troubles may occur and data will be lost.
168
+ class Batch < Statsd::Client
169
+
170
+ extend Forwardable
171
+ def_delegators :@statsd,
172
+ :host, :host=,
173
+ :port, :port=,
174
+ :prefix,
175
+ :postfix,
176
+ :delimiter, :delimiter=
177
+
178
+ attr_accessor :batch_size
179
+
180
+ # @param [Statsd] requires a configured Statsd instance
181
+ def initialize(statsd)
182
+ @statsd = statsd
183
+ @batch_size = statsd.batch_size
184
+ @backlog = []
185
+ @send_data = send_method
186
+ end
187
+
188
+ # @yields [Batch] yields itself
189
+ #
190
+ # A convenience method to ensure that data is not lost in the event of an
191
+ # exception being thrown. Batches will be transmitted on the parent socket
192
+ # as soon as the batch is full, and when the block finishes.
193
+ def easy
194
+ yield self
195
+ ensure
196
+ flush
197
+ end
198
+
199
+ def flush
200
+ unless @backlog.empty?
201
+ @statsd.send_data @backlog.join("\n")
202
+ @backlog.clear
203
+ end
204
+ end
205
+
206
+ def send_batch_data(message)
207
+ @backlog << message
208
+ if @backlog.size >= @batch_size
209
+ flush
210
+ end
211
+ end
212
+
213
+ def send_method
214
+ lambda { |data|
215
+ @backlog << data
216
+ if @backlog.size >= @batch_size
217
+ flush
218
+ end
219
+ }
220
+ end
112
221
  end
113
222
 
114
223
  module Rails
data/spec/statsd_spec.rb CHANGED
@@ -55,6 +55,48 @@ describe Statsd::Client do
55
55
  c = Statsd::Client.new(:prefix => prefix)
56
56
  c.prefix.should match(prefix)
57
57
  end
58
+
59
+ it 'should accept a :resolve_always keyword argument' do
60
+ lookup = false
61
+ c = Statsd::Client.new(:resolve_always => lookup)
62
+ c.resolve_always.should be(lookup)
63
+ end
64
+
65
+ context 'when :resolve_always is not specified' do
66
+
67
+ context 'when host is localhost or 127.0.0.1' do
68
+ it ':resolve_always should default to false' do
69
+ c = Statsd::Client.new(:host => 'localhost')
70
+ c.resolve_always.should be(false)
71
+ end
72
+ end
73
+
74
+ context 'when host is not local' do
75
+ it ':resolve_always should default to true' do
76
+ c = Statsd::Client.new(:host => 'statsd.example.example')
77
+ c.resolve_always.should be(true)
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ describe '#send_stats' do
86
+
87
+ it 'should use cached resolve address when :resolve_always is false' do
88
+ c = Statsd::Client.new(:resolve_always => false)
89
+ sock = c.instance_variable_get(:@socket)
90
+ expect(sock).to receive(:send).with(anything, 0)
91
+ c.increment('foo')
92
+ end
93
+
94
+ it 'should always resolve address when :resolve_always is true' do
95
+ c = Statsd::Client.new(:resolve_always => true)
96
+ sock = c.instance_variable_get(:@socket)
97
+ expect(sock).to receive(:send).with(anything, 0, c.host, c.port)
98
+ c.increment('foo')
99
+ end
58
100
  end
59
101
 
60
102
  describe '#timing' do
@@ -148,4 +190,18 @@ describe Statsd::Client do
148
190
  c.gauge('foo' => 1)
149
191
  end
150
192
  end
151
- end
193
+
194
+ describe '#batch' do
195
+ let(:c) { Statsd::Client.new }
196
+ subject { c.batch { |b| b.increment('foo'); b.increment('bar'); } }
197
+
198
+ it 'should take a block and put increments into a buffer' do
199
+ Statsd::Batch.any_instance do |b|
200
+ b.backlog.should_receive(:<<).exactly.twice
201
+ end
202
+ Statsd::Batch.any_instance.should_receive(:flush).and_call_original
203
+ c.should_receive(:send_data).once
204
+ subject
205
+ end
206
+ end
207
+ end
data/statsd.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "lookout-statsd"
5
- s.version = "1.0.0"
5
+ s.version = "2.0.0"
6
6
  s.platform = Gem::Platform::RUBY
7
7
 
8
8
  s.authors = ['R. Tyler Croy', 'Andrew Coldham', 'Ben VandenBos']
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lookout-statsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - R. Tyler Croy
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-07-09 00:00:00.000000000 Z
13
+ date: 2016-05-16 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: A simple ruby statsd client.
16
16
  email:
@@ -20,6 +20,7 @@ extensions: []
20
20
  extra_rdoc_files: []
21
21
  files:
22
22
  - ".gitignore"
23
+ - ".travis.yml"
23
24
  - Gemfile
24
25
  - Guardfile
25
26
  - README.md
@@ -50,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
51
  version: 1.3.6
51
52
  requirements: []
52
53
  rubyforge_project:
53
- rubygems_version: 2.4.5
54
+ rubygems_version: 2.4.6
54
55
  signing_key:
55
56
  specification_version: 4
56
57
  summary: Ruby statsd client.