summaryrefslogtreecommitdiff
path: root/src/slowlog.c
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2011-06-30 13:27:32 +0200
committerantirez <antirez@gmail.com>2011-06-30 13:27:32 +0200
commitdaa70b179888121b92554103817443ad0ef32cd8 (patch)
tree33c755b9e53668e71cd5b6919c120d73baebce72 /src/slowlog.c
parentef67a2fc3c24d346efb1fa73b822e6a160229166 (diff)
downloadredis-daa70b179888121b92554103817443ad0ef32cd8.tar.gz
First implementation of the slow log feature
Diffstat (limited to 'src/slowlog.c')
-rw-r--r--src/slowlog.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/slowlog.c b/src/slowlog.c
new file mode 100644
index 000000000..ecaf65080
--- /dev/null
+++ b/src/slowlog.c
@@ -0,0 +1,111 @@
+#include "redis.h"
+#include "slowlog.h"
+
+/* Slowlog implements a system that is able to remember the latest N
+ * queries that took more than M microseconds to execute.
+ *
+ * The execution time to reach to be logged in the slow log is set
+ * using the 'slowlog-log-slower-than' config directive, that is also
+ * readable and writable using the CONFIG SET/GET command.
+ *
+ * The slow queries log is actually not "logged" in the Redis log file
+ * but is accessible thanks to the SLOWLOG command. */
+
+/* Create a new slowlog entry.
+ * Incrementing the ref count of all the objects retained is up to
+ * this function. */
+slowlogEntry *slowlogCreateEntry(robj **argv, int argc, long long duration) {
+ slowlogEntry *se = zmalloc(sizeof(*se));
+ int j;
+
+ se->argc = argc;
+ se->argv = zmalloc(sizeof(robj*)*argc);
+ for (j = 0; j < argc; j++) {
+ se->argv[j] = argv[j];
+ incrRefCount(argv[j]);
+ }
+ se->time = time(NULL);
+ se->duration = duration;
+ return se;
+}
+
+/* Free a slow log entry. The argument is void so that the prototype of this
+ * function matches the one of the 'free' method of adlist.c.
+ *
+ * This function will take care to release all the retained object. */
+void slowlogFreeEntry(void *septr) {
+ slowlogEntry *se = septr;
+ int j;
+
+ for (j = 0; j < se->argc; j++)
+ decrRefCount(se->argv[j]);
+ zfree(se->argv);
+ zfree(se);
+}
+
+/* Initialize the slow log. This function should be called a single time
+ * at server startup. */
+void slowlogInit(void) {
+ server.slowlog = listCreate();
+ listSetFreeMethod(server.slowlog,slowlogFreeEntry);
+}
+
+/* Push a new entry into the slow log.
+ * This function will make sure to trim the slow log accordingly to the
+ * configured max length. */
+void slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration) {
+ if (duration > server.slowlog_log_slower_than)
+ listAddNodeHead(server.slowlog,slowlogCreateEntry(argv,argc,duration));
+
+ /* Remove old entries if needed. */
+ while (listLength(server.slowlog) > server.slowlog_max_len)
+ listDelNode(server.slowlog,listLast(server.slowlog));
+}
+
+/* Remove all the entries from the current slow log. */
+void slowlogReset(void) {
+ while (listLength(server.slowlog) > 0)
+ listDelNode(server.slowlog,listLast(server.slowlog));
+}
+
+/* The SLOWLOG command. Implements all the subcommands needed to handle the
+ * Redis slow log. */
+void slowlogCommand(redisClient *c) {
+ if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"reset")) {
+ slowlogReset();
+ addReply(c,shared.ok);
+ } else if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"len")) {
+ addReplyLongLong(c,listLength(server.slowlog));
+ } else if ((c->argc == 2 || c->argc == 3) &&
+ !strcasecmp(c->argv[1]->ptr,"get"))
+ {
+ long count = 10, sent = 0;
+ listIter li;
+ void *totentries;
+ listNode *ln;
+ slowlogEntry *se;
+
+ if (c->argc == 3 &&
+ getLongFromObjectOrReply(c,c->argv[2],&count,NULL) != REDIS_OK)
+ return;
+
+ listRewind(server.slowlog,&li);
+ totentries = addDeferredMultiBulkLength(c);
+ while(count-- && (ln = listNext(&li))) {
+ int j;
+
+ se = ln->value;
+ addReplyMultiBulkLen(c,3);
+ addReplyLongLong(c,se->time);
+ addReplyLongLong(c,se->duration);
+ addReplyMultiBulkLen(c,se->argc);
+ for (j = 0; j < se->argc; j++)
+ addReplyBulk(c,se->argv[j]);
+ sent++;
+ }
+ setDeferredMultiBulkLength(c,totentries,sent);
+ } else {
+ addReplyError(c,
+ "Unknown SLOWLOG subcommand or wrong # of args. Try GET, RESET, LEN.");
+ }
+}