#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_); client.set_password(passwd_); 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_); conn->set_password(passwd_); 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; } } double 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.0); return 0.0; } else { double n = atof(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; } static double to_human(long long n, acl::string& units) { double msize; #define KB 1024 #define MB (1024 * 1024) #define GB (1024 * 1024 * 1024) long long TB = (long long) GB * 1024; if ((msize = (double) (n / TB)) >= 1) { units = "T"; } else if ((msize = ((double) n) / GB) >= 1) { units = "G"; } else if ((msize = ((double) n) / MB) >= 1) { units = "M"; } else if ((msize = ((double) n) / KB) >= 1) { units = "K"; } else { msize = (double) n; units = "B"; } return msize; } void redis_monitor::show_status(std::vector& conns) { std::vector addrs; std::vector tpses; std::vector clients; std::vector keys; std::vector memory; std::vector memory_rss; std::vector memory_peak; std::vector memory_frag; 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); check(info, "used_memory_rss", memory_rss); check(info, "used_memory_peak", memory_peak); check(info, "mem_fragmentation_ratio", memory_frag); } int all_tps = 0, all_client = 0, all_keys = 0; size_t size = addrs.size(); acl::string units, rss_units, peak_units; double msize, mrss, mpeak; long long total_msize = 0, total_rss = 0, total_peak = 0; for (size_t i = 0; i < size; i++) { msize = to_human(memory[i], units); mrss = to_human(memory_rss[i], rss_units); mpeak = to_human(memory_peak[i], peak_units); #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%6d\033[0m," " \033[1;33;40mkeys:\033[0m" " \033[1;36;40m%10d\033[0m," " \033[1;33;40mmem:\033[0m" " \033[1;36;40m%8.2f %s\033[0m," " \033[1;33;40mmem rss:\033[0m" " \033[1;36;40m%8.2f %s\033[0m," " \033[1;33;40mmem peak:\033[0m" " \033[1;36;40m%8.2f %s\033[0m," " \033[1;33;40mfrag ratio:\033[0m" " \033[1;36;40m%4.2f\033[0m\r\n", #else printf("redis: %15s, tps: %8d, clients: %6d, keys: %10d," " mem: %8.2f %s, mem rss: %8.2f %s," " mem peak: %8.2f %s, frag ratio: %4.2f\r\n", #endif addrs[i].c_str(), tpses[i], clients[i], keys[i], msize, units.c_str(), mrss, rss_units.c_str(), mpeak, peak_units.c_str(), memory_frag[i]); 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 (memory_rss[i] > 0) { total_rss += memory_rss[i]; } if (memory_peak[i] > 0) { total_peak += memory_peak[i]; } } msize = to_human(total_msize, units); mrss = to_human(total_rss, rss_units); mpeak = to_human(total_peak, peak_units); #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%6d\033[0m," " \033[1;34;40mkeys:\033[0m" " \033[1;36;40m%10d\033[0m," " \033[1;34;40mmem:\033[0m" " \033[1;36;40m%8.2f %s\033[0m," " \033[1;34;40mmem rss:\033[0m" " \033[1;36;40m%8.2f %s\033[0m," " \033[1;34;40mmem peak:\033[0m" " \033[1;36;40m%8.2f %s\033[0m\r\n", #else printf("total masters: %12d, tps: %8d, clients: %6d," " keys: %10d, mem: %8.2f %s, mem rss: %8.2f %s," " mem peak: %8.2f %s\r\n", #endif (int) size, all_tps, all_client, all_keys, msize, units.c_str(), mrss, rss_units.c_str(), mpeak, peak_units.c_str()); }