summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES1
-rw-r--r--redis/_compat.py2
-rw-r--r--redis/client.py36
-rw-r--r--tests/test_commands.py32
4 files changed, 69 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 935b0d6..5569ddf 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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()