Skip to content

Commit

Permalink
add commandlog and its subcommands
Browse files Browse the repository at this point in the history
Signed-off-by: zhaozhao.zz <[email protected]>
  • Loading branch information
soloestoy committed Nov 12, 2024
1 parent 3aba75c commit 91dbd11
Show file tree
Hide file tree
Showing 8 changed files with 371 additions and 21 deletions.
107 changes: 86 additions & 21 deletions src/commandlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,33 @@ void commandlogReset(int type) {
while (listLength(server.commandlog[type].entries) > 0) listDelNode(server.commandlog[type].entries, listLast(server.commandlog[type].entries));
}

/* Reply command logs to client. */
void commandlogGetReply(client *c, int type, long count) {
listIter li;
listNode *ln;
commandlogEntry *ce;

if (count > (long)listLength(server.commandlog[type].entries)) {
count = listLength(server.commandlog[type].entries);
}
addReplyArrayLen(c, count);
listRewind(server.commandlog[type].entries, &li);
while (count--) {
int j;

ln = listNext(&li);
ce = ln->value;
addReplyArrayLen(c, 6);
addReplyLongLong(c, ce->id);
addReplyLongLong(c, ce->time);
addReplyLongLong(c, ce->value);
addReplyArrayLen(c, ce->argc);
for (j = 0; j < ce->argc; j++) addReplyBulk(c, ce->argv[j]);
addReplyBulkCBuffer(c, ce->peerid, sdslen(ce->peerid));
addReplyBulkCBuffer(c, ce->cname, sdslen(ce->cname));
}
}

/* The SLOWLOG command. Implements all the subcommands needed to handle the
* slow log. */
void slowlogCommand(client *c) {
Expand All @@ -158,9 +185,6 @@ void slowlogCommand(client *c) {
addReplyLongLong(c, listLength(server.commandlog[COMMANDLOG_TYPE_SLOW].entries));
} else if ((c->argc == 2 || c->argc == 3) && !strcasecmp(c->argv[1]->ptr, "get")) {
long count = 10;
listIter li;
listNode *ln;
commandlogEntry *ce;

if (c->argc == 3) {
/* Consume count arg. */
Expand All @@ -175,25 +199,66 @@ void slowlogCommand(client *c) {
}
}

if (count > (long)listLength(server.commandlog[COMMANDLOG_TYPE_SLOW].entries)) {
count = listLength(server.commandlog[COMMANDLOG_TYPE_SLOW].entries);
}
addReplyArrayLen(c, count);
listRewind(server.commandlog[COMMANDLOG_TYPE_SLOW].entries, &li);
while (count--) {
int j;

ln = listNext(&li);
ce = ln->value;
addReplyArrayLen(c, 6);
addReplyLongLong(c, ce->id);
addReplyLongLong(c, ce->time);
addReplyLongLong(c, ce->value);
addReplyArrayLen(c, ce->argc);
for (j = 0; j < ce->argc; j++) addReplyBulk(c, ce->argv[j]);
addReplyBulkCBuffer(c, ce->peerid, sdslen(ce->peerid));
addReplyBulkCBuffer(c, ce->cname, sdslen(ce->cname));
commandlogGetReply(c, COMMANDLOG_TYPE_SLOW, count);
} else {
addReplySubcommandSyntaxError(c);
}
}

int commandlogGetTypeOrReply(client *c, robj *o) {
if (!strcasecmp(o->ptr, "slow")) return COMMANDLOG_TYPE_SLOW;
if (!strcasecmp(o->ptr, "heavytraffic-input")) return COMMANDLOG_TYPE_HEAVYTRAFFIC_INPUT;
if (!strcasecmp(o->ptr, "heavytraffic-output")) return COMMANDLOG_TYPE_HEAVYTRAFFIC_OUTPUT;
addReplyError(c, "type should be one of the following: slow, heavytraffic-input, heavytraffic-output");
return -1;
}

/* The COMMANDLOG command. Implements all the subcommands needed to handle the
* command log. */
void commandlogCommand(client *c) {
int type;
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr, "help")) {
const char *help[] = {
"GET <count> <type>",
" Return top <count> entries of the specified <type> from the commandlog (-1 mean all).",
" Entries are made of:",
" id, timestamp,",
" time in microseconds for type of slow,",
" or size in bytes for type of heavytraffic-input,",
" or size in bytes for type of heavytraffic-output",
" arguments array, client IP and port,",
" client name",
"LEN <type>",
" Return the length of the specified type of commandlog.",
"RESET <type>",
" Reset the specified type of commandlog.",
NULL,
};
addReplyHelp(c, help);
} else if (c->argc == 3 && !strcasecmp(c->argv[1]->ptr, "reset")) {
if ((type = commandlogGetTypeOrReply(c, c->argv[2])) == -1) return;
commandlogReset(type);
addReply(c, shared.ok);
} else if (c->argc == 3 && !strcasecmp(c->argv[1]->ptr, "len")) {
if ((type = commandlogGetTypeOrReply(c, c->argv[2])) == -1) return;
addReplyLongLong(c, listLength(server.commandlog[type].entries));
} else if (c->argc == 4 && !strcasecmp(c->argv[1]->ptr, "get")) {
long count;

/* Consume count arg. */
if (getRangeLongFromObjectOrReply(c, c->argv[2], -1, LONG_MAX, &count,
"count should be greater than or equal to -1") != C_OK)
return;

if (count == -1) {
/* We treat -1 as a special value, which means to get all command logs.
* Simply set count to the length of server.commandlog. */
count = listLength(server.commandlog[type].entries);
}

if ((type = commandlogGetTypeOrReply(c, c->argv[3])) == -1) return;

commandlogGetReply(c, type, count);
} else {
addReplySubcommandSyntaxError(c);
}
Expand Down
121 changes: 121 additions & 0 deletions src/commands.def
Original file line number Diff line number Diff line change
Expand Up @@ -6618,6 +6618,126 @@ const char *COMMAND_Tips[] = {
#define COMMAND_Keyspecs NULL
#endif

/********** COMMANDLOG GET ********************/

#ifndef SKIP_CMD_HISTORY_TABLE
/* COMMANDLOG GET history */
#define COMMANDLOG_GET_History NULL
#endif

#ifndef SKIP_CMD_TIPS_TABLE
/* COMMANDLOG GET tips */
const char *COMMANDLOG_GET_Tips[] = {
"request_policy:all_nodes",
"nondeterministic_output",
};
#endif

#ifndef SKIP_CMD_KEY_SPECS_TABLE
/* COMMANDLOG GET key specs */
#define COMMANDLOG_GET_Keyspecs NULL
#endif

/* COMMANDLOG GET argument table */
struct COMMAND_ARG COMMANDLOG_GET_Args[] = {
{MAKE_ARG("count",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
{MAKE_ARG("type",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
};

/********** COMMANDLOG HELP ********************/

#ifndef SKIP_CMD_HISTORY_TABLE
/* COMMANDLOG HELP history */
#define COMMANDLOG_HELP_History NULL
#endif

#ifndef SKIP_CMD_TIPS_TABLE
/* COMMANDLOG HELP tips */
#define COMMANDLOG_HELP_Tips NULL
#endif

#ifndef SKIP_CMD_KEY_SPECS_TABLE
/* COMMANDLOG HELP key specs */
#define COMMANDLOG_HELP_Keyspecs NULL
#endif

/********** COMMANDLOG LEN ********************/

#ifndef SKIP_CMD_HISTORY_TABLE
/* COMMANDLOG LEN history */
#define COMMANDLOG_LEN_History NULL
#endif

#ifndef SKIP_CMD_TIPS_TABLE
/* COMMANDLOG LEN tips */
const char *COMMANDLOG_LEN_Tips[] = {
"request_policy:all_nodes",
"response_policy:agg_sum",
"nondeterministic_output",
};
#endif

#ifndef SKIP_CMD_KEY_SPECS_TABLE
/* COMMANDLOG LEN key specs */
#define COMMANDLOG_LEN_Keyspecs NULL
#endif

/* COMMANDLOG LEN argument table */
struct COMMAND_ARG COMMANDLOG_LEN_Args[] = {
{MAKE_ARG("type",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
};

/********** COMMANDLOG RESET ********************/

#ifndef SKIP_CMD_HISTORY_TABLE
/* COMMANDLOG RESET history */
#define COMMANDLOG_RESET_History NULL
#endif

#ifndef SKIP_CMD_TIPS_TABLE
/* COMMANDLOG RESET tips */
const char *COMMANDLOG_RESET_Tips[] = {
"request_policy:all_nodes",
"response_policy:all_succeeded",
};
#endif

#ifndef SKIP_CMD_KEY_SPECS_TABLE
/* COMMANDLOG RESET key specs */
#define COMMANDLOG_RESET_Keyspecs NULL
#endif

/* COMMANDLOG RESET argument table */
struct COMMAND_ARG COMMANDLOG_RESET_Args[] = {
{MAKE_ARG("type",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
};

/* COMMANDLOG command table */
struct COMMAND_STRUCT COMMANDLOG_Subcommands[] = {
{MAKE_CMD("get","Returns the specified command log's entries.","O(N) where N is the number of entries returned","8.2.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,COMMANDLOG_GET_History,0,COMMANDLOG_GET_Tips,2,commandlogCommand,4,CMD_ADMIN|CMD_LOADING|CMD_STALE,0,COMMANDLOG_GET_Keyspecs,0,NULL,2),.args=COMMANDLOG_GET_Args},
{MAKE_CMD("help","Show helpful text about the different subcommands","O(1)","8.2.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,COMMANDLOG_HELP_History,0,COMMANDLOG_HELP_Tips,0,commandlogCommand,2,CMD_LOADING|CMD_STALE,0,COMMANDLOG_HELP_Keyspecs,0,NULL,0)},
{MAKE_CMD("len","Returns the number of entries in the specified type of command log.","O(1)","8.2.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,COMMANDLOG_LEN_History,0,COMMANDLOG_LEN_Tips,3,commandlogCommand,3,CMD_ADMIN|CMD_LOADING|CMD_STALE,0,COMMANDLOG_LEN_Keyspecs,0,NULL,1),.args=COMMANDLOG_LEN_Args},
{MAKE_CMD("reset","Clears all entries from the specified type of command log.","O(N) where N is the number of entries in the commandlog","8.2.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,COMMANDLOG_RESET_History,0,COMMANDLOG_RESET_Tips,2,commandlogCommand,3,CMD_ADMIN|CMD_LOADING|CMD_STALE,0,COMMANDLOG_RESET_Keyspecs,0,NULL,1),.args=COMMANDLOG_RESET_Args},
{0}
};

/********** COMMANDLOG ********************/

#ifndef SKIP_CMD_HISTORY_TABLE
/* COMMANDLOG history */
#define COMMANDLOG_History NULL
#endif

#ifndef SKIP_CMD_TIPS_TABLE
/* COMMANDLOG tips */
#define COMMANDLOG_Tips NULL
#endif

#ifndef SKIP_CMD_KEY_SPECS_TABLE
/* COMMANDLOG key specs */
#define COMMANDLOG_Keyspecs NULL
#endif

/********** CONFIG GET ********************/

#ifndef SKIP_CMD_HISTORY_TABLE
Expand Down Expand Up @@ -10991,6 +11111,7 @@ struct COMMAND_STRUCT serverCommandTable[] = {
{MAKE_CMD("bgrewriteaof","Asynchronously rewrites the append-only file to disk.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,BGREWRITEAOF_History,0,BGREWRITEAOF_Tips,0,bgrewriteaofCommand,1,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT,0,BGREWRITEAOF_Keyspecs,0,NULL,0)},
{MAKE_CMD("bgsave","Asynchronously saves the database(s) to disk.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,BGSAVE_History,1,BGSAVE_Tips,0,bgsaveCommand,-1,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_NOSCRIPT,0,BGSAVE_Keyspecs,0,NULL,1),.args=BGSAVE_Args},
{MAKE_CMD("command","Returns detailed information about all commands.","O(N) where N is the total number of commands","2.8.13",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,COMMAND_History,0,COMMAND_Tips,1,commandCommand,-1,CMD_LOADING|CMD_STALE|CMD_SENTINEL,ACL_CATEGORY_CONNECTION,COMMAND_Keyspecs,0,NULL,0),.subcommands=COMMAND_Subcommands},
{MAKE_CMD("commandlog","A container for command log commands.","Depends on subcommand.","8.2.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,COMMANDLOG_History,0,COMMANDLOG_Tips,0,NULL,-2,0,0,COMMANDLOG_Keyspecs,0,NULL,0),.subcommands=COMMANDLOG_Subcommands},
{MAKE_CMD("config","A container for server configuration commands.","Depends on subcommand.","2.0.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,CONFIG_History,0,CONFIG_Tips,0,NULL,-2,0,0,CONFIG_Keyspecs,0,NULL,0),.subcommands=CONFIG_Subcommands},
{MAKE_CMD("dbsize","Returns the number of keys in the database.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"server",COMMAND_GROUP_SERVER,DBSIZE_History,0,DBSIZE_Tips,2,dbsizeCommand,1,CMD_READONLY|CMD_FAST,ACL_CATEGORY_KEYSPACE,DBSIZE_Keyspecs,0,NULL,0)},
{MAKE_CMD("debug","A container for debugging commands.","Depends on subcommand.","1.0.0",CMD_DOC_SYSCMD,NULL,NULL,"server",COMMAND_GROUP_SERVER,DEBUG_History,0,DEBUG_Tips,0,debugCommand,-2,CMD_ADMIN|CMD_NOSCRIPT|CMD_LOADING|CMD_STALE|CMD_PROTECTED,0,DEBUG_Keyspecs,0,NULL,0)},
Expand Down
71 changes: 71 additions & 0 deletions src/commands/commandlog-get.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"GET": {
"summary": "Returns the specified command log's entries.",
"complexity": "O(N) where N is the number of entries returned",
"group": "server",
"since": "8.2.0",
"arity": 4,
"container": "COMMANDLOG",
"function": "commandlogCommand",
"command_flags": [
"ADMIN",
"LOADING",
"STALE"
],
"command_tips": [
"REQUEST_POLICY:ALL_NODES",
"NONDETERMINISTIC_OUTPUT"
],
"reply_schema": {
"type": "array",
"description": "Entries from the command log in chronological order.",
"uniqueItems": true,
"items": {
"type": "array",
"minItems": 6,
"maxItems": 6,
"items": [
{
"type": "integer",
"description": "Command log entry ID."
},
{
"type": "integer",
"description": "The unix timestamp at which the logged command was processed.",
"minimum": 0
},
{
"type": "integer",
"description": "Determined by the type parameter.",
"minimum": 0
},
{
"type": "array",
"description": "The arguments of the command.",
"items": {
"type": "string"
}
},
{
"type": "string",
"description": "Client IP address and port."
},
{
"type": "string",
"description": "Client name if set via the CLIENT SETNAME command."
}
]
}
},
"arguments": [
{
"name": "count",
"type": "integer"
},
{
"name": "type",
"type": "string"
}
]
}
}
22 changes: 22 additions & 0 deletions src/commands/commandlog-help.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"HELP": {
"summary": "Show helpful text about the different subcommands",
"complexity": "O(1)",
"group": "server",
"since": "8.2.0",
"arity": 2,
"container": "COMMANDLOG",
"function": "commandlogCommand",
"command_flags": [
"LOADING",
"STALE"
],
"reply_schema": {
"type": "array",
"description": "Helpful text about subcommands.",
"items": {
"type": "string"
}
}
}
}
32 changes: 32 additions & 0 deletions src/commands/commandlog-len.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"LEN": {
"summary": "Returns the number of entries in the specified type of command log.",
"complexity": "O(1)",
"group": "server",
"since": "8.2.0",
"arity": 3,
"container": "COMMANDLOG",
"function": "commandlogCommand",
"command_flags": [
"ADMIN",
"LOADING",
"STALE"
],
"command_tips": [
"REQUEST_POLICY:ALL_NODES",
"RESPONSE_POLICY:AGG_SUM",
"NONDETERMINISTIC_OUTPUT"
],
"reply_schema": {
"type": "integer",
"description": "Number of entries in the command log.",
"minimum": 0
},
"arguments": [
{
"name": "type",
"type": "string"
}
]
}
}
Loading

0 comments on commit 91dbd11

Please sign in to comment.