librato-statsd-ruby 1.0.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.
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new("librato-statsd-ruby", "1.0.0") do |s|
4
+ s.authors = ["Bryan Mikaelian"]
5
+ s.email = 'support@librato.com'
6
+
7
+ s.summary = "A Ruby StatsD client with Librato support"
8
+
9
+ s.homepage = "https://www.librato.com/docs/kb/collect/collection_agents/stastd.html"
10
+ s.licenses = %w[MIT]
11
+
12
+ s.extra_rdoc_files = %w[LICENSE.txt README.md]
13
+
14
+ if $0 =~ /gem/ # If running under rubygems (building), otherwise, just leave
15
+ s.files = `git ls-files`.split($\)
16
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
+ end
18
+
19
+ s.add_development_dependency "minitest", ">= 3.2.0"
20
+ s.add_development_dependency "yard"
21
+ s.add_development_dependency "simplecov", ">= 0.6.4"
22
+ s.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,43 @@
1
+ require 'bundler/setup'
2
+
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
6
+ require 'minitest/autorun'
7
+ require 'librato-statsd-ruby'
8
+ require 'logger'
9
+ require 'timeout'
10
+
11
+ class FakeUDPSocket
12
+ def initialize
13
+ @buffer = []
14
+ end
15
+
16
+ def write(message)
17
+ @buffer.push [message]
18
+ message.length
19
+ end
20
+
21
+ def recv
22
+ @buffer.shift
23
+ end
24
+
25
+ def clear
26
+ @buffer = []
27
+ end
28
+
29
+ def to_s
30
+ inspect
31
+ end
32
+
33
+ def inspect
34
+ "<#{self.class.name}: #{@buffer.inspect}>"
35
+ end
36
+ end
37
+
38
+ class FakeTCPSocket < FakeUDPSocket
39
+ alias_method :readline, :recv
40
+ def write(message)
41
+ @buffer.push message
42
+ end
43
+ end
@@ -0,0 +1,117 @@
1
+ require 'helper'
2
+
3
+ describe Statsd::Admin do
4
+
5
+ before do
6
+ class Statsd::Admin
7
+ o, $VERBOSE = $VERBOSE, nil
8
+ alias connect_old connect
9
+ def connect
10
+ $connect_count ||= 0
11
+ $connect_count += 1
12
+ end
13
+ $VERBOSE = o
14
+ end
15
+ @admin = Statsd::Admin.new('localhost', 1234)
16
+ @socket = @admin.instance_variable_set(:@socket, FakeTCPSocket.new)
17
+ end
18
+
19
+ after do
20
+ class Statsd::Admin
21
+ o, $VERBOSE = $VERBOSE, nil
22
+ alias connect connect_old
23
+ $VERBOSE = o
24
+ end
25
+ end
26
+
27
+ describe "#initialize" do
28
+ it "should set the host and port" do
29
+ @admin.host.must_equal 'localhost'
30
+ @admin.port.must_equal 1234
31
+ end
32
+
33
+ it "should default the host to 127.0.0.1 and port to 8126" do
34
+ statsd = Statsd::Admin.new
35
+ statsd.host.must_equal '127.0.0.1'
36
+ statsd.port.must_equal 8126
37
+ end
38
+ end
39
+
40
+ describe "#host and #port" do
41
+ it "should set host and port" do
42
+ @admin.host = '1.2.3.4'
43
+ @admin.port = 5678
44
+ @admin.host.must_equal '1.2.3.4'
45
+ @admin.port.must_equal 5678
46
+ end
47
+
48
+ it "should not resolve hostnames to IPs" do
49
+ @admin.host = 'localhost'
50
+ @admin.host.must_equal 'localhost'
51
+ end
52
+
53
+ it "should set nil host to default" do
54
+ @admin.host = nil
55
+ @admin.host.must_equal '127.0.0.1'
56
+ end
57
+
58
+ it "should set nil port to default" do
59
+ @admin.port = nil
60
+ @admin.port.must_equal 8126
61
+ end
62
+ end
63
+
64
+ %w(gauges counters timers).each do |action|
65
+ describe "##{action}" do
66
+ it "should send a command and return a Hash" do
67
+ ["{'foo.bar': 0,\n",
68
+ "'foo.baz': 1,\n",
69
+ "'foo.quux': 2 }\n",
70
+ "END\n","\n"].each do |line|
71
+ @socket.write line
72
+ end
73
+ result = @admin.send action.to_sym
74
+ result.must_be_kind_of Hash
75
+ result.size.must_equal 3
76
+ @socket.readline.must_equal "#{action}\n"
77
+ end
78
+ end
79
+
80
+ describe "#del#{action}" do
81
+ it "should send a command and return an Array" do
82
+ ["deleted: foo.bar\n",
83
+ "deleted: foo.baz\n",
84
+ "deleted: foo.quux\n",
85
+ "END\n", "\n"].each do |line|
86
+ @socket.write line
87
+ end
88
+ result = @admin.send "del#{action}", "foo.*"
89
+ result.must_be_kind_of Array
90
+ result.size.must_equal 3
91
+ @socket.readline.must_equal "del#{action} foo.*\n"
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "#stats" do
97
+ it "should send a command and return a Hash" do
98
+ ["whatever: 0\n", "END\n", "\n"].each do |line|
99
+ @socket.write line
100
+ end
101
+ result = @admin.stats
102
+ result.must_be_kind_of Hash
103
+ result["whatever"].must_equal 0
104
+ @socket.readline.must_equal "stats\n"
105
+ end
106
+ end
107
+
108
+ describe "#connect" do
109
+ it "should reconnect" do
110
+ c = $connect_count
111
+ @admin.connect
112
+ ($connect_count - c).must_equal 1
113
+ end
114
+ end
115
+ end
116
+
117
+
@@ -0,0 +1,562 @@
1
+ require 'helper'
2
+
3
+ describe Statsd do
4
+ before do
5
+ class Statsd
6
+ o, $VERBOSE = $VERBOSE, nil
7
+ alias connect_old connect
8
+ def connect
9
+ $connect_count ||= 1
10
+ $connect_count += 1
11
+ end
12
+ $VERBOSE = o
13
+ end
14
+
15
+ @statsd = Statsd.new('localhost', 1234)
16
+ @socket = @statsd.instance_variable_set(:@socket, FakeUDPSocket.new)
17
+ end
18
+
19
+ after do
20
+ class Statsd
21
+ o, $VERBOSE = $VERBOSE, nil
22
+ alias connect connect_old
23
+ $VERBOSE = o
24
+ end
25
+ end
26
+
27
+ describe "#initialize" do
28
+ it "should set the host and port" do
29
+ @statsd.host.must_equal 'localhost'
30
+ @statsd.port.must_equal 1234
31
+ end
32
+
33
+ it "should default the host to 127.0.0.1 and port to 8125" do
34
+ statsd = Statsd.new
35
+ statsd.host.must_equal '127.0.0.1'
36
+ statsd.port.must_equal 8125
37
+ end
38
+
39
+ it "should set delimiter to period by default" do
40
+ @statsd.delimiter.must_equal "."
41
+ end
42
+ end
43
+
44
+ describe "#host and #port" do
45
+ it "should set host and port" do
46
+ @statsd.host = '1.2.3.4'
47
+ @statsd.port = 5678
48
+ @statsd.host.must_equal '1.2.3.4'
49
+ @statsd.port.must_equal 5678
50
+ end
51
+
52
+ it "should not resolve hostnames to IPs" do
53
+ @statsd.host = 'localhost'
54
+ @statsd.host.must_equal 'localhost'
55
+ end
56
+
57
+ it "should set nil host to default" do
58
+ @statsd.host = nil
59
+ @statsd.host.must_equal '127.0.0.1'
60
+ end
61
+
62
+ it "should set nil port to default" do
63
+ @statsd.port = nil
64
+ @statsd.port.must_equal 8125
65
+ end
66
+
67
+ it "should allow an IPv6 address" do
68
+ @statsd.host = '::1'
69
+ @statsd.host.must_equal '::1'
70
+ end
71
+ end
72
+
73
+ describe "#delimiter" do
74
+ it "should set delimiter" do
75
+ @statsd.delimiter = "-"
76
+ @statsd.delimiter.must_equal "-"
77
+ end
78
+
79
+ it "should set default to period if not given a value" do
80
+ @statsd.delimiter = nil
81
+ @statsd.delimiter.must_equal "."
82
+ end
83
+ end
84
+
85
+ describe "#increment" do
86
+ it "should format the message according to the statsd spec" do
87
+ @statsd.increment('foobar')
88
+ @socket.recv.must_equal ['foobar:1|c']
89
+ end
90
+
91
+ describe "with a sample rate" do
92
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
93
+ it "should format the message according to the statsd spec" do
94
+ @statsd.increment('foobar', { sample_rate: 0.5 })
95
+ @socket.recv.must_equal ['foobar:1|c|@0.5']
96
+ end
97
+ end
98
+ end
99
+
100
+ describe "#decrement" do
101
+ it "should format the message according to the statsd spec" do
102
+ @statsd.decrement('foobar')
103
+ @socket.recv.must_equal ['foobar:-1|c']
104
+ end
105
+
106
+ describe "with a sample rate" do
107
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
108
+ it "should format the message according to the statsd spec" do
109
+ @statsd.decrement('foobar', { sample_rate: 0.5 })
110
+ @socket.recv.must_equal ['foobar:-1|c|@0.5']
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "#gauge" do
116
+ it "should send a message with a 'g' type, per the nearbuy fork" do
117
+ @statsd.gauge('begrutten-suffusion', 536)
118
+ @socket.recv.must_equal ['begrutten-suffusion:536|g']
119
+ @statsd.gauge('begrutten-suffusion', -107.3)
120
+ @socket.recv.must_equal ['begrutten-suffusion:-107.3|g']
121
+ end
122
+
123
+ describe "with a sample rate" do
124
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
125
+ it "should format the message according to the statsd spec" do
126
+ @statsd.gauge('begrutten-suffusion', 536, { sample_rate: 0.1 })
127
+ @socket.recv.must_equal ['begrutten-suffusion:536|g|@0.1']
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "#timing" do
133
+ it "should format the message according to the statsd spec" do
134
+ @statsd.timing('foobar', 500)
135
+ @socket.recv.must_equal ['foobar:500|ms']
136
+ end
137
+
138
+ describe "with a sample rate" do
139
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
140
+ it "should format the message according to the statsd spec" do
141
+ @statsd.timing('foobar', 500, { sample_rate: 0.5 })
142
+ @socket.recv.must_equal ['foobar:500|ms|@0.5']
143
+ end
144
+ end
145
+ end
146
+
147
+ describe "#set" do
148
+ it "should format the message according to the statsd spec" do
149
+ @statsd.set('foobar', 765)
150
+ @socket.recv.must_equal ['foobar:765|s']
151
+ end
152
+
153
+ describe "with a sample rate" do
154
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
155
+ it "should format the message according to the statsd spec" do
156
+ @statsd.set('foobar', 500, { sample_rate: 0.5 })
157
+ @socket.recv.must_equal ['foobar:500|s|@0.5']
158
+ end
159
+ end
160
+ end
161
+
162
+ describe "#time" do
163
+ it "should format the message according to the statsd spec" do
164
+ @statsd.time('foobar') { 'test' }
165
+ @socket.recv.must_equal ['foobar:0|ms']
166
+ end
167
+
168
+ it "should return the result of the block" do
169
+ result = @statsd.time('foobar') { 'test' }
170
+ result.must_equal 'test'
171
+ end
172
+
173
+ describe "when given a block with an explicit return" do
174
+ it "should format the message according to the statsd spec" do
175
+ lambda { @statsd.time('foobar') { return 'test' } }.call
176
+ @socket.recv.must_equal ['foobar:0|ms']
177
+ end
178
+
179
+ it "should return the result of the block" do
180
+ result = lambda { @statsd.time('foobar') { return 'test' } }.call
181
+ result.must_equal 'test'
182
+ end
183
+ end
184
+
185
+ describe "with a sample rate" do
186
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
187
+
188
+ it "should format the message according to the statsd spec" do
189
+ @statsd.time('foobar', { sample_rate: 0.5 }) { 'test' }
190
+ @socket.recv.must_equal ['foobar:0|ms|@0.5']
191
+ end
192
+ end
193
+ end
194
+
195
+ describe "#sampled" do
196
+ describe "when the sample rate is 1" do
197
+ before { class << @statsd; def rand; raise end; end }
198
+ it "should send" do
199
+ @statsd.timing('foobar', 500, { sample_rate: 1 })
200
+ @socket.recv.must_equal ['foobar:500|ms']
201
+ end
202
+ end
203
+
204
+ describe "when the sample rate is greater than a random value [0,1]" do
205
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
206
+ it "should send" do
207
+ @statsd.timing('foobar', 500, { sample_rate: 0.5 })
208
+ @socket.recv.must_equal ['foobar:500|ms|@0.5']
209
+ end
210
+ end
211
+
212
+ describe "when the sample rate is less than a random value [0,1]" do
213
+ before { class << @statsd; def rand; 1; end; end } # ensure no delivery
214
+ it "should not send" do
215
+ @statsd.timing('foobar', 500, { sample_rate: 0.5 }).must_equal nil
216
+ end
217
+ end
218
+
219
+ describe "when the sample rate is equal to a random value [0,1]" do
220
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
221
+ it "should send" do
222
+ @statsd.timing('foobar', 500, { sample_rate: 0.5 })
223
+ @socket.recv.must_equal ['foobar:500|ms|@0.5']
224
+ end
225
+ end
226
+ end
227
+
228
+ describe "with namespace" do
229
+ before { @statsd.namespace = 'service' }
230
+
231
+ it "should add namespace to increment" do
232
+ @statsd.increment('foobar')
233
+ @socket.recv.must_equal ['service.foobar:1|c']
234
+ end
235
+
236
+ it "should add namespace to decrement" do
237
+ @statsd.decrement('foobar')
238
+ @socket.recv.must_equal ['service.foobar:-1|c']
239
+ end
240
+
241
+ it "should add namespace to timing" do
242
+ @statsd.timing('foobar', 500)
243
+ @socket.recv.must_equal ['service.foobar:500|ms']
244
+ end
245
+
246
+ it "should add namespace to gauge" do
247
+ @statsd.gauge('foobar', 500)
248
+ @socket.recv.must_equal ['service.foobar:500|g']
249
+ end
250
+ end
251
+
252
+ describe "with postfix" do
253
+ before { @statsd.postfix = 'ip-23-45-56-78' }
254
+
255
+ it "should add postfix to increment" do
256
+ @statsd.increment('foobar')
257
+ @socket.recv.must_equal ['foobar.ip-23-45-56-78:1|c']
258
+ end
259
+
260
+ it "should add postfix to decrement" do
261
+ @statsd.decrement('foobar')
262
+ @socket.recv.must_equal ['foobar.ip-23-45-56-78:-1|c']
263
+ end
264
+
265
+ it "should add namespace to timing" do
266
+ @statsd.timing('foobar', 500)
267
+ @socket.recv.must_equal ['foobar.ip-23-45-56-78:500|ms']
268
+ end
269
+
270
+ it "should add namespace to gauge" do
271
+ @statsd.gauge('foobar', 500)
272
+ @socket.recv.must_equal ['foobar.ip-23-45-56-78:500|g']
273
+ end
274
+ end
275
+
276
+ describe '#postfix=' do
277
+ describe "when nil, false, or empty" do
278
+ it "should set postfix to nil" do
279
+ [nil, false, ''].each do |value|
280
+ @statsd.postfix = 'a postfix'
281
+ @statsd.postfix = value
282
+ @statsd.postfix.must_equal nil
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ describe "with logging" do
289
+ require 'stringio'
290
+ before { Statsd.logger = Logger.new(@log = StringIO.new)}
291
+
292
+ it "should write to the log in debug" do
293
+ Statsd.logger.level = Logger::DEBUG
294
+
295
+ @statsd.increment('foobar')
296
+
297
+ @log.string.must_match "Statsd: foobar:1|c"
298
+ end
299
+
300
+ it "should not write to the log unless debug" do
301
+ Statsd.logger.level = Logger::INFO
302
+
303
+ @statsd.increment('foobar')
304
+
305
+ @log.string.must_be_empty
306
+ end
307
+ end
308
+
309
+ describe "stat names" do
310
+ it "should accept anything as stat" do
311
+ @statsd.increment(Object)
312
+ end
313
+
314
+ it "should replace ruby constant delimeter with graphite package name" do
315
+ class Statsd::SomeClass; end
316
+ @statsd.increment(Statsd::SomeClass)
317
+
318
+ @socket.recv.must_equal ['Statsd.SomeClass:1|c']
319
+ end
320
+
321
+ describe "custom delimiter" do
322
+ before do
323
+ @statsd.delimiter = "-"
324
+ end
325
+
326
+ it "should replace ruby constant delimiter with custom delimiter" do
327
+ class Statsd::SomeOtherClass; end
328
+ @statsd.increment(Statsd::SomeOtherClass)
329
+
330
+ @socket.recv.must_equal ['Statsd-SomeOtherClass:1|c']
331
+ end
332
+ end
333
+
334
+ it "should replace statsd reserved chars in the stat name" do
335
+ @statsd.increment('ray@hostname.blah|blah.blah:blah')
336
+ @socket.recv.must_equal ['ray_hostname.blah_blah.blah_blah:1|c']
337
+ end
338
+ end
339
+
340
+ describe "handling socket errors" do
341
+ before do
342
+ require 'stringio'
343
+ Statsd.logger = Logger.new(@log = StringIO.new)
344
+ @socket.instance_eval { def write(*) raise SocketError end }
345
+ end
346
+
347
+ it "should ignore socket errors" do
348
+ @statsd.increment('foobar').must_equal nil
349
+ end
350
+
351
+ it "should log socket errors" do
352
+ @statsd.increment('foobar')
353
+ @log.string.must_match 'Statsd: SocketError'
354
+ end
355
+ end
356
+
357
+ describe "batching" do
358
+ it "should have a default batch size of 10" do
359
+ @statsd.batch_size.must_equal 10
360
+ end
361
+
362
+ it "should have a modifiable batch size" do
363
+ @statsd.batch_size = 7
364
+ @statsd.batch_size.must_equal 7
365
+ @statsd.batch do |b|
366
+ b.batch_size.must_equal 7
367
+ end
368
+ end
369
+
370
+ it "should flush the batch at the batch size or at the end of the block" do
371
+ @statsd.batch do |b|
372
+ b.batch_size = 3
373
+
374
+ # The first three should flush, the next two will be flushed when the
375
+ # block is done.
376
+ 5.times { b.increment('foobar') }
377
+
378
+ @socket.recv.must_equal [(["foobar:1|c"] * 3).join("\n")]
379
+ end
380
+
381
+ @socket.recv.must_equal [(["foobar:1|c"] * 2).join("\n")]
382
+ end
383
+
384
+ it "should not flush to the socket if the backlog is empty" do
385
+ batch = Statsd::Batch.new(@statsd)
386
+ batch.flush
387
+ @socket.recv.must_be :nil?
388
+
389
+ batch.increment 'foobar'
390
+ batch.flush
391
+ @socket.recv.must_equal %w[foobar:1|c]
392
+ end
393
+
394
+ it "should support setting namespace for the underlying instance" do
395
+ batch = Statsd::Batch.new(@statsd)
396
+ batch.namespace = 'ns'
397
+ @statsd.namespace.must_equal 'ns'
398
+ end
399
+
400
+ it "should support setting host for the underlying instance" do
401
+ batch = Statsd::Batch.new(@statsd)
402
+ batch.host = '1.2.3.4'
403
+ @statsd.host.must_equal '1.2.3.4'
404
+ end
405
+
406
+ it "should support setting port for the underlying instance" do
407
+ batch = Statsd::Batch.new(@statsd)
408
+ batch.port = 42
409
+ @statsd.port.must_equal 42
410
+ end
411
+
412
+ end
413
+
414
+ describe "#connect" do
415
+ it "should reconnect" do
416
+ c = $connect_count
417
+ @statsd.connect
418
+ ($connect_count - c).must_equal 1
419
+ end
420
+ end
421
+
422
+ describe "tags" do
423
+ before { class << @statsd; def rand; 0; end; end } # ensure delivery
424
+
425
+ describe "with counters" do
426
+ it "accepts tags" do
427
+ @statsd.increment('foobar', { tags: { foo: 'bar' }})
428
+ @socket.recv.must_equal ['foobar#foo=bar:1|c']
429
+ end
430
+
431
+ it "accepts tags with sample rate" do
432
+ @statsd.increment('foobar', { sample_rate: 0.5, tags: { foo: 'bar' }})
433
+ @socket.recv.must_equal ['foobar#foo=bar:1|c|@0.5']
434
+ end
435
+ end
436
+
437
+ describe "with timers" do
438
+ it "accepts tags" do
439
+ @statsd.time('foobar', { tags: { foo: 'bar' }}) {}
440
+ @socket.recv.must_equal ['foobar#foo=bar:0|ms']
441
+ end
442
+
443
+ it "accepts tags with sample rate" do
444
+ @statsd.time('foobar', { sample_rate: 0.5, tags: { foo: 'bar' }}) {}
445
+ @socket.recv.must_equal ['foobar#foo=bar:0|ms|@0.5']
446
+ end
447
+ end
448
+
449
+ describe "with postfix" do
450
+ before { @statsd.postfix = 'foo' }
451
+
452
+ it "accepts tags" do
453
+ @statsd.increment('foobar', { tags: { foo: 'bar' }})
454
+ @socket.recv.must_equal ['foobar.foo#foo=bar:1|c']
455
+ end
456
+ end
457
+ end
458
+
459
+ end
460
+
461
+ describe Statsd do
462
+ describe "with a real UDP socket" do
463
+ it "should actually send stuff over the socket" do
464
+ family = Addrinfo.udp(UDPSocket.getaddress('localhost'), 0).afamily
465
+ begin
466
+ socket = UDPSocket.new family
467
+ host, port = 'localhost', 0
468
+ socket.bind(host, port)
469
+ port = socket.addr[1]
470
+
471
+ statsd = Statsd.new(host, port)
472
+ statsd.increment('foobar')
473
+ message = socket.recvfrom(16).first
474
+ message.must_equal 'foobar:1|c'
475
+ ensure
476
+ socket.close
477
+ end
478
+ end
479
+
480
+ it "should send stuff over an IPv4 socket" do
481
+ begin
482
+ socket = UDPSocket.new Socket::AF_INET
483
+ host, port = '127.0.0.1', 0
484
+ socket.bind(host, port)
485
+ port = socket.addr[1]
486
+
487
+ statsd = Statsd.new(host, port)
488
+ statsd.increment('foobar')
489
+ message = socket.recvfrom(16).first
490
+ message.must_equal 'foobar:1|c'
491
+ ensure
492
+ socket.close
493
+ end
494
+ end
495
+
496
+ it "should send stuff over an IPv6 socket" do
497
+ begin
498
+ socket = UDPSocket.new Socket::AF_INET6
499
+ host, port = '::1', 0
500
+ socket.bind(host, port)
501
+ port = socket.addr[1]
502
+
503
+ statsd = Statsd.new(host, port)
504
+ statsd.increment('foobar')
505
+ message = socket.recvfrom(16).first
506
+ message.must_equal 'foobar:1|c'
507
+ ensure
508
+ socket.close
509
+ end
510
+ end
511
+ end
512
+
513
+ describe "supports TCP sockets" do
514
+ it "should connect to and send stats over TCPv4" do
515
+ begin
516
+ host, port = '127.0.0.1', 0
517
+ server = TCPServer.new host, port
518
+ port = server.addr[1]
519
+
520
+ socket = nil
521
+ Thread.new { socket = server.accept }
522
+
523
+ statsd = Statsd.new(host, port, :tcp)
524
+ statsd.increment('foobar')
525
+
526
+ Timeout.timeout(5) do
527
+ Thread.pass while socket == nil
528
+ end
529
+
530
+ message = socket.recvfrom(16).first
531
+ message.must_equal 'foobar:1|c'
532
+ ensure
533
+ socket.close if socket
534
+ server.close
535
+ end
536
+ end
537
+
538
+ it "should connect to and send stats over TCPv6" do
539
+ begin
540
+ host, port = '::1', 0
541
+ server = TCPServer.new host, port
542
+ port = server.addr[1]
543
+
544
+ socket = nil
545
+ Thread.new { socket = server.accept }
546
+
547
+ statsd = Statsd.new(host, port, :tcp)
548
+ statsd.increment('foobar')
549
+
550
+ Timeout.timeout(5) do
551
+ Thread.pass while socket == nil
552
+ end
553
+
554
+ message = socket.recvfrom(16).first
555
+ message.must_equal 'foobar:1|c'
556
+ ensure
557
+ socket.close if socket
558
+ server.close
559
+ end
560
+ end
561
+ end
562
+ end