]> git.saurik.com Git - redis.git/blobdiff - src/slowlog.c
Test: fixed osx "leaks" support in test.
[redis.git] / src / slowlog.c
index ecaf65080838c794d6bfb110404412e58f5c77d6..fdc18e579dd2b2d3fe4cbe939fa90bc5a8393fbc 100644 (file)
@@ -1,6 +1,3 @@
-#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.
  *
@@ -9,23 +6,81 @@
  * 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. */
+ * but is accessible thanks to the SLOWLOG command.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Redis nor the names of its contributors may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "redis.h"
+#include "slowlog.h"
 
 /* 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;
+    int j, slargc = argc;
+
+    if (slargc > SLOWLOG_ENTRY_MAX_ARGC) slargc = SLOWLOG_ENTRY_MAX_ARGC;
+    se->argc = slargc;
+    se->argv = zmalloc(sizeof(robj*)*slargc);
+    for (j = 0; j < slargc; j++) {
+        /* Logging too many arguments is a useless memory waste, so we stop
+         * at SLOWLOG_ENTRY_MAX_ARGC, but use the last argument to specify
+         * how many remaining arguments there were in the original command. */
+        if (slargc != argc && j == slargc-1) {
+            se->argv[j] = createObject(REDIS_STRING,
+                sdscatprintf(sdsempty(),"... (%d more arguments)",
+                argc-slargc+1));
+        } else {
+            /* Trim too long strings as well... */
+            if (argv[j]->type == REDIS_STRING &&
+                argv[j]->encoding == REDIS_ENCODING_RAW &&
+                sdslen(argv[j]->ptr) > SLOWLOG_ENTRY_MAX_STRING)
+            {
+                sds s = sdsnewlen(argv[j]->ptr, SLOWLOG_ENTRY_MAX_STRING);
 
-    se->argc = argc;
-    se->argv = zmalloc(sizeof(robj*)*argc);
-    for (j = 0; j < argc; j++) {
-        se->argv[j] = argv[j];
-        incrRefCount(argv[j]);
+                s = sdscatprintf(s,"... (%lu more bytes)",
+                    (unsigned long)
+                    sdslen(argv[j]->ptr) - SLOWLOG_ENTRY_MAX_STRING);
+                se->argv[j] = createObject(REDIS_STRING,s);
+            } else {
+                se->argv[j] = argv[j];
+                incrRefCount(argv[j]);
+            }
+        }
     }
     se->time = time(NULL);
     se->duration = duration;
+    se->id = server.slowlog_entry_id++;
     return se;
 }
 
@@ -47,6 +102,7 @@ void slowlogFreeEntry(void *septr) {
  * at server startup. */
 void slowlogInit(void) {
     server.slowlog = listCreate();
+    server.slowlog_entry_id = 0;
     listSetFreeMethod(server.slowlog,slowlogFreeEntry);
 }
 
@@ -54,7 +110,8 @@ void slowlogInit(void) {
  * 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)
+    if (server.slowlog_log_slower_than < 0) return; /* Slowlog disabled */
+    if (duration >= server.slowlog_log_slower_than)
         listAddNodeHead(server.slowlog,slowlogCreateEntry(argv,argc,duration));
 
     /* Remove old entries if needed. */
@@ -95,7 +152,8 @@ void slowlogCommand(redisClient *c) {
             int j;
 
             se = ln->value;
-            addReplyMultiBulkLen(c,3);
+            addReplyMultiBulkLen(c,4);
+            addReplyLongLong(c,se->id);
             addReplyLongLong(c,se->time);
             addReplyLongLong(c,se->duration);
             addReplyMultiBulkLen(c,se->argc);