Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional IPv6 support #38

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.rdoc
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Bundler:
# Set up a global Statsd client for a server on localhost:9125 # Set up a global Statsd client for a server on localhost:9125
$statsd = Statsd.new 'localhost', 9125 $statsd = Statsd.new 'localhost', 9125


# Set up a global Statsd client for a server on IPv6 port 9125
$statsd = Statsd.new '::1', 9125, true

# Send some stats # Send some stats
$statsd.increment 'garets' $statsd.increment 'garets'
$statsd.timing 'glork', 320 $statsd.timing 'glork', 320
Expand Down
25 changes: 21 additions & 4 deletions lib/statsd.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@


# = Statsd: A Statsd client (https://github.com/etsy/statsd) # = Statsd: A Statsd client (https://github.com/etsy/statsd)
# #
# @example Set up a global Statsd client for a server on localhost:9125 # @example Set up a global Statsd client for a server on localhost:8125
# $statsd = Statsd.new 'localhost', 8125 # $statsd = Statsd.new 'localhost', 8125
# @example Set up a global Statsd client for a server on IPv6 port 8125
# $statsd = Statsd.new '::1', 8125, true
# @example Send some stats # @example Send some stats
# $statsd.increment 'garets' # $statsd.increment 'garets'
# $statsd.timing 'glork', 320 # $statsd.timing 'glork', 320
Expand Down Expand Up @@ -46,6 +48,7 @@ class Batch < Statsd
:namespace, :namespace=, :namespace, :namespace=,
:host, :host=, :host, :host=,
:port, :port=, :port, :port=,
:ipv6, :ipv6=,
:prefix, :prefix,
:postfix :postfix


Expand Down Expand Up @@ -97,6 +100,9 @@ def send_to_socket(message)
# StatsD port. Defaults to 8125. # StatsD port. Defaults to 8125.
attr_reader :port attr_reader :port


# StatsD ipv6. Defaults to false.
attr_reader :ipv6

# StatsD namespace prefix, generated from #namespace # StatsD namespace prefix, generated from #namespace
attr_reader :prefix attr_reader :prefix


Expand All @@ -113,8 +119,9 @@ class << self


# @param [String] host your statsd host # @param [String] host your statsd host
# @param [Integer] port your statsd port # @param [Integer] port your statsd port
def initialize(host = '127.0.0.1', port = 8125) # @param [Bool] ipv6 can be 'true' or 'false'
self.host, self.port = host, port def initialize(host = '127.0.0.1', port = 8125, ipv6 = false)
self.host, self.port, self.ipv6 = host, port, ipv6
@prefix = nil @prefix = nil
@batch_size = 10 @batch_size = 10
@postfix = nil @postfix = nil
Expand Down Expand Up @@ -149,6 +156,12 @@ def port=(port)
@port = port || 8125 @port = port || 8125
end end


# @attribute [w] ipv6
# Writes are not thread safe.
def ipv6=(ipv6)
@ipv6 = ipv6 || false
end

# Sends an increment (count = 1) for the given stat to the statsd server. # Sends an increment (count = 1) for the given stat to the statsd server.
# #
# @param [String] stat stat name # @param [String] stat stat name
Expand Down Expand Up @@ -270,6 +283,10 @@ def send_stats(stat, delta, type, sample_rate=1)
end end


def socket def socket
Thread.current[:statsd_socket] ||= UDPSocket.new Thread.current[:statsd_socket] ||= UDPSocket.new addr_family
end

def addr_family
@ipv6 ? Socket::AF_INET6 : Socket::AF_INET
end end
end end
49 changes: 47 additions & 2 deletions spec/statsd_spec.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,19 +18,22 @@ class Statsd
@statsd.port.must_equal 1234 @statsd.port.must_equal 1234
end end


it "should default the host to 127.0.0.1 and port to 8125" do it "should default the host to 127.0.0.1, port to 8125, and ipv6 to false" do
statsd = Statsd.new statsd = Statsd.new
statsd.host.must_equal '127.0.0.1' statsd.host.must_equal '127.0.0.1'
statsd.port.must_equal 8125 statsd.port.must_equal 8125
statsd.ipv6.must_equal false
end end
end end


describe "#host and #port" do describe "#host and #port" do
it "should set host and port" do it "should set host, port and ipv6" do
@statsd.host = '1.2.3.4' @statsd.host = '1.2.3.4'
@statsd.port = 5678 @statsd.port = 5678
@statsd.ipv6 = true
@statsd.host.must_equal '1.2.3.4' @statsd.host.must_equal '1.2.3.4'
@statsd.port.must_equal 5678 @statsd.port.must_equal 5678
@statsd.ipv6.must_equal true
end end


it "should not resolve hostnames to IPs" do it "should not resolve hostnames to IPs" do
Expand All @@ -47,6 +50,16 @@ class Statsd
@statsd.port = nil @statsd.port = nil
@statsd.port.must_equal 8125 @statsd.port.must_equal 8125
end end

it "should set nil ipv6 to default" do
@statsd.ipv6 = nil
@statsd.ipv6.must_equal false
end

it "should allow an IPv6 address" do
@statsd.host = '::1'
@statsd.host.must_equal '::1'
end
end end


describe "#increment" do describe "#increment" do
Expand Down Expand Up @@ -351,6 +364,12 @@ class Statsd::SomeClass; end
@statsd.port.must_equal 42 @statsd.port.must_equal 42
end end


it "should support setting ipv6 for the underlying instance" do
batch = Statsd::Batch.new(@statsd)
batch.ipv6 = true
@statsd.ipv6.must_equal true
end

end end


describe "thread safety" do describe "thread safety" do
Expand All @@ -370,7 +389,9 @@ class Statsd::SomeClass; end


describe Statsd do describe Statsd do
describe "with a real UDP socket" do describe "with a real UDP socket" do

it "should actually send stuff over the socket" do it "should actually send stuff over the socket" do
Thread.current[:statsd_socket] = nil
socket = UDPSocket.new socket = UDPSocket.new
host, port = 'localhost', 12345 host, port = 'localhost', 12345
socket.bind(host, port) socket.bind(host, port)
Expand All @@ -380,5 +401,29 @@ class Statsd::SomeClass; end
message = socket.recvfrom(16).first message = socket.recvfrom(16).first
message.must_equal 'foobar:1|c' message.must_equal 'foobar:1|c'
end end

it "should send stuff over an IPv4 socket" do
Thread.current[:statsd_socket] = nil
socket = UDPSocket.new Socket::AF_INET
host, port = '127.0.0.1', 12346
socket.bind(host, port)

statsd = Statsd.new(host, port, false)
statsd.increment('foobar')
message = socket.recvfrom(16).first
message.must_equal 'foobar:1|c'
end

it "should send stuff over an IPv6 socket" do
Thread.current[:statsd_socket] = nil
socket = UDPSocket.new Socket::AF_INET6
host, port = '::1', 12347
socket.bind(host, port)

statsd = Statsd.new(host, port, true)
statsd.increment('foobar')
message = socket.recvfrom(16).first
message.must_equal 'foobar:1|c'
end
end end
end if ENV['LIVE'] end if ENV['LIVE']