#include "stdafx.h" #include "redis_util.h" #include "redis_monitor.h" redis_monitor::redis_monitor(const char* addr, int conn_timeout, int rw_timeout, const char* passwd, bool prefer_master) { addr_ = addr; conn_timeout_ = conn_timeout; rw_timeout_ = rw_timeout; if (passwd && *passwd) passwd_ = passwd; prefer_master_ = prefer_master; } redis_monitor::~redis_monitor(void) { } void redis_monitor::status(void) { acl::redis_client client(addr_, conn_timeout_, rw_timeout_); acl::redis redis(&client); std::vector nodes; redis_util::get_nodes(redis, prefer_master_, nodes); if (nodes.empty()) { logger_error("no redis nodes available"); return; } std::vector conns; for (std::vector::const_iterator cit = nodes.begin(); cit != nodes.end(); ++cit) { const char* addr = (*cit)->get_addr(); if (addr == NULL || *addr == 0) { logger_warn("addr NULL, skip it"); continue; } acl::redis_client* conn = new acl::redis_client( addr, conn_timeout_, rw_timeout_); conns.push_back(conn); } while (true) { show_status(conns); sleep(1); } for (std::vector::iterator it = conns.begin(); it != conns.end(); ++it) { delete *it; } } int redis_monitor::check(const std::map& info, const char* name, std::vector& res) { std::map::const_iterator cit = info.find(name); if (cit == info.end()) { logger_error("no %s", name); res.push_back(0); return 0; } else { int n = atoi(cit->second.c_str()); res.push_back(n); return n; } } long long redis_monitor::check(const std::map& info, const char* name, std::vector& res) { std::map::const_iterator cit = info.find(name); if (cit == info.end()) { logger_error("no %s", name); res.push_back(0); return 0; } else { long long n = acl_atoll(cit->second.c_str()); res.push_back(n); return n; } } int redis_monitor::check_keys(const char* name, const char* value) { if (strncmp(name, "db", 2) != 0 || *value == 0) return 0; name += 2; if (*name == 0 || !acl_alldig(name)) return 0; acl::string buf(value); buf.trim_space(); int keys = 0; std::vector& tokens = buf.split2(";,"); for (std::vector::iterator it = tokens.begin(); it != tokens.end(); ++it) { std::vector& tokens2 = (*it).split2("="); if (tokens2.size() != 2) continue; if (tokens2[0] == "keys" && acl_alldig(tokens2[1])) keys = atoi(tokens2[1].c_str()); } return keys; } int redis_monitor::check_keys(const std::map& info, std::vector& keys) { int count = 0; for (std::map::const_iterator cit = info.begin(); cit != info.end(); ++cit) { int n = check_keys(cit->first, cit->second); if (n > 0) count += n; } keys.push_back(count); return count; } void redis_monitor::show_status(std::vector& conns) { std::vector addrs; std::vector tpses; std::vector clients; std::vector keys; std::vector memory; for (std::vector::iterator it = conns.begin(); it != conns.end(); ++it) { acl::redis cmd(*it); std::map info; if (cmd.info(info) < 0) { logger_error("cmd info error: %s, addr: %s", cmd.result_error(), (*it)->get_addr()); continue; } addrs.push_back((*it)->get_addr()); check(info, "instantaneous_ops_per_sec", tpses); check(info, "connected_clients", clients); check_keys(info, keys); check(info, "used_memory", memory); } int all_tps = 0, all_client = 0, all_keys = 0; size_t size = addrs.size(); #define KB 1024 #define MB (1024 * 1024) #define GB (1024 * 1024 * 1024) const char* units; double msize; long long total_msize = 0; for (size_t i = 0; i < size; i++) { if ((msize = ((double) memory[i]) / GB) >= 1) units = "G"; else if ((msize = ((double) memory[i]) / MB) >= 1) units = "M"; else if ((msize = ((double) memory[i]) / KB) >= 1) units = "K"; else { msize = (double) memory[i]; units = "B"; } #ifdef ACL_UNIX printf("\033[1;32;40mredis:\033[0m" " \033[1;36;40m%20s\033[0m," " \033[1;33;40mtps:\033[0m" " \033[1;36;40m%8d\033[0m," " \033[1;33;40mclients:\033[0m" " \033[1;36;40m%8d\033[0m," " \033[1;33;40mkeys:\033[0m" " \033[1;36;40m%8d\033[0m," " \033[1;33;40mmemory:\033[0m" " \033[1;36;40m%8.2f %s\033[0m\r\n", addrs[i].c_str(), tpses[i], clients[i], keys[i], msize, units); #else printf("redis: %s, tps: %d, client: %d, keys: %d," " memory: %.2f %s\r\n", addrs[i].c_str(), tpses[i], clients[i], keys[i], msize, units); #endif if (tpses[i] > 0) all_tps += tpses[i]; if (clients[i] > 0) all_client += clients[i]; if (keys[i] > 0) all_keys += keys[i]; if (memory[i] > 0) total_msize += memory[i]; } if ((msize = ((double) total_msize) / GB) >= 1) units = "G"; else if ((msize = ((double) total_msize) / MB) >= 1) units = "M"; else if ((msize = ((double) total_msize) / KB) >= 1) units = "K"; else { msize = (double) total_msize; units = "B"; } #ifdef ACL_UNIX printf("\033[1;34;40mtotal masters:\033[0m" " \033[1;36;40m%12d\033[0m," " \033[1;34;40mtps:\033[0m" " \033[1;36;40m%8d\033[0m," " \033[1;34;40mclients:\033[0m" " \033[1;36;40m%8d\033[0m," " \033[1;34;40mkeys:\033[0m" " \033[1;36;40m%8d\033[0m," " \033[1;34;40mmemory:\033[0m" " \033[1;36;40m%8.2f %s\033[0m\r\n", (int) size, all_tps, all_client, all_keys, msize, units); #else printf("total masters: %d, total tps: %d, total clients: %d," " total keys: %d, total memory: %.2f %s\r\n", (int) size, all_tps, all_client, all_keys, msize, units); #endif }