diff options
author | huangwei-ds5 <huangwei-ds5@gome.com.cn> | 2019-08-09 15:54:57 +0800 |
---|---|---|
committer | Andy McCurdy <andy@andymccurdy.com> | 2019-08-19 12:30:39 -0700 |
commit | d811ae71dbdbeeb4fc0ee73a96b7fbdb1aec8522 (patch) | |
tree | 928cee652b10c7ae6d0ba974ef47423f60a9f94f | |
parent | f0516c9f7589557883a5eb23a44531066e275950 (diff) | |
download | redis-py-d811ae71dbdbeeb4fc0ee73a96b7fbdb1aec8522.tar.gz |
version 3.3.8, fix MONITOR output to account for all types of clients3.3.8
The client section of MONITOR output varies for TCP connections, unix socket
connections and commands executed from Lua scripts. Account for each of these
cases by including an additional key `client_type` in the MONITOR output.
`client_type` will be one of ('tcp', 'unix', 'lua'). `client_address` and
`client_port` vary based on the `client_type`.
Fixes #1201
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | redis/__init__.py | 2 | ||||
-rwxr-xr-x | redis/client.py | 18 | ||||
-rw-r--r-- | tests/test_monitor.py | 11 |
4 files changed, 31 insertions, 3 deletions
@@ -1,3 +1,6 @@ +* 3.3.8 + * Fixed MONITOR parsing to properly parse IPv6 client addresses, unix + socket connections and commands issued from Lua. Thanks @kukey. #1201 * 3.3.7 * Fixed a regression introduced in 3.3.0 where socket.error exceptions (or subclasses) could potentially be raised instead of diff --git a/redis/__init__.py b/redis/__init__.py index bfd1839..9395147 100644 --- a/redis/__init__.py +++ b/redis/__init__.py @@ -29,7 +29,7 @@ def int_or_str(value): return value -__version__ = '3.3.7' +__version__ = '3.3.8' VERSION = tuple(map(int_or_str, __version__.split('.'))) __all__ = [ diff --git a/redis/client.py b/redis/client.py index c13ccff..df1ebfd 100755 --- a/redis/client.py +++ b/redis/client.py @@ -3002,7 +3002,7 @@ class Monitor(object): next_command() method returns one command from monitor listen() method yields commands from monitor. """ - monitor_re = re.compile(r'\[(\d+) (.+):(\d+)\] (.*)') + monitor_re = re.compile(r'\[(\d+) (.*)\] (.*)') command_re = re.compile(r'"(.*?)(?<!\\)"') def __init__(self, connection_pool): @@ -3028,14 +3028,28 @@ class Monitor(object): response = self.connection.encoder.decode(response, force=True) command_time, command_data = response.split(' ', 1) m = self.monitor_re.match(command_data) - db_id, client_address, client_port, command = m.groups() + db_id, client_info, command = m.groups() command = ' '.join(self.command_re.findall(command)) command = command.replace('\\"', '"').replace('\\\\', '\\') + + if client_info == 'lua': + client_address = 'lua' + client_port = '' + client_type = 'lua' + elif client_info.startswith('unix'): + client_address = 'unix' + client_port = client_info[5:] + client_type = 'unix' + else: + # use rsplit as ipv6 addresses contain colons + client_address, client_port = client_info.rsplit(':', 1) + client_type = 'tcp' return { 'time': float(command_time), 'db': int(db_id), 'client_address': client_address, 'client_port': client_port, + 'client_type': client_type, 'command': command } diff --git a/tests/test_monitor.py b/tests/test_monitor.py index 9e9ee83..09ec21b 100644 --- a/tests/test_monitor.py +++ b/tests/test_monitor.py @@ -29,6 +29,7 @@ class TestPipeline(object): response = wait_for_command(r, m, 'PING') assert isinstance(response['time'], float) assert response['db'] == 9 + assert response['client_type'] in ('tcp', 'unix') assert isinstance(response['client_address'], unicode) assert isinstance(response['client_port'], unicode) assert response['command'] == 'PING' @@ -45,3 +46,13 @@ class TestPipeline(object): r.get(byte_string) response = wait_for_command(r, m, 'GET foo\\x92') assert response['command'] == 'GET foo\\x92' + + def test_lua_script(self, r): + with r.monitor() as m: + script = 'return redis.call("GET", "foo")' + assert r.eval(script, 0) is None + response = wait_for_command(r, m, 'GET foo') + assert response['command'] == 'GET foo' + assert response['client_type'] == 'lua' + assert response['client_address'] == 'lua' + assert response['client_port'] == '' |