MXS-1220: Add old router diagnostic interface

Added back the old diagnostic entry point to the router interface.
This commit is contained in:
Markus Mäkelä
2017-04-21 12:15:06 +03:00
committed by Markus Mäkelä
parent b1294f083c
commit fc887c7f5f
11 changed files with 769 additions and 18 deletions

View File

@ -95,7 +95,8 @@ static MXS_ROUTER_SESSION *newSession(MXS_ROUTER *instance, MXS_SESSION *sessio
static void closeSession(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session);
static void freeSession(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session);
static int routeQuery(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session, GWBUF *queue);
static json_t* diagnostics(const MXS_ROUTER *instance);
static void diagnostics(MXS_ROUTER *instance, DCB *dcb);
static json_t* diagnostics_json(const MXS_ROUTER *instance);
static void clientReply(MXS_ROUTER *instance,
MXS_ROUTER_SESSION *router_session,
GWBUF *queue,
@ -160,6 +161,7 @@ MXS_MODULE* MXS_CREATE_MODULE()
freeSession,
routeQuery,
diagnostics,
diagnostics_json,
clientReply,
errorReply,
getCapabilities,
@ -1287,7 +1289,450 @@ spin_reporter(void *dcb, char *desc, int value)
* @param instance Instance of the router
* @param dcb DCB to send diagnostics to
*/
static json_t* diagnostics(const MXS_ROUTER *router)
static void
diagnostics(MXS_ROUTER *router, DCB *dcb)
{
ROUTER_INSTANCE *router_inst = (ROUTER_INSTANCE *)router;
ROUTER_SLAVE *session;
int i = 0, j;
int minno = 0;
double min5, min10, min15, min30;
char buf[40];
struct tm tm;
spinlock_acquire(&router_inst->lock);
session = router_inst->slaves;
while (session)
{
i++;
session = session->next;
}
spinlock_release(&router_inst->lock);
minno = router_inst->stats.minno;
min30 = 0.0;
min15 = 0.0;
min10 = 0.0;
min5 = 0.0;
for (j = 0; j < BLR_NSTATS_MINUTES; j++)
{
minno--;
if (minno < 0)
{
minno += BLR_NSTATS_MINUTES;
}
min30 += router_inst->stats.minavgs[minno];
if (j < 15)
{
min15 += router_inst->stats.minavgs[minno];
}
if (j < 10)
{
min10 += router_inst->stats.minavgs[minno];
}
if (j < 5)
{
min5 += router_inst->stats.minavgs[minno];
}
}
min30 /= 30.0;
min15 /= 15.0;
min10 /= 10.0;
min5 /= 5.0;
if (router_inst->master)
{
dcb_printf(dcb, "\tMaster connection DCB: %p\n",
router_inst->master);
}
else
{
dcb_printf(dcb, "\tMaster connection DCB: 0x0\n");
}
/* SSL options */
if (router_inst->ssl_enabled)
{
dcb_printf(dcb, "\tMaster SSL is ON:\n");
if (router_inst->service->dbref->server && router_inst->service->dbref->server->server_ssl)
{
dcb_printf(dcb, "\t\tMaster SSL CA cert: %s\n",
router_inst->service->dbref->server->server_ssl->ssl_ca_cert);
dcb_printf(dcb, "\t\tMaster SSL Cert: %s\n",
router_inst->service->dbref->server->server_ssl->ssl_cert);
dcb_printf(dcb, "\t\tMaster SSL Key: %s\n",
router_inst->service->dbref->server->server_ssl->ssl_key);
dcb_printf(dcb, "\t\tMaster SSL tls_ver: %s\n",
router_inst->ssl_version ? router_inst->ssl_version : "MAX");
}
}
/* Binlog Encryption options */
if (router_inst->encryption.enabled)
{
dcb_printf(dcb, "\tBinlog Encryption is ON:\n");
dcb_printf(dcb, "\t\tEncryption Key File: %s\n",
router_inst->encryption.key_management_filename);
dcb_printf(dcb, "\t\tEncryption Key Algorithm: %s\n",
blr_get_encryption_algorithm(router_inst->encryption.encryption_algorithm));
dcb_printf(dcb, "\t\tEncryption Key length: %lu bits\n",
8 * router_inst->encryption.key_len);
}
dcb_printf(dcb, "\tMaster connection state: %s\n",
blrm_states[router_inst->master_state]);
localtime_r(&router_inst->stats.lastReply, &tm);
asctime_r(&tm, buf);
dcb_printf(dcb, "\tBinlog directory: %s\n",
router_inst->binlogdir);
dcb_printf(dcb, "\tHeartbeat period (seconds): %lu\n",
router_inst->heartbeat);
dcb_printf(dcb, "\tNumber of master connects: %d\n",
router_inst->stats.n_masterstarts);
dcb_printf(dcb, "\tNumber of delayed reconnects: %d\n",
router_inst->stats.n_delayedreconnects);
dcb_printf(dcb, "\tCurrent binlog file: %s\n",
router_inst->binlog_name);
dcb_printf(dcb, "\tCurrent binlog position: %lu\n",
router_inst->current_pos);
if (router_inst->trx_safe)
{
if (router_inst->pending_transaction.state != BLRM_NO_TRANSACTION)
{
dcb_printf(dcb, "\tCurrent open transaction pos: %lu\n",
router_inst->binlog_position);
}
}
dcb_printf(dcb, "\tNumber of slave servers: %u\n",
router_inst->stats.n_slaves);
dcb_printf(dcb, "\tNo. of binlog events received this session: %lu\n",
router_inst->stats.n_binlogs_ses);
dcb_printf(dcb, "\tTotal no. of binlog events received: %lu\n",
router_inst->stats.n_binlogs);
dcb_printf(dcb, "\tNo. of bad CRC received from master: %u\n",
router_inst->stats.n_badcrc);
minno = router_inst->stats.minno - 1;
if (minno == -1)
{
minno += BLR_NSTATS_MINUTES;
}
dcb_printf(dcb, "\tNumber of binlog events per minute\n");
dcb_printf(dcb, "\tCurrent 5 10 15 30 Min Avg\n");
dcb_printf(dcb, "\t %6d %8.1f %8.1f %8.1f %8.1f\n",
router_inst->stats.minavgs[minno], min5, min10, min15, min30);
dcb_printf(dcb, "\tNumber of fake binlog events: %lu\n",
router_inst->stats.n_fakeevents);
dcb_printf(dcb, "\tNumber of artificial binlog events: %lu\n",
router_inst->stats.n_artificial);
dcb_printf(dcb, "\tNumber of binlog events in error: %lu\n",
router_inst->stats.n_binlog_errors);
dcb_printf(dcb, "\tNumber of binlog rotate events: %lu\n",
router_inst->stats.n_rotates);
dcb_printf(dcb, "\tNumber of heartbeat events: %u\n",
router_inst->stats.n_heartbeats);
dcb_printf(dcb, "\tNumber of packets received: %u\n",
router_inst->stats.n_reads);
dcb_printf(dcb, "\tNumber of residual data packets: %u\n",
router_inst->stats.n_residuals);
dcb_printf(dcb, "\tAverage events per packet: %.1f\n",
router_inst->stats.n_reads != 0 ?
((double)router_inst->stats.n_binlogs / router_inst->stats.n_reads) : 0);
spinlock_acquire(&router_inst->lock);
if (router_inst->stats.lastReply)
{
if (buf[strlen(buf) - 1] == '\n')
{
buf[strlen(buf) - 1] = '\0';
}
dcb_printf(dcb, "\tLast event from master at: %s (%ld seconds ago)\n",
buf, time(0) - router_inst->stats.lastReply);
if (!router_inst->mariadb10_compat)
{
dcb_printf(dcb, "\tLast event from master: 0x%x, %s\n",
router_inst->lastEventReceived,
(router_inst->lastEventReceived <= MAX_EVENT_TYPE) ?
event_names[router_inst->lastEventReceived] : "unknown");
}
else
{
char *ptr = NULL;
if (router_inst->lastEventReceived <= MAX_EVENT_TYPE)
{
ptr = event_names[router_inst->lastEventReceived];
}
else
{
/* Check MariaDB 10 new events */
if (router_inst->lastEventReceived >= MARIADB_NEW_EVENTS_BEGIN &&
router_inst->lastEventReceived <= MAX_EVENT_TYPE_MARIADB10)
{
ptr = event_names_mariadb10[(router_inst->lastEventReceived - MARIADB_NEW_EVENTS_BEGIN)];
}
}
dcb_printf(dcb, "\tLast event from master: 0x%x, %s\n",
router_inst->lastEventReceived, (ptr != NULL) ? ptr : "unknown");
if (router_inst->mariadb_gtid &&
router_inst->last_mariadb_gtid[0])
{
dcb_printf(dcb, "\tLast seen MariaDB GTID: %s\n",
router_inst->last_mariadb_gtid);
}
}
if (router_inst->lastEventTimestamp)
{
time_t last_event = (time_t)router_inst->lastEventTimestamp;
localtime_r(&last_event, &tm);
asctime_r(&tm, buf);
if (buf[strlen(buf) - 1] == '\n')
{
buf[strlen(buf) - 1] = '\0';
}
dcb_printf(dcb, "\tLast binlog event timestamp: %u (%s)\n",
router_inst->lastEventTimestamp, buf);
}
}
else
{
dcb_printf(dcb, "\tNo events received from master yet\n");
}
spinlock_release(&router_inst->lock);
if (router_inst->active_logs)
{
dcb_printf(dcb, "\tRouter processing binlog records\n");
}
if (router_inst->reconnect_pending)
{
dcb_printf(dcb, "\tRouter pending reconnect to master\n");
}
dcb_printf(dcb, "\tEvents received:\n");
for (i = 0; i <= MAX_EVENT_TYPE; i++)
{
dcb_printf(dcb, "\t\t%-38s %lu\n", event_names[i], router_inst->stats.events[i]);
}
if (router_inst->mariadb10_compat)
{
/* Display MariaDB 10 new events */
for (i = MARIADB_NEW_EVENTS_BEGIN; i <= MAX_EVENT_TYPE_MARIADB10; i++)
{
dcb_printf(dcb, "\t\tMariaDB 10 %-38s %lu\n",
event_names_mariadb10[(i - MARIADB_NEW_EVENTS_BEGIN)],
router_inst->stats.events[i]);
}
}
#if SPINLOCK_PROFILE
dcb_printf(dcb, "\tSpinlock statistics (instlock):\n");
spinlock_stats(&instlock, spin_reporter, dcb);
dcb_printf(dcb, "\tSpinlock statistics (instance lock):\n");
spinlock_stats(&router_inst->lock, spin_reporter, dcb);
dcb_printf(dcb, "\tSpinlock statistics (binlog position lock):\n");
spinlock_stats(&router_inst->binlog_lock, spin_reporter, dcb);
#endif
if (router_inst->slaves)
{
dcb_printf(dcb, "\tSlaves:\n");
spinlock_acquire(&router_inst->lock);
session = router_inst->slaves;
while (session)
{
minno = session->stats.minno;
min30 = 0.0;
min15 = 0.0;
min10 = 0.0;
min5 = 0.0;
for (j = 0; j < BLR_NSTATS_MINUTES; j++)
{
minno--;
if (minno < 0)
{
minno += BLR_NSTATS_MINUTES;
}
min30 += session->stats.minavgs[minno];
if (j < 15)
{
min15 += session->stats.minavgs[minno];
}
if (j < 10)
{
min10 += session->stats.minavgs[minno];
}
if (j < 5)
{
min5 += session->stats.minavgs[minno];
}
}
min30 /= 30.0;
min15 /= 15.0;
min10 /= 10.0;
min5 /= 5.0;
dcb_printf(dcb,
"\t\tServer-id: %d\n",
session->serverid);
if (session->hostname)
{
dcb_printf(dcb,
"\t\tHostname: %s\n", session->hostname);
}
if (session->uuid)
{
dcb_printf(dcb, "\t\tSlave UUID: %s\n", session->uuid);
}
dcb_printf(dcb,
"\t\tSlave_host_port: [%s]:%d\n",
session->dcb->remote, dcb_get_port(session->dcb));
dcb_printf(dcb,
"\t\tUsername: %s\n",
session->dcb->user);
dcb_printf(dcb,
"\t\tSlave DCB: %p\n",
session->dcb);
if (session->dcb->ssl)
{
dcb_printf(dcb,
"\t\tSlave connected with SSL: %s\n",
session->dcb->ssl_state == SSL_ESTABLISHED ?
"Established" : "Not connected yet");
}
dcb_printf(dcb,
"\t\tNext Sequence No: %d\n",
session->seqno);
dcb_printf(dcb,
"\t\tState: %s\n",
blrs_states[session->state]);
dcb_printf(dcb,
"\t\tBinlog file: %s\n",
session->binlogfile);
dcb_printf(dcb,
"\t\tBinlog position: %u\n",
session->binlog_pos);
if (session->nocrc)
{
dcb_printf(dcb,
"\t\tMaster Binlog CRC: None\n");
}
dcb_printf(dcb,
"\t\tNo. requests: %u\n",
session->stats.n_requests);
dcb_printf(dcb,
"\t\tNo. events sent: %u\n",
session->stats.n_events);
dcb_printf(dcb,
"\t\tNo. bytes sent: %lu\n",
session->stats.n_bytes);
dcb_printf(dcb,
"\t\tNo. bursts sent: %u\n",
session->stats.n_bursts);
dcb_printf(dcb,
"\t\tNo. transitions to follow mode: %u\n",
session->stats.n_bursts);
if (router_inst->send_slave_heartbeat)
{
dcb_printf(dcb,
"\t\tHeartbeat period (seconds): %d\n",
session->heartbeat);
}
minno = session->stats.minno - 1;
if (minno == -1)
{
minno += BLR_NSTATS_MINUTES;
}
dcb_printf(dcb, "\t\tNumber of binlog events per minute\n");
dcb_printf(dcb, "\t\tCurrent 5 10 15 30 Min Avg\n");
dcb_printf(dcb, "\t\t %6d %8.1f %8.1f %8.1f %8.1f\n",
session->stats.minavgs[minno], min5, min10,
min15, min30);
dcb_printf(dcb, "\t\tNo. flow control: %u\n",
session->stats.n_flows);
dcb_printf(dcb, "\t\tNo. up to date: %u\n",
session->stats.n_upd);
dcb_printf(dcb, "\t\tNo. of drained cbs %u\n",
session->stats.n_dcb);
dcb_printf(dcb, "\t\tNo. of failed reads %u\n",
session->stats.n_failed_read);
#ifdef DETAILED_DIAG
dcb_printf(dcb, "\t\tNo. of nested distribute events %u\n",
session->stats.n_overrun);
dcb_printf(dcb, "\t\tNo. of distribute action 1 %u\n",
session->stats.n_actions[0]);
dcb_printf(dcb, "\t\tNo. of distribute action 2 %u\n",
session->stats.n_actions[1]);
dcb_printf(dcb, "\t\tNo. of distribute action 3 %u\n",
session->stats.n_actions[2]);
#endif
if (session->lastEventTimestamp
&& router_inst->lastEventTimestamp && session->lastEventReceived != HEARTBEAT_EVENT)
{
unsigned long seconds_behind;
time_t session_last_event = (time_t)session->lastEventTimestamp;
if (router_inst->lastEventTimestamp > session->lastEventTimestamp)
{
seconds_behind = router_inst->lastEventTimestamp - session->lastEventTimestamp;
}
else
{
seconds_behind = 0;
}
localtime_r(&session_last_event, &tm);
asctime_r(&tm, buf);
dcb_printf(dcb, "\t\tLast binlog event timestamp %u, %s",
session->lastEventTimestamp, buf);
dcb_printf(dcb, "\t\tSeconds behind master %lu\n",
seconds_behind);
}
if (session->state == 0)
{
dcb_printf(dcb, "\t\tSlave_mode: connected\n");
}
else
{
if ((session->cstate & CS_WAIT_DATA) == CS_WAIT_DATA)
{
dcb_printf(dcb, "\t\tSlave_mode: wait-for-data\n");
}
else
{
dcb_printf(dcb, "\t\tSlave_mode: catchup. %s%s\n",
((session->cstate & CS_EXPECTCB) == 0 ? "" :
"Waiting for DCB queue to drain."),
((session->cstate & CS_BUSY) == 0 ? "" :
" Busy in slave catchup."));
}
}
#if SPINLOCK_PROFILE
dcb_printf(dcb, "\tSpinlock statistics (catch_lock):\n");
spinlock_stats(&session->catch_lock, spin_reporter, dcb);
dcb_printf(dcb, "\tSpinlock statistics (rses_lock):\n");
spinlock_stats(&session->rses_lock, spin_reporter, dcb);
#endif
dcb_printf(dcb, "\t\t--------------------\n\n");
session = session->next;
}
spinlock_release(&router_inst->lock);
}
}
/**
* Display router diagnostics
*
* @param instance Instance of the router
*/
static json_t* diagnostics_json(const MXS_ROUTER *router)
{
ROUTER_INSTANCE *router_inst = (ROUTER_INSTANCE *)router;
int minno = 0;