Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 291a76a

Browse files
add prefer_ipv6 option, remember if we are in v4 or v6 mode
Signed-off-by: Matt Cipperly <mcipperly@fb.com>
1 parent 4a30c09 commit 291a76a

File tree

3 files changed

+80
-12
lines changed

3 files changed

+80
-12
lines changed

‎README.rst‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ can also specify remote logger by passing the options.
8080
# for remote fluent
8181
logger = sender.FluentSender('app', host='host', port=24224)
8282
83+
The logger will prefer using IPv4 and fall back to IPv6 by default. Should you wish to prefer
84+
IPv6 and fall back to IPv4, specify `prefer_ipv6` option as `True`.
85+
86+
.. code:: python
87+
88+
# for remote fluent preferring IPv6, falling back to IPv4
89+
logger = sender.FluentSender('app', host='host', port=24224, prefer_ipv6=True)
90+
8391
For sending event, call `emit` method with your event. Following example will send the event to
8492
fluentd, with tag 'app.follow' and the attributes 'from' and 'to'.
8593

‎fluent/sender.py‎

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def __init__(self,
5454
buffer_overflow_handler=None,
5555
nanosecond_precision=False,
5656
msgpack_kwargs=None,
57+
prefer_ipv6=False,
5758
**kwargs):
5859
"""
5960
:param kwargs: This kwargs argument is not used in __init__. This will be removed in the next major version.
@@ -69,6 +70,8 @@ def __init__(self,
6970
self.msgpack_kwargs = {} if msgpack_kwargs is None else msgpack_kwargs
7071

7172
self.socket = None
73+
self.prefer_ipv6 = prefer_ipv6
74+
self.ip_addr_family = None
7275
self.pendings = None
7376
self.lock = threading.Lock()
7477
self._closed = False
@@ -120,12 +123,19 @@ def close(self):
120123
self._close()
121124
self.pendings = None
122125

123-
def _is_ipv4_host(self):
124-
try:
125-
socket.getaddrinfo(self.host, None, socket.AF_INET)
126-
return True
127-
except socket.error:
128-
return False
126+
def _find_ip_addr_family(self):
127+
if not self.prefer_ipv6:
128+
try:
129+
socket.getaddrinfo(self.host, None, socket.AF_INET)
130+
return socket.AF_INET
131+
except socket.error:
132+
return socket.AF_INET6
133+
else:
134+
try:
135+
socket.getaddrinfo(self.host, None, socket.AF_INET6)
136+
return socket.AF_INET6
137+
except socket.error:
138+
return socket.AF_INET
129139

130140
def _make_packet(self, label, timestamp, data):
131141
if label:
@@ -208,12 +218,10 @@ def _reconnect(self):
208218
sock.settimeout(self.timeout)
209219
sock.connect(self.host[len('unix://'):])
210220
else:
211-
if self._is_ipv4_host():
212-
sock = socket.socket(socket.AF_INET,
213-
socket.SOCK_STREAM)
214-
else:
215-
sock = socket.socket(socket.AF_INET6,
216-
socket.SOCK_STREAM)
221+
if not self.ip_addr_family:
222+
self.ip_addr_family = self._find_ip_addr_family()
223+
sock = socket.socket(self.ip_addr_family,
224+
socket.SOCK_STREAM)
217225
sock.settimeout(self.timeout)
218226
# This might be controversial and may need to be removed
219227
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

‎tests/test_sender.py‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,25 @@ def recv(self, bufsize, flags=0):
292292
finally:
293293
self._sender.socket = old_sock
294294

295+
def test_ipv6_preferred_but_not_avail(self):
296+
real_getaddrinfo = socket.getaddrinfo
297+
298+
def _fake_getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
299+
if family == socket.AF_INET6:
300+
raise socket.gaierror("mock: IPv4 Only")
301+
else:
302+
return real_getaddrinfo(host, port, family, type, proto, flags)
303+
with patch('socket.getaddrinfo', side_effect=_fake_getaddrinfo):
304+
sender = fluent.sender.FluentSender(tag='test',
305+
host='localhost',
306+
port=self._server.port,
307+
prefer_ipv6=True)
308+
sender.emit('foo', {'bar': 'baz'})
309+
sender._close()
310+
data = self.get_data()
311+
self.assertEqual(len(data), 1)
312+
self.assertEqual(data[0][2], {'bar': 'baz'})
313+
295314
def test_ipv6_only(self):
296315
# Test if our host supports IPv6 before running this test
297316
try:
@@ -323,6 +342,39 @@ def _fake_getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
323342
self.assertEqual(len(data), 1)
324343
self.assertEqual(data[0][2], {'bar': 'baz'})
325344

345+
def test_ipv6_preferred(self):
346+
# Test if our host supports IPv6 before running this test
347+
try:
348+
socket.gethostbyaddr('::1')
349+
except socket.herror:
350+
self.skipTest("Host does not support IPv6, cannot run this test")
351+
352+
self.tearDown()
353+
354+
real_getaddrinfo = socket.getaddrinfo
355+
356+
def _fake_getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
357+
if family == socket.AF_INET:
358+
raise socket.gaierror("mock: IPv6 Only")
359+
else:
360+
return real_getaddrinfo(host, port, family, type, proto, flags)
361+
362+
self._server = mockserver.MockRecvServer(host='localhost',
363+
inet_family=socket.AF_INET6)
364+
365+
366+
with patch('socket.getaddrinfo', side_effect=_fake_getaddrinfo):
367+
sender = fluent.sender.FluentSender(tag='test',
368+
host='localhost',
369+
port=self._server.port,
370+
prefer_ipv6=True)
371+
sender.emit('foo', {'bar': 'baz'})
372+
sender._close()
373+
data = self.get_data()
374+
self.assertEqual(len(data), 1)
375+
self.assertEqual(data[0][2], {'bar': 'baz'})
376+
377+
326378
@unittest.skipIf(sys.platform == "win32", "Unix socket not supported")
327379
def test_unix_socket(self):
328380
self.tearDown()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /