diff --git a/src/server.c b/src/server.c index c08c095cb..ba93eb789 100644 --- a/src/server.c +++ b/src/server.c @@ -2214,7 +2214,7 @@ void call(client *c, int flags) { char *latency_event = (c->cmd->flags & CMD_FAST) ? "fast-command" : "command"; latencyAddSampleIfNeeded(latency_event,duration/1000); - slowlogPushEntryIfNeeded(c->argv,c->argc,duration); + slowlogPushEntryIfNeeded(c,c->argv,c->argc,duration); } if (flags & CMD_CALL_STATS) { c->lastcmd->microseconds += duration; diff --git a/src/slowlog.c b/src/slowlog.c index 484cf06bf..805ee1d77 100644 --- a/src/slowlog.c +++ b/src/slowlog.c @@ -45,7 +45,7 @@ /* 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 *slowlogCreateEntry(client *c, robj **argv, int argc, long long duration) { slowlogEntry *se = zmalloc(sizeof(*se)); int j, slargc = argc; @@ -81,6 +81,8 @@ slowlogEntry *slowlogCreateEntry(robj **argv, int argc, long long duration) { se->time = time(NULL); se->duration = duration; se->id = server.slowlog_entry_id++; + se->peerid = sdsnew(getClientPeerId(c)); + se->cname = c->name ? sdsnew(c->name->ptr) : sdsempty(); return se; } @@ -95,6 +97,8 @@ void slowlogFreeEntry(void *septr) { for (j = 0; j < se->argc; j++) decrRefCount(se->argv[j]); zfree(se->argv); + sdsfree(se->peerid); + sdsfree(se->cname); zfree(se); } @@ -109,10 +113,11 @@ void slowlogInit(void) { /* 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) { +void slowlogPushEntryIfNeeded(client *c, robj **argv, int argc, long long duration) { if (server.slowlog_log_slower_than < 0) return; /* Slowlog disabled */ if (duration >= server.slowlog_log_slower_than) - listAddNodeHead(server.slowlog,slowlogCreateEntry(argv,argc,duration)); + listAddNodeHead(server.slowlog, + slowlogCreateEntry(c,argv,argc,duration)); /* Remove old entries if needed. */ while (listLength(server.slowlog) > server.slowlog_max_len) @@ -152,13 +157,15 @@ void slowlogCommand(client *c) { int j; se = ln->value; - addReplyMultiBulkLen(c,4); + addReplyMultiBulkLen(c,6); addReplyLongLong(c,se->id); addReplyLongLong(c,se->time); addReplyLongLong(c,se->duration); addReplyMultiBulkLen(c,se->argc); for (j = 0; j < se->argc; j++) addReplyBulk(c,se->argv[j]); + addReplyBulkCBuffer(c,se->peerid,sdslen(se->peerid)); + addReplyBulkCBuffer(c,se->cname,sdslen(se->cname)); sent++; } setDeferredMultiBulkLength(c,totentries,sent); diff --git a/src/slowlog.h b/src/slowlog.h index 81df0b054..e3781c67b 100644 --- a/src/slowlog.h +++ b/src/slowlog.h @@ -37,11 +37,13 @@ typedef struct slowlogEntry { long long id; /* Unique entry identifier. */ long long duration; /* Time spent by the query, in nanoseconds. */ time_t time; /* Unix time at which the query was executed. */ + sds cname; /* Client name. */ + sds peerid; /* Client network address. */ } slowlogEntry; /* Exported API */ void slowlogInit(void); -void slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration); +void slowlogPushEntryIfNeeded(client *c, robj **argv, int argc, long long duration); /* Exported commands */ void slowlogCommand(client *c); diff --git a/tests/unit/slowlog.tcl b/tests/unit/slowlog.tcl index b25b91e2c..fce02498b 100644 --- a/tests/unit/slowlog.tcl +++ b/tests/unit/slowlog.tcl @@ -31,12 +31,14 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} { } {0} test {SLOWLOG - logged entry sanity check} { + r client setname foobar r debug sleep 0.2 set e [lindex [r slowlog get] 0] - assert_equal [llength $e] 4 + assert_equal [llength $e] 6 assert_equal [lindex $e 0] 105 assert_equal [expr {[lindex $e 2] > 100000}] 1 assert_equal [lindex $e 3] {debug sleep 0.2} + assert_equal {foobar} [lindex $e 5] } test {SLOWLOG - commands with too many arguments are trimmed} { @@ -67,4 +69,13 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} { set e [lindex [r slowlog get] 0] assert_equal [lindex $e 3] {debug sleep 0.2} } + + test {SLOWLOG - can clean older entires} { + r client setname lastentry_client + r config set slowlog-max-len 1 + r debug sleep 0.2 + assert {[llength [r slowlog get]] == 1} + set e [lindex [r slowlog get] 0] + assert_equal {lastentry_client} [lindex $e 5] + } }