]>
git.saurik.com Git - redis.git/blob - src/slowlog.c
4 /* Slowlog implements a system that is able to remember the latest N
5 * queries that took more than M microseconds to execute.
7 * The execution time to reach to be logged in the slow log is set
8 * using the 'slowlog-log-slower-than' config directive, that is also
9 * readable and writable using the CONFIG SET/GET command.
11 * The slow queries log is actually not "logged" in the Redis log file
12 * but is accessible thanks to the SLOWLOG command. */
14 /* Create a new slowlog entry.
15 * Incrementing the ref count of all the objects retained is up to
17 slowlogEntry
*slowlogCreateEntry(robj
**argv
, int argc
, long long duration
) {
18 slowlogEntry
*se
= zmalloc(sizeof(*se
));
21 if (slargc
> SLOWLOG_ENTRY_MAX_ARGC
) slargc
= SLOWLOG_ENTRY_MAX_ARGC
;
23 se
->argv
= zmalloc(sizeof(robj
*)*slargc
);
24 for (j
= 0; j
< slargc
; j
++) {
25 /* Logging too many arguments is a useless memory waste, so we stop
26 * at SLOWLOG_ENTRY_MAX_ARGC, but use the last argument to specify
27 * how many remaining arguments there were in the original command. */
28 if (slargc
!= argc
&& j
== slargc
-1) {
29 se
->argv
[j
] = createObject(REDIS_STRING
,
30 sdscatprintf(sdsempty(),"... (%d more arguments)",
33 /* Trim too long strings as well... */
34 if (argv
[j
]->type
== REDIS_STRING
&&
35 argv
[j
]->encoding
== REDIS_ENCODING_RAW
&&
36 sdslen(argv
[j
]->ptr
) > SLOWLOG_ENTRY_MAX_STRING
)
38 sds s
= sdsnewlen(argv
[j
]->ptr
, SLOWLOG_ENTRY_MAX_STRING
);
40 s
= sdscatprintf(s
,"... (%lu more bytes)",
42 sdslen(argv
[j
]->ptr
) - SLOWLOG_ENTRY_MAX_STRING
);
43 se
->argv
[j
] = createObject(REDIS_STRING
,s
);
45 se
->argv
[j
] = argv
[j
];
46 incrRefCount(argv
[j
]);
50 se
->time
= time(NULL
);
51 se
->duration
= duration
;
52 se
->id
= server
.slowlog_entry_id
++;
56 /* Free a slow log entry. The argument is void so that the prototype of this
57 * function matches the one of the 'free' method of adlist.c.
59 * This function will take care to release all the retained object. */
60 void slowlogFreeEntry(void *septr
) {
61 slowlogEntry
*se
= septr
;
64 for (j
= 0; j
< se
->argc
; j
++)
65 decrRefCount(se
->argv
[j
]);
70 /* Initialize the slow log. This function should be called a single time
71 * at server startup. */
72 void slowlogInit(void) {
73 server
.slowlog
= listCreate();
74 server
.slowlog_entry_id
= 0;
75 listSetFreeMethod(server
.slowlog
,slowlogFreeEntry
);
78 /* Push a new entry into the slow log.
79 * This function will make sure to trim the slow log accordingly to the
80 * configured max length. */
81 void slowlogPushEntryIfNeeded(robj
**argv
, int argc
, long long duration
) {
82 if (server
.slowlog_log_slower_than
< 0) return; /* Slowlog disabled */
83 if (duration
>= server
.slowlog_log_slower_than
)
84 listAddNodeHead(server
.slowlog
,slowlogCreateEntry(argv
,argc
,duration
));
86 /* Remove old entries if needed. */
87 while (listLength(server
.slowlog
) > server
.slowlog_max_len
)
88 listDelNode(server
.slowlog
,listLast(server
.slowlog
));
91 /* Remove all the entries from the current slow log. */
92 void slowlogReset(void) {
93 while (listLength(server
.slowlog
) > 0)
94 listDelNode(server
.slowlog
,listLast(server
.slowlog
));
97 /* The SLOWLOG command. Implements all the subcommands needed to handle the
99 void slowlogCommand(redisClient
*c
) {
100 if (c
->argc
== 2 && !strcasecmp(c
->argv
[1]->ptr
,"reset")) {
102 addReply(c
,shared
.ok
);
103 } else if (c
->argc
== 2 && !strcasecmp(c
->argv
[1]->ptr
,"len")) {
104 addReplyLongLong(c
,listLength(server
.slowlog
));
105 } else if ((c
->argc
== 2 || c
->argc
== 3) &&
106 !strcasecmp(c
->argv
[1]->ptr
,"get"))
108 long count
= 10, sent
= 0;
115 getLongFromObjectOrReply(c
,c
->argv
[2],&count
,NULL
) != REDIS_OK
)
118 listRewind(server
.slowlog
,&li
);
119 totentries
= addDeferredMultiBulkLength(c
);
120 while(count
-- && (ln
= listNext(&li
))) {
124 addReplyMultiBulkLen(c
,4);
125 addReplyLongLong(c
,se
->id
);
126 addReplyLongLong(c
,se
->time
);
127 addReplyLongLong(c
,se
->duration
);
128 addReplyMultiBulkLen(c
,se
->argc
);
129 for (j
= 0; j
< se
->argc
; j
++)
130 addReplyBulk(c
,se
->argv
[j
]);
133 setDeferredMultiBulkLength(c
,totentries
,sent
);
136 "Unknown SLOWLOG subcommand or wrong # of args. Try GET, RESET, LEN.");