diff options
author | antirez <antirez@gmail.com> | 2011-06-30 13:27:32 +0200 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2011-06-30 13:27:32 +0200 |
commit | daa70b179888121b92554103817443ad0ef32cd8 (patch) | |
tree | 33c755b9e53668e71cd5b6919c120d73baebce72 /src/slowlog.c | |
parent | ef67a2fc3c24d346efb1fa73b822e6a160229166 (diff) | |
download | redis-daa70b179888121b92554103817443ad0ef32cd8.tar.gz |
First implementation of the slow log feature
Diffstat (limited to 'src/slowlog.c')
-rw-r--r-- | src/slowlog.c | 111 |
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."); + } +} |