diff options
-rw-r--r-- | CHANGES | 1 | ||||
-rw-r--r-- | redis/_compat.py | 2 | ||||
-rw-r--r-- | redis/client.py | 36 | ||||
-rw-r--r-- | tests/test_commands.py | 32 |
4 files changed, 69 insertions, 2 deletions
@@ -10,6 +10,7 @@ * Added extra *SCAN commands that return iterators instead of the normal [cursor, data] type. Use scan_iter, hscan_iter, sscan_iter, and zscan_iter for iterators. Thanks Mathieu Longtin. + * Added support for SLOWLOG commands. Thanks Rick van Hattem. * 2.9.1 * IPv6 support. Thanks https://github.com/amashinchi * 2.9.0 diff --git a/redis/_compat.py b/redis/_compat.py index 38a7316..add9c9b 100644 --- a/redis/_compat.py +++ b/redis/_compat.py @@ -40,7 +40,7 @@ else: nativestr = lambda x: \ x if isinstance(x, str) else x.decode('utf-8', 'replace') u = lambda x: x - b = lambda x: x.encode('iso-8859-1') if not isinstance(x, bytes) else x + b = lambda x: x.encode('latin-1') if not isinstance(x, bytes) else x next = next unichr = chr imap = map diff --git a/redis/client.py b/redis/client.py index 0a1d4c9..3c333e7 100644 --- a/redis/client.py +++ b/redis/client.py @@ -260,6 +260,21 @@ def parse_zscan(response, **options): return nativestr(cursor), list(izip(it, imap(score_cast_func, it))) +def parse_slowlog(response, **options): + parse = options['parse'] + if parse == 'LEN': + return int(response) + elif parse == 'RESET': + return nativestr(response) == 'OK' + elif parse == 'GET': + return [{ + 'id': item[0], + 'start_time': int(item[1]), + 'duration': int(item[2]), + 'command': b(' ').join(item[3]) + } for item in response] + + class StrictRedis(object): """ Implementation of the Redis protocol. @@ -316,6 +331,7 @@ class StrictRedis(object): 'CONFIG': parse_config, 'DEBUG': parse_debug_object, 'HGETALL': lambda r: r and pairs_to_dict(r) or {}, + 'HSCAN': parse_hscan, 'INFO': parse_info, 'LASTSAVE': timestamp_to_datetime, 'OBJECT': parse_object, @@ -326,8 +342,8 @@ class StrictRedis(object): 'TIME': lambda x: (int(x[0]), int(x[1])), 'SENTINEL': parse_sentinel, 'SCAN': parse_scan, + 'SLOWLOG': parse_slowlog, 'SSCAN': parse_scan, - 'HSCAN': parse_hscan, 'ZSCAN': parse_zscan } ) @@ -621,6 +637,24 @@ class StrictRedis(object): return self.execute_command("SLAVEOF", "NO", "ONE") return self.execute_command("SLAVEOF", host, port) + def slowlog_get(self, num=None): + """ + Get the entries from the slowlog. If ``num`` is specified, get the + most recent ``num`` items. + """ + args = ['SLOWLOG', 'GET'] + if num is not None: + args.append(num) + return self.execute_command(*args, parse='GET') + + def slowlog_len(self): + "Get the number of items in the slowlog" + return self.execute_command('SLOWLOG', 'LEN', parse='LEN') + + def slowlog_reset(self): + "Remove all items in the slowlog" + return self.execute_command('SLOWLOG', 'RESET', parse='RESET') + def time(self): """ Returns the server time as a 2-item tuple of ints: diff --git a/tests/test_commands.py b/tests/test_commands.py index f030c6e..a8a242c 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -94,6 +94,38 @@ class TestRedisCommands(object): def test_ping(self, r): assert r.ping() + def test_slowlog_get(self, r): + assert r.slowlog_reset() + unicode_string = unichr(3456) + u('abcd') + unichr(3421) + r.get(unicode_string) + slowlog = r.slowlog_get() + assert isinstance(slowlog, list) + assert len(slowlog) == 2 + get_command = slowlog[0] + assert isinstance(get_command['start_time'], int) + assert isinstance(get_command['duration'], int) + assert get_command['command'] == \ + b(' ').join((b('GET'), unicode_string.encode('utf-8'))) + + slowlog_reset_command = slowlog[1] + assert isinstance(slowlog_reset_command['start_time'], int) + assert isinstance(slowlog_reset_command['duration'], int) + assert slowlog_reset_command['command'] == b('SLOWLOG RESET') + + def test_slowlog_get_limit(self, r): + assert r.slowlog_reset() + r.get('foo') + r.get('bar') + slowlog = r.slowlog_get(1) + assert isinstance(slowlog, list) + assert len(slowlog) == 1 + assert slowlog[0]['command'] == b('GET bar') + + def test_slowlog_length(self, r): + assert r.slowlog_reset() + r.get('foo') + assert r.slowlog_len() == 2 + @skip_if_server_version_lt('2.6.0') def test_time(self, r): t = r.time() |