diff --git a/src/latency.c b/src/latency.c index 582906edc13abdab3b856fdc7613b8fb18961919..bb05e8e719024e09a4357a0911759833d939c288 100644 --- a/src/latency.c +++ b/src/latency.c @@ -89,5 +89,49 @@ void latencyAddSample(char *event, mstime_t latency) { /* ---------------------- Latency command implementation -------------------- */ +/* latencyCommand() helper to produce a time-delay reply for all the samples + * in memory for the specified time series. */ +void latencyCommandReplyWithSamples(redisClient *c, struct latencyTimeSeries *ts) { + void *replylen = addDeferredMultiBulkLength(c); + int samples = 0, j; + + for (j = 0; j < LATENCY_TS_LEN; j++) { + int i = (ts->idx + j) % LATENCY_TS_LEN; + + if (ts->samples[i].time == 0) continue; + addReplyMultiBulkLen(c,2); + addReplyLongLong(c,ts->samples[i].time); + addReplyLongLong(c,ts->samples[i].latency); + samples++; + } + setDeferredMultiBulkLength(c,replylen,samples); +} + +/* LATENCY command implementations. + * + * LATENCY SAMPLES: return time-latency samples for the specified event. + * LATENCY LATEST: return the latest latency for all the events classes. + * LATENCY DOCTOR: returns an human readable analysis of instance latency. + * LATENCY GRAPH: provide an ASCII graph of the latency of the specified event. + */ void latencyCommand(redisClient *c) { + struct latencyTimeSeries *ts; + + if (!strcasecmp(c->argv[1]->ptr,"samples") && c->argc == 3) { + /* LATENCY SAMPLES */ + ts = dictFetchValue(server.latency_events,c->argv[2]->ptr); + if (ts == NULL) goto nodataerr; + latencyCommandReplyWithSamples(c,ts); + } else { + addReply(c,shared.syntaxerr); + return; + } + return; + +nodataerr: + /* Common error when the user asks for an event we have no latency + * information about. */ + addReplyErrorFormat(c, + "No samples available for event '%s'", c->argv[2]->ptr); } + diff --git a/src/redis.c b/src/redis.c index ac544095aea054a049e270cb834e83732ab985f0..159cb0b4be87a2988f246a1e9e33a02d0200b103 100644 --- a/src/redis.c +++ b/src/redis.c @@ -273,7 +273,8 @@ struct redisCommand redisCommandTable[] = { {"pfadd",pfaddCommand,-2,"wmF",0,NULL,1,1,1,0,0}, {"pfcount",pfcountCommand,-2,"w",0,NULL,1,1,1,0,0}, {"pfmerge",pfmergeCommand,-2,"wm",0,NULL,1,-1,1,0,0}, - {"pfdebug",pfdebugCommand,-3,"w",0,NULL,0,0,0,0,0} + {"pfdebug",pfdebugCommand,-3,"w",0,NULL,0,0,0,0,0}, + {"latency",latencyCommand,-2,"arslt",0,NULL,0,0,0,0,0} }; /*============================ Utility functions ============================ */ diff --git a/src/redis.h b/src/redis.h index 44e0bbe5914f78dad8563f516a12a0c3bbe9ac52..1f3e901e051c4a5d8a1c49b743624abfab8de704 100644 --- a/src/redis.h +++ b/src/redis.h @@ -1388,6 +1388,7 @@ void pfaddCommand(redisClient *c); void pfcountCommand(redisClient *c); void pfmergeCommand(redisClient *c); void pfdebugCommand(redisClient *c); +void latencyCommand(redisClient *c); #if defined(__GNUC__) void *calloc(size_t count, size_t size) __attribute__ ((deprecated));