mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-16 01:40:52 +08:00
256 lines
6.0 KiB
C++
256 lines
6.0 KiB
C++
|
#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<acl::redis_node*> nodes;
|
||
|
redis_util::get_nodes(redis, prefer_master_, nodes);
|
||
|
|
||
|
if (nodes.empty())
|
||
|
{
|
||
|
logger_error("no redis nodes available");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
std::vector<acl::redis_client*> conns;
|
||
|
for (std::vector<acl::redis_node*>::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<acl::redis_client*>::iterator it = conns.begin();
|
||
|
it != conns.end(); ++it)
|
||
|
{
|
||
|
delete *it;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int redis_monitor::check(const std::map<acl::string, acl::string>& info,
|
||
|
const char* name, std::vector<int>& res)
|
||
|
{
|
||
|
std::map<acl::string, acl::string>::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<acl::string, acl::string>& info,
|
||
|
const char* name, std::vector<long long>& res)
|
||
|
{
|
||
|
std::map<acl::string, acl::string>::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<acl::string>& tokens = buf.split2(";,");
|
||
|
for (std::vector<acl::string>::iterator it = tokens.begin();
|
||
|
it != tokens.end(); ++it)
|
||
|
{
|
||
|
std::vector<acl::string>& 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<acl::string, acl::string>& info,
|
||
|
std::vector<int>& keys)
|
||
|
{
|
||
|
int count = 0;
|
||
|
|
||
|
for (std::map<acl::string, acl::string>::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<acl::redis_client*>& conns)
|
||
|
{
|
||
|
std::vector<acl::string> addrs;
|
||
|
std::vector<int> tpses;
|
||
|
std::vector<int> clients;
|
||
|
std::vector<int> keys;
|
||
|
std::vector<long long> memory;
|
||
|
|
||
|
for (std::vector<acl::redis_client*>::iterator it = conns.begin();
|
||
|
it != conns.end(); ++it)
|
||
|
{
|
||
|
acl::redis cmd(*it);
|
||
|
std::map<acl::string, acl::string> 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
|
||
|
}
|