mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
Add rolling statistics that are collected across 10 second intervals.
Add a new command "ctdb stats [num]" that prints the [num] most recent statistics intervals collected. (This used to be ctdb commit e6e16fcd5a45ebd3739a8160c8fb5f44494edb9e)
This commit is contained in:
parent
41b6e09fb1
commit
9f66a93f12
@ -63,7 +63,7 @@ CTDB_SERVER_OBJ = server/ctdbd.o server/ctdb_daemon.o server/ctdb_lockwait.o \
|
|||||||
server/ctdb_traverse.o server/eventscript.o server/ctdb_takeover.o \
|
server/ctdb_traverse.o server/eventscript.o server/ctdb_takeover.o \
|
||||||
server/ctdb_serverids.o server/ctdb_persistent.o \
|
server/ctdb_serverids.o server/ctdb_persistent.o \
|
||||||
server/ctdb_keepalive.o server/ctdb_logging.o server/ctdb_uptime.o \
|
server/ctdb_keepalive.o server/ctdb_logging.o server/ctdb_uptime.o \
|
||||||
server/ctdb_vacuum.o server/ctdb_banning.o \
|
server/ctdb_vacuum.o server/ctdb_banning.o server/ctdb_statistics.o \
|
||||||
$(CTDB_CLIENT_OBJ) $(CTDB_TCP_OBJ) @INFINIBAND_WRAPPER_OBJ@
|
$(CTDB_CLIENT_OBJ) $(CTDB_TCP_OBJ) @INFINIBAND_WRAPPER_OBJ@
|
||||||
|
|
||||||
TEST_BINS=tests/bin/ctdb_bench tests/bin/ctdb_fetch tests/bin/ctdb_fetch_one \
|
TEST_BINS=tests/bin/ctdb_bench tests/bin/ctdb_fetch tests/bin/ctdb_fetch_one \
|
||||||
|
@ -4216,3 +4216,23 @@ int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ctdb_ctrl_getstathistory(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_statistics_wire **stats)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
TDB_DATA outdata;
|
||||||
|
int32_t res;
|
||||||
|
|
||||||
|
ret = ctdb_control(ctdb, destnode, 0,
|
||||||
|
CTDB_CONTROL_GET_STAT_HISTORY, 0, tdb_null,
|
||||||
|
mem_ctx, &outdata, &res, &timeout, NULL);
|
||||||
|
if (ret != 0 || res != 0 || outdata.dsize == 0) {
|
||||||
|
DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getstathistory failed ret:%d res:%d\n", ret, res));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*stats = (struct ctdb_statistics_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
|
||||||
|
talloc_free(outdata.dptr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -588,4 +588,7 @@ struct ctdb_db_priority {
|
|||||||
int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio);
|
int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio);
|
||||||
int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority);
|
int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority);
|
||||||
|
|
||||||
|
int ctdb_ctrl_getstathistory(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_statistics_wire **stats);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _CTDB_CLIENT_H */
|
#endif /* _CTDB_CLIENT_H */
|
||||||
|
@ -334,60 +334,6 @@ struct ctdb_daemon_data {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
ctdb statistics information
|
|
||||||
*/
|
|
||||||
struct ctdb_statistics {
|
|
||||||
uint32_t num_clients;
|
|
||||||
uint32_t frozen;
|
|
||||||
uint32_t recovering;
|
|
||||||
uint32_t client_packets_sent;
|
|
||||||
uint32_t client_packets_recv;
|
|
||||||
uint32_t node_packets_sent;
|
|
||||||
uint32_t node_packets_recv;
|
|
||||||
uint32_t keepalive_packets_sent;
|
|
||||||
uint32_t keepalive_packets_recv;
|
|
||||||
struct {
|
|
||||||
uint32_t req_call;
|
|
||||||
uint32_t reply_call;
|
|
||||||
uint32_t req_dmaster;
|
|
||||||
uint32_t reply_dmaster;
|
|
||||||
uint32_t reply_error;
|
|
||||||
uint32_t req_message;
|
|
||||||
uint32_t req_control;
|
|
||||||
uint32_t reply_control;
|
|
||||||
} node;
|
|
||||||
struct {
|
|
||||||
uint32_t req_call;
|
|
||||||
uint32_t req_message;
|
|
||||||
uint32_t req_control;
|
|
||||||
} client;
|
|
||||||
struct {
|
|
||||||
uint32_t call;
|
|
||||||
uint32_t control;
|
|
||||||
uint32_t traverse;
|
|
||||||
} timeouts;
|
|
||||||
struct {
|
|
||||||
double ctdbd;
|
|
||||||
double recd;
|
|
||||||
} reclock;
|
|
||||||
uint32_t total_calls;
|
|
||||||
uint32_t pending_calls;
|
|
||||||
uint32_t lockwait_calls;
|
|
||||||
uint32_t pending_lockwait_calls;
|
|
||||||
uint32_t childwrite_calls;
|
|
||||||
uint32_t pending_childwrite_calls;
|
|
||||||
uint32_t memory_used;
|
|
||||||
uint32_t __last_counter; /* hack for control_statistics_all */
|
|
||||||
uint32_t max_hop_count;
|
|
||||||
double max_call_latency;
|
|
||||||
double max_lockwait_latency;
|
|
||||||
double max_childwrite_latency;
|
|
||||||
uint32_t num_recoveries;
|
|
||||||
struct timeval statistics_start_time;
|
|
||||||
struct timeval statistics_current_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define INVALID_GENERATION 1
|
#define INVALID_GENERATION 1
|
||||||
/* table that contains the mapping between a hash value and lmaster
|
/* table that contains the mapping between a hash value and lmaster
|
||||||
@ -477,6 +423,8 @@ struct ctdb_context {
|
|||||||
struct ctdb_daemon_data daemon;
|
struct ctdb_daemon_data daemon;
|
||||||
struct ctdb_statistics statistics;
|
struct ctdb_statistics statistics;
|
||||||
struct ctdb_statistics statistics_current;
|
struct ctdb_statistics statistics_current;
|
||||||
|
#define MAX_STAT_HISTORY 100
|
||||||
|
struct ctdb_statistics statistics_history[MAX_STAT_HISTORY];
|
||||||
struct ctdb_vnn_map *vnn_map;
|
struct ctdb_vnn_map *vnn_map;
|
||||||
uint32_t num_clients;
|
uint32_t num_clients;
|
||||||
uint32_t recovery_master;
|
uint32_t recovery_master;
|
||||||
@ -1395,6 +1343,10 @@ int update_ip_assignment_tree(struct ctdb_context *ctdb,
|
|||||||
|
|
||||||
int ctdb_init_tevent_logging(struct ctdb_context *ctdb);
|
int ctdb_init_tevent_logging(struct ctdb_context *ctdb);
|
||||||
|
|
||||||
int ctdb_update_stat_counter(struct ctdb_context *ctdb, uint32_t *counter, uint32_t value);
|
int ctdb_statistics_init(struct ctdb_context *ctdb);
|
||||||
|
|
||||||
|
int32_t ctdb_control_get_stat_history(struct ctdb_context *ctdb,
|
||||||
|
struct ctdb_req_control *c,
|
||||||
|
TDB_DATA *outdata);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -357,6 +357,7 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0,
|
|||||||
CTDB_CONTROL_GET_IFACES = 124,
|
CTDB_CONTROL_GET_IFACES = 124,
|
||||||
CTDB_CONTROL_SET_IFACE_LINK_STATE = 125,
|
CTDB_CONTROL_SET_IFACE_LINK_STATE = 125,
|
||||||
CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE = 126,
|
CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE = 126,
|
||||||
|
CTDB_CONTROL_GET_STAT_HISTORY = 127,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -534,4 +535,68 @@ struct ctdb_all_public_ips {
|
|||||||
struct ctdb_public_ip ips[1];
|
struct ctdb_public_ip ips[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
ctdb statistics information
|
||||||
|
*/
|
||||||
|
struct ctdb_statistics {
|
||||||
|
uint32_t num_clients;
|
||||||
|
uint32_t frozen;
|
||||||
|
uint32_t recovering;
|
||||||
|
uint32_t client_packets_sent;
|
||||||
|
uint32_t client_packets_recv;
|
||||||
|
uint32_t node_packets_sent;
|
||||||
|
uint32_t node_packets_recv;
|
||||||
|
uint32_t keepalive_packets_sent;
|
||||||
|
uint32_t keepalive_packets_recv;
|
||||||
|
struct {
|
||||||
|
uint32_t req_call;
|
||||||
|
uint32_t reply_call;
|
||||||
|
uint32_t req_dmaster;
|
||||||
|
uint32_t reply_dmaster;
|
||||||
|
uint32_t reply_error;
|
||||||
|
uint32_t req_message;
|
||||||
|
uint32_t req_control;
|
||||||
|
uint32_t reply_control;
|
||||||
|
} node;
|
||||||
|
struct {
|
||||||
|
uint32_t req_call;
|
||||||
|
uint32_t req_message;
|
||||||
|
uint32_t req_control;
|
||||||
|
} client;
|
||||||
|
struct {
|
||||||
|
uint32_t call;
|
||||||
|
uint32_t control;
|
||||||
|
uint32_t traverse;
|
||||||
|
} timeouts;
|
||||||
|
struct {
|
||||||
|
double ctdbd;
|
||||||
|
double recd;
|
||||||
|
} reclock;
|
||||||
|
uint32_t total_calls;
|
||||||
|
uint32_t pending_calls;
|
||||||
|
uint32_t lockwait_calls;
|
||||||
|
uint32_t pending_lockwait_calls;
|
||||||
|
uint32_t childwrite_calls;
|
||||||
|
uint32_t pending_childwrite_calls;
|
||||||
|
uint32_t memory_used;
|
||||||
|
uint32_t __last_counter; /* hack for control_statistics_all */
|
||||||
|
uint32_t max_hop_count;
|
||||||
|
double max_call_latency;
|
||||||
|
double max_lockwait_latency;
|
||||||
|
double max_childwrite_latency;
|
||||||
|
uint32_t num_recoveries;
|
||||||
|
struct timeval statistics_start_time;
|
||||||
|
struct timeval statistics_current_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wire format for statistics history
|
||||||
|
*/
|
||||||
|
struct ctdb_statistics_wire {
|
||||||
|
uint32_t num;
|
||||||
|
struct ctdb_statistics stats[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -600,6 +600,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
|
|||||||
CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_iface_info));
|
CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_iface_info));
|
||||||
return ctdb_control_set_iface_link(ctdb, c, indata);
|
return ctdb_control_set_iface_link(ctdb, c, indata);
|
||||||
|
|
||||||
|
case CTDB_CONTROL_GET_STAT_HISTORY:
|
||||||
|
CHECK_CONTROL_DATA_SIZE(0);
|
||||||
|
return ctdb_control_get_stat_history(ctdb, c, outdata);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
|
DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -761,6 +761,9 @@ int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork, bool use_syslog)
|
|||||||
|
|
||||||
ctdb_set_child_logging(ctdb);
|
ctdb_set_child_logging(ctdb);
|
||||||
|
|
||||||
|
/* initialize statistics collection */
|
||||||
|
ctdb_statistics_init(ctdb);
|
||||||
|
|
||||||
/* force initial recovery for election */
|
/* force initial recovery for election */
|
||||||
ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE;
|
ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE;
|
||||||
|
|
||||||
|
77
ctdb/server/ctdb_statistics.c
Normal file
77
ctdb/server/ctdb_statistics.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
ctdb statistics code
|
||||||
|
|
||||||
|
Copyright (C) Ronnie Sahlberg 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "includes.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "lib/tevent/tevent.h"
|
||||||
|
#include "../include/ctdb_private.h"
|
||||||
|
|
||||||
|
static void ctdb_statistics_update(struct event_context *ev, struct timed_event *te,
|
||||||
|
struct timeval t, void *p)
|
||||||
|
{
|
||||||
|
struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
|
||||||
|
|
||||||
|
memmove(&ctdb->statistics_history[1], &ctdb->statistics_history[0], (MAX_STAT_HISTORY-1)*sizeof(struct ctdb_statistics));
|
||||||
|
memcpy(&ctdb->statistics_history[0], &ctdb->statistics_current, sizeof(struct ctdb_statistics));
|
||||||
|
ctdb->statistics_history[0].statistics_current_time = timeval_current();
|
||||||
|
|
||||||
|
|
||||||
|
bzero(&ctdb->statistics_current, sizeof(struct ctdb_statistics));
|
||||||
|
ctdb->statistics_current.statistics_start_time = timeval_current();
|
||||||
|
|
||||||
|
event_add_timed(ctdb->ev, ctdb, timeval_current_ofs(10, 0), ctdb_statistics_update, ctdb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ctdb_statistics_init(struct ctdb_context *ctdb)
|
||||||
|
{
|
||||||
|
bzero(&ctdb->statistics, sizeof(struct ctdb_statistics));
|
||||||
|
|
||||||
|
bzero(&ctdb->statistics_current, sizeof(struct ctdb_statistics));
|
||||||
|
ctdb->statistics_current.statistics_start_time = timeval_current();
|
||||||
|
|
||||||
|
bzero(ctdb->statistics_history, sizeof(ctdb->statistics_history));
|
||||||
|
|
||||||
|
event_add_timed(ctdb->ev, ctdb, timeval_current_ofs(10, 0), ctdb_statistics_update, ctdb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t ctdb_control_get_stat_history(struct ctdb_context *ctdb,
|
||||||
|
struct ctdb_req_control *c,
|
||||||
|
TDB_DATA *outdata)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
struct ctdb_statistics_wire *stat;
|
||||||
|
|
||||||
|
len = offsetof(struct ctdb_statistics_wire, stats) + MAX_STAT_HISTORY*sizeof(struct ctdb_statistics);
|
||||||
|
|
||||||
|
stat = talloc_size(outdata, len);
|
||||||
|
if (stat == NULL) {
|
||||||
|
DEBUG(DEBUG_ERR,(__location__ " Failed to allocate statistics history structure\n"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
stat->num = MAX_STAT_HISTORY;
|
||||||
|
memcpy(&stat->stats[0], &ctdb->statistics_history[0], sizeof(ctdb->statistics_history));
|
||||||
|
|
||||||
|
outdata->dsize = len;
|
||||||
|
outdata->dptr = (uint8_t *)stat;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -323,6 +323,38 @@ static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
display remote ctdb rolling statistics
|
||||||
|
*/
|
||||||
|
static int control_stats(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct ctdb_statistics_wire *stats;
|
||||||
|
int i, num_records = -1;
|
||||||
|
|
||||||
|
if (argc ==1) {
|
||||||
|
num_records = atoi(argv[0]) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ctdb_ctrl_getstathistory(ctdb, TIMELIMIT(), options.pnn, ctdb, &stats);
|
||||||
|
if (ret != 0) {
|
||||||
|
DEBUG(DEBUG_ERR, ("Unable to get rolling statistics from node %u\n", options.pnn));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
for (i=0;i<stats->num;i++) {
|
||||||
|
if (stats->stats[i].statistics_start_time.tv_sec == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
show_statistics(&stats->stats[i]);
|
||||||
|
if (i == num_records) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("===\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
display uptime of remote node
|
display uptime of remote node
|
||||||
*/
|
*/
|
||||||
@ -4679,6 +4711,7 @@ static const struct {
|
|||||||
{ "listvars", control_listvars, true, false, "list tunable variables"},
|
{ "listvars", control_listvars, true, false, "list tunable variables"},
|
||||||
{ "statistics", control_statistics, false, false, "show statistics" },
|
{ "statistics", control_statistics, false, false, "show statistics" },
|
||||||
{ "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
|
{ "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
|
||||||
|
{ "stats", control_stats, false, false, "show rolling statistics", "[number of history records]" },
|
||||||
{ "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
|
{ "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
|
||||||
{ "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
|
{ "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
|
||||||
{ "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
|
{ "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
|
||||||
|
Loading…
Reference in New Issue
Block a user