Skip to content

Commit f4a523f

Browse files
authored
Merge pull request #539 from dellis23/memcached-recv
memcached: call socket.recv multiple times to get all stats
2 parents c2f842f + f641277 commit f4a523f

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/collectors/memcached/memcached.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,26 @@ def get_raw_stats(self, host, port):
8787
else:
8888
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
8989
sock.connect((host, int(port)))
90+
91+
# give up after a reasonable amount of time
92+
sock.settimeout(3)
93+
9094
# request stats
9195
sock.send('stats\n')
92-
# something big enough to get whatever is sent back
93-
data = sock.recv(4096)
96+
97+
# stats can be sent across multiple packets, so make sure we've
98+
# read up until the END marker
99+
while True:
100+
received = sock.recv(4096)
101+
if not received:
102+
break
103+
data += received
104+
if data.endswith('END\r\n'):
105+
break
94106
except socket.error:
95107
self.log.exception('Failed to get stats from %s:%s',
96108
host, port)
109+
sock.close()
97110
return data
98111

99112
def get_stats(self, host, port):

src/collectors/memcached/test/testmemcached.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from test import CollectorTestCase
66
from test import get_collector_config
77
from test import unittest
8+
from mock import MagicMock
89
from mock import Mock
910
from mock import patch
1011

@@ -27,6 +28,15 @@ def setUp(self):
2728
def test_import(self):
2829
self.assertTrue(MemcachedCollector)
2930

31+
@patch('socket.socket')
32+
def test_get_raw_stats_works_across_packet_boundaries(self, socket_mock):
33+
socket_instance = MagicMock()
34+
socket_mock.return_value = socket_instance
35+
stats_packets = ['stat foo 1\r\n', 'END\r\n']
36+
socket_instance.recv.side_effect = stats_packets
37+
stats = self.collector.get_raw_stats('', None)
38+
self.assertEqual(stats, ''.join(stats_packets))
39+
3040
@patch.object(Collector, 'publish')
3141
def test_should_work_with_real_data(self, publish_mock):
3242
patch_raw_stats = patch.object(

0 commit comments

Comments
 (0)