Commit 1b085c9f authored by antirez's avatar antirez
Browse files

INFO output refactoring. Now "INFO section" will report only the specified section

parent d9cb288c
...@@ -174,7 +174,7 @@ struct redisCommand readonlyCommandTable[] = { ...@@ -174,7 +174,7 @@ struct redisCommand readonlyCommandTable[] = {
{"flushdb",flushdbCommand,1,0,NULL,0,0,0,0}, {"flushdb",flushdbCommand,1,0,NULL,0,0,0,0},
{"flushall",flushallCommand,1,0,NULL,0,0,0,0}, {"flushall",flushallCommand,1,0,NULL,0,0,0,0},
{"sort",sortCommand,-2,REDIS_CMD_DENYOOM,NULL,1,1,1,0}, {"sort",sortCommand,-2,REDIS_CMD_DENYOOM,NULL,1,1,1,0},
{"info",infoCommand,1,0,NULL,0,0,0,0}, {"info",infoCommand,-1,0,NULL,0,0,0,0},
{"monitor",monitorCommand,1,0,NULL,0,0,0,0}, {"monitor",monitorCommand,1,0,NULL,0,0,0,0},
{"ttl",ttlCommand,2,0,NULL,1,1,1,0}, {"ttl",ttlCommand,2,0,NULL,1,1,1,0},
{"persist",persistCommand,2,0,NULL,1,1,1,0}, {"persist",persistCommand,2,0,NULL,1,1,1,0},
...@@ -1156,106 +1156,199 @@ void bytesToHuman(char *s, unsigned long long n) { ...@@ -1156,106 +1156,199 @@ void bytesToHuman(char *s, unsigned long long n) {
/* Create the string returned by the INFO command. This is decoupled /* Create the string returned by the INFO command. This is decoupled
* by the INFO command itself as we need to report the same information * by the INFO command itself as we need to report the same information
* on memory corruption problems. */ * on memory corruption problems. */
sds genRedisInfoString(void) { sds genRedisInfoString(char *section) {
sds info; sds info = sdsempty();
time_t uptime = time(NULL)-server.stat_starttime; time_t uptime = time(NULL)-server.stat_starttime;
int j, numcommands; int j, numcommands;
char hmem[64]; char hmem[64];
struct rusage self_ru, c_ru; struct rusage self_ru, c_ru;
unsigned long lol, bib; unsigned long lol, bib;
int allsections = 0, defsections = 0;
int sections = 0;
if (section) {
allsections = strcasecmp(section,"all") == 0;
allsections = strcasecmp(section,"default") == 0;
}
getrusage(RUSAGE_SELF, &self_ru); getrusage(RUSAGE_SELF, &self_ru);
getrusage(RUSAGE_CHILDREN, &c_ru); getrusage(RUSAGE_CHILDREN, &c_ru);
getClientsMaxBuffers(&lol,&bib); getClientsMaxBuffers(&lol,&bib);
bytesToHuman(hmem,zmalloc_used_memory()); bytesToHuman(hmem,zmalloc_used_memory());
info = sdscatprintf(sdsempty(),
/* Server */
if (allsections || defsections || !strcasecmp(section,"server")) {
if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info,
"# Server\r\n"
"redis_version:%s\r\n" "redis_version:%s\r\n"
"redis_git_sha1:%s\r\n" "redis_git_sha1:%s\r\n"
"redis_git_dirty:%d\r\n" "redis_git_dirty:%d\r\n"
"arch_bits:%s\r\n" "arch_bits:%s\r\n"
"multiplexing_api:%s\r\n" "multiplexing_api:%s\r\n"
"process_id:%ld\r\n" "process_id:%ld\r\n"
"tcp_port:%d\r\n"
"uptime_in_seconds:%ld\r\n" "uptime_in_seconds:%ld\r\n"
"uptime_in_days:%ld\r\n" "uptime_in_days:%ld\r\n"
"lru_clock:%ld\r\n" "lru_clock:%ld\r\n",
"used_cpu_sys:%.2f\r\n" REDIS_VERSION,
"used_cpu_user:%.2f\r\n" redisGitSHA1(),
"used_cpu_sys_childrens:%.2f\r\n" strtol(redisGitDirty(),NULL,10) > 0,
"used_cpu_user_childrens:%.2f\r\n" (sizeof(long) == 8) ? "64" : "32",
aeGetApiName(),
(long) getpid(),
server.port,
uptime,
uptime/(3600*24),
(unsigned long) server.lruclock);
}
/* Clients */
if (allsections || defsections || !strcasecmp(section,"clients")) {
if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info,
"# Clients\r\n"
"connected_clients:%d\r\n" "connected_clients:%d\r\n"
"connected_slaves:%d\r\n"
"client_longest_output_list:%lu\r\n" "client_longest_output_list:%lu\r\n"
"client_biggest_input_buf:%lu\r\n" "client_biggest_input_buf:%lu\r\n"
"blocked_clients:%d\r\n" "blocked_clients:%d\r\n",
listLength(server.clients)-listLength(server.slaves),
lol, bib,
server.bpop_blocked_clients);
}
/* Memory */
if (allsections || defsections || !strcasecmp(section,"memory")) {
if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info,
"# Memory\r\n"
"used_memory:%zu\r\n" "used_memory:%zu\r\n"
"used_memory_human:%s\r\n" "used_memory_human:%s\r\n"
"used_memory_rss:%zu\r\n" "used_memory_rss:%zu\r\n"
"mem_fragmentation_ratio:%.2f\r\n" "mem_fragmentation_ratio:%.2f\r\n"
"use_tcmalloc:%d\r\n" "use_tcmalloc:%d\r\n",
zmalloc_used_memory(),
hmem,
zmalloc_get_rss(),
zmalloc_get_fragmentation_ratio(),
#ifdef USE_TCMALLOC
1
#else
0
#endif
);
info = sdscat(info,"allocation_stats:");
for (j = 0; j <= ZMALLOC_MAX_ALLOC_STAT; j++) {
size_t count = zmalloc_allocations_for_size(j);
if (count) {
if (info[sdslen(info)-1] != ':') info = sdscatlen(info,",",1);
info = sdscatprintf(info,"%s%d=%zu",
(j == ZMALLOC_MAX_ALLOC_STAT) ? ">=" : "",
j,count);
}
}
}
/* Persistence */
if (allsections || defsections || !strcasecmp(section,"persistence")) {
if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info,
"# Persistence\r\n"
"loading:%d\r\n" "loading:%d\r\n"
"aof_enabled:%d\r\n" "aof_enabled:%d\r\n"
"changes_since_last_save:%lld\r\n" "changes_since_last_save:%lld\r\n"
"bgsave_in_progress:%d\r\n" "bgsave_in_progress:%d\r\n"
"last_save_time:%ld\r\n" "last_save_time:%ld\r\n"
"bgrewriteaof_in_progress:%d\r\n" "bgrewriteaof_in_progress:%d\r\n",
server.loading,
server.appendonly,
server.dirty,
server.bgsavechildpid != -1 ||
server.bgsavethread != (pthread_t) -1,
server.lastsave,
server.bgrewritechildpid != -1);
if (server.loading) {
double perc;
time_t eta, elapsed;
off_t remaining_bytes = server.loading_total_bytes-
server.loading_loaded_bytes;
perc = ((double)server.loading_loaded_bytes /
server.loading_total_bytes) * 100;
elapsed = time(NULL)-server.loading_start_time;
if (elapsed == 0) {
eta = 1; /* A fake 1 second figure if we don't have
enough info */
} else {
eta = (elapsed*remaining_bytes)/server.loading_loaded_bytes;
}
info = sdscatprintf(info,
"loading_start_time:%ld\r\n"
"loading_total_bytes:%llu\r\n"
"loading_loaded_bytes:%llu\r\n"
"loading_loaded_perc:%.2f\r\n"
"loading_eta_seconds:%ld\r\n"
,(unsigned long) server.loading_start_time,
(unsigned long long) server.loading_total_bytes,
(unsigned long long) server.loading_loaded_bytes,
perc,
eta
);
}
}
/* Diskstore */
if (allsections || defsections || !strcasecmp(section,"diskstore")) {
if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info,
"# Diskstore\r\n"
"ds_enabled:%d\r\n",
server.ds_enabled != 0);
if (server.ds_enabled) {
lockThreadedIO();
info = sdscatprintf(info,
"cache_max_memory:%llu\r\n"
"cache_blocked_clients:%lu\r\n"
,(unsigned long long) server.cache_max_memory,
(unsigned long) server.cache_blocked_clients
);
unlockThreadedIO();
}
}
/* Stats */
if (allsections || defsections || !strcasecmp(section,"stats")) {
if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info,
"# Stats\r\n"
"total_connections_received:%lld\r\n" "total_connections_received:%lld\r\n"
"total_commands_processed:%lld\r\n" "total_commands_processed:%lld\r\n"
"expired_keys:%lld\r\n" "expired_keys:%lld\r\n"
"evicted_keys:%lld\r\n" "evicted_keys:%lld\r\n"
"keyspace_hits:%lld\r\n" "keyspace_hits:%lld\r\n"
"keyspace_misses:%lld\r\n" "keyspace_misses:%lld\r\n"
"hash_max_zipmap_entries:%zu\r\n"
"hash_max_zipmap_value:%zu\r\n"
"pubsub_channels:%ld\r\n" "pubsub_channels:%ld\r\n"
"pubsub_patterns:%u\r\n" "pubsub_patterns:%u\r\n",
"ds_enabled:%d\r\n"
"role:%s\r\n"
,REDIS_VERSION,
redisGitSHA1(),
strtol(redisGitDirty(),NULL,10) > 0,
(sizeof(long) == 8) ? "64" : "32",
aeGetApiName(),
(long) getpid(),
uptime,
uptime/(3600*24),
(unsigned long) server.lruclock,
(float)self_ru.ru_utime.tv_sec+(float)self_ru.ru_utime.tv_usec/1000000,
(float)self_ru.ru_stime.tv_sec+(float)self_ru.ru_stime.tv_usec/1000000,
(float)c_ru.ru_utime.tv_sec+(float)c_ru.ru_utime.tv_usec/1000000,
(float)c_ru.ru_stime.tv_sec+(float)c_ru.ru_stime.tv_usec/1000000,
listLength(server.clients)-listLength(server.slaves),
listLength(server.slaves),
lol, bib,
server.bpop_blocked_clients,
zmalloc_used_memory(),
hmem,
zmalloc_get_rss(),
zmalloc_get_fragmentation_ratio(),
#ifdef USE_TCMALLOC
1,
#else
0,
#endif
server.loading,
server.appendonly,
server.dirty,
server.bgsavechildpid != -1 || server.bgsavethread != (pthread_t) -1,
server.lastsave,
server.bgrewritechildpid != -1,
server.stat_numconnections, server.stat_numconnections,
server.stat_numcommands, server.stat_numcommands,
server.stat_expiredkeys, server.stat_expiredkeys,
server.stat_evictedkeys, server.stat_evictedkeys,
server.stat_keyspace_hits, server.stat_keyspace_hits,
server.stat_keyspace_misses, server.stat_keyspace_misses,
server.hash_max_zipmap_entries,
server.hash_max_zipmap_value,
dictSize(server.pubsub_channels), dictSize(server.pubsub_channels),
listLength(server.pubsub_patterns), listLength(server.pubsub_patterns));
server.ds_enabled != 0, }
server.masterhost == NULL ? "master" : "slave"
); /* Replication */
if (allsections || defsections || !strcasecmp(section,"replication")) {
if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info,
"# Replication\r\n"
"role:%s\r\n",
server.masterhost == NULL ? "master" : "slave");
if (server.masterhost) { if (server.masterhost) {
info = sdscatprintf(info, info = sdscatprintf(info,
"master_host:%s\r\n" "master_host:%s\r\n"
...@@ -1267,7 +1360,8 @@ sds genRedisInfoString(void) { ...@@ -1267,7 +1360,8 @@ sds genRedisInfoString(void) {
server.masterport, server.masterport,
(server.replstate == REDIS_REPL_CONNECTED) ? (server.replstate == REDIS_REPL_CONNECTED) ?
"up" : "down", "up" : "down",
server.master ? ((int)(time(NULL)-server.master->lastinteraction)) : -1, server.master ?
((int)(time(NULL)-server.master->lastinteraction)) : -1,
server.replstate == REDIS_REPL_TRANSFER server.replstate == REDIS_REPL_TRANSFER
); );
...@@ -1280,65 +1374,37 @@ sds genRedisInfoString(void) { ...@@ -1280,65 +1374,37 @@ sds genRedisInfoString(void) {
); );
} }
} }
if (server.ds_enabled) {
lockThreadedIO();
info = sdscatprintf(info, info = sdscatprintf(info,
"cache_max_memory:%llu\r\n" "connected_slaves:%d\r\n",
"cache_blocked_clients:%lu\r\n" listLength(server.slaves));
,(unsigned long long) server.cache_max_memory,
(unsigned long) server.cache_blocked_clients
);
unlockThreadedIO();
}
if (server.loading) {
double perc;
time_t eta, elapsed;
off_t remaining_bytes = server.loading_total_bytes-
server.loading_loaded_bytes;
perc = ((double)server.loading_loaded_bytes /
server.loading_total_bytes) * 100;
elapsed = time(NULL)-server.loading_start_time;
if (elapsed == 0) {
eta = 1; /* A fake 1 second figure if we don't have enough info */
} else {
eta = (elapsed*remaining_bytes)/server.loading_loaded_bytes;
} }
/* Profiling */
if (allsections || defsections || !strcasecmp(section,"profiling")) {
if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info, info = sdscatprintf(info,
"loading_start_time:%ld\r\n" "# Profiling\r\n"
"loading_total_bytes:%llu\r\n" "used_cpu_sys:%.2f\r\n"
"loading_loaded_bytes:%llu\r\n" "used_cpu_user:%.2f\r\n"
"loading_loaded_perc:%.2f\r\n" "used_cpu_sys_childrens:%.2f\r\n"
"loading_eta_seconds:%ld\r\n" "used_cpu_user_childrens:%.2f\r\n",
,(unsigned long) server.loading_start_time, (float)self_ru.ru_utime.tv_sec+(float)self_ru.ru_utime.tv_usec/1000000,
(unsigned long long) server.loading_total_bytes, (float)self_ru.ru_stime.tv_sec+(float)self_ru.ru_stime.tv_usec/1000000,
(unsigned long long) server.loading_loaded_bytes, (float)c_ru.ru_utime.tv_sec+(float)c_ru.ru_utime.tv_usec/1000000,
perc, (float)c_ru.ru_stime.tv_sec+(float)c_ru.ru_stime.tv_usec/1000000);
eta
);
}
info = sdscat(info,"allocation_stats:");
for (j = 0; j <= ZMALLOC_MAX_ALLOC_STAT; j++) {
size_t count = zmalloc_allocations_for_size(j);
if (count) {
if (info[sdslen(info)-1] != ':') info = sdscatlen(info,",",1);
info = sdscatprintf(info,"%s%d=%zu",
(j == ZMALLOC_MAX_ALLOC_STAT) ? ">=" : "",
j,count);
}
}
info = sdscat(info,"\r\n");
numcommands = sizeof(readonlyCommandTable)/sizeof(struct redisCommand); numcommands = sizeof(readonlyCommandTable)/sizeof(struct redisCommand);
for (j = 0; j < numcommands; j++) { for (j = 0; j < numcommands; j++) {
struct redisCommand *c = readonlyCommandTable+j; struct redisCommand *c = readonlyCommandTable+j;
info = sdscatprintf(info,"command_%s:microseconds:%lld\r\n", info = sdscatprintf(info,"used_time_cmd_%s:%lld\r\n",
c->name, c->microseconds); c->name, c->microseconds);
} }
}
/* Key space */
if (allsections || defsections || !strcasecmp(section,"keyspace")) {
if (sections++) info = sdscat(info,"\r\n");
info = sdscatprintf(info, "# Keyspace\r\n");
for (j = 0; j < server.dbnum; j++) { for (j = 0; j < server.dbnum; j++) {
long long keys, vkeys; long long keys, vkeys;
...@@ -1349,11 +1415,18 @@ sds genRedisInfoString(void) { ...@@ -1349,11 +1415,18 @@ sds genRedisInfoString(void) {
j, keys, vkeys); j, keys, vkeys);
} }
} }
}
return info; return info;
} }
void infoCommand(redisClient *c) { void infoCommand(redisClient *c) {
sds info = genRedisInfoString(); char *section = c->argc == 2 ? c->argv[1]->ptr : "default";
if (c->argc > 2) {
addReply(c,shared.syntaxerr);
return;
}
sds info = genRedisInfoString(section);
addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n", addReplySds(c,sdscatprintf(sdsempty(),"$%lu\r\n",
(unsigned long)sdslen(info))); (unsigned long)sdslen(info)));
addReplySds(c,info); addReplySds(c,info);
...@@ -1619,7 +1692,7 @@ void segvHandler(int sig, siginfo_t *info, void *secret) { ...@@ -1619,7 +1692,7 @@ void segvHandler(int sig, siginfo_t *info, void *secret) {
redisLog(REDIS_WARNING, redisLog(REDIS_WARNING,
"======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION, sig); "======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION, sig);
infostring = genRedisInfoString(); infostring = genRedisInfoString("all");
redisLog(REDIS_WARNING, "%s",infostring); redisLog(REDIS_WARNING, "%s",infostring);
/* It's not safe to sdsfree() the returned string under memory /* It's not safe to sdsfree() the returned string under memory
* corruption conditions. Let it leak as we are going to abort */ * corruption conditions. Let it leak as we are going to abort */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment