User interface improvements

Addition of enable/disable heartbeat, enable/disable root, list monitors,
show monitors

Better filter diagnostic output
This commit is contained in:
Mark Riddoch
2014-06-26 16:46:19 +01:00
parent fa08a141e4
commit f96b762478
12 changed files with 290 additions and 20 deletions

View File

@ -1264,6 +1264,41 @@ DCB *dcb;
spinlock_release(&dcbspin); spinlock_release(&dcbspin);
} }
/**
* Diagnotic routine to print client DCB data in a tabular form.
*
* @param pdcb DCB to print results to
*/
void
dListClients(DCB *pdcb)
{
DCB *dcb;
spinlock_acquire(&dcbspin);
dcb = allDCBs;
dcb_printf(pdcb, "Client Connections\n");
dcb_printf(pdcb, "-----------------+------------+----------------------+------------\n");
dcb_printf(pdcb, " %-15s | %-10s | %-20s | %s\n",
"Client", "DCB", "Service", "Session");
dcb_printf(pdcb, "-----------------+------------+----------------------+------------\n");
while (dcb)
{
if (dcb_isclient(dcb)
&& dcb->dcb_role == DCB_ROLE_REQUEST_HANDLER)
{
dcb_printf(pdcb, " %-15s | %10p | %-20s | %10p\n",
(dcb->remote ? dcb->remote : ""),
dcb, (dcb->session->service ?
dcb->session->service->name : ""),
dcb->session);
}
dcb = dcb->next;
}
dcb_printf(pdcb, "-----------------+------------+----------------------+------------\n\n");
spinlock_release(&dcbspin);
}
/** /**
* Diagnostic to print a DCB to another DCB * Diagnostic to print a DCB to another DCB
* *
@ -1275,8 +1310,14 @@ dprintDCB(DCB *pdcb, DCB *dcb)
{ {
dcb_printf(pdcb, "DCB: %p\n", (void *)dcb); dcb_printf(pdcb, "DCB: %p\n", (void *)dcb);
dcb_printf(pdcb, "\tDCB state: %s\n", gw_dcb_state2string(dcb->state)); dcb_printf(pdcb, "\tDCB state: %s\n", gw_dcb_state2string(dcb->state));
if (dcb->session && dcb->session->service)
dcb_printf(pdcb, "\tService: %s\n",
dcb->session->service->name);
if (dcb->remote) if (dcb->remote)
dcb_printf(pdcb, "\tConnected to: %s\n", dcb->remote); dcb_printf(pdcb, "\tConnected to: %s\n", dcb->remote);
if (dcb->user)
dcb_printf(pdcb, "\tUsername: %s\n",
dcb->user);
dcb_printf(pdcb, "\tOwning Session: %p\n", dcb->session); dcb_printf(pdcb, "\tOwning Session: %p\n", dcb->session);
if (dcb->writeq) if (dcb->writeq)
dcb_printf(pdcb, "\tQueued write data: %d\n", gwbuf_length(dcb->writeq)); dcb_printf(pdcb, "\tQueued write data: %d\n", gwbuf_length(dcb->writeq));

View File

@ -378,7 +378,9 @@ MODULES *ptr = registered;
: (ptr->info->status == MODULE_BETA_RELEASE : (ptr->info->status == MODULE_BETA_RELEASE
? "Beta" ? "Beta"
: (ptr->info->status == MODULE_GA : (ptr->info->status == MODULE_GA
? "GA" : "Unknown")))); ? "GA"
: (ptr->info->status == MODULE_EXPERIMENTAL
? "Experimental" : "Unknown")))));
dcb_printf(dcb, "\n"); dcb_printf(dcb, "\n");
ptr = ptr->next; ptr = ptr->next;
} }

View File

@ -73,6 +73,7 @@ MONITOR *mon;
return NULL; return NULL;
} }
mon->handle = (*mon->module->startMonitor)(NULL); mon->handle = (*mon->module->startMonitor)(NULL);
mon->state |= MONITOR_RUNNING;
spinlock_acquire(&monLock); spinlock_acquire(&monLock);
mon->next = allMonitors; mon->next = allMonitors;
allMonitors = mon; allMonitors = mon;
@ -93,6 +94,7 @@ monitor_free(MONITOR *mon)
MONITOR *ptr; MONITOR *ptr;
mon->module->stopMonitor(mon->handle); mon->module->stopMonitor(mon->handle);
mon->state &= ~MONITOR_RUNNING;
spinlock_acquire(&monLock); spinlock_acquire(&monLock);
if (allMonitors == mon) if (allMonitors == mon)
allMonitors = mon->next; allMonitors = mon->next;
@ -119,6 +121,7 @@ void
monitorStart(MONITOR *monitor) monitorStart(MONITOR *monitor)
{ {
monitor->handle = (*monitor->module->startMonitor)(monitor->handle); monitor->handle = (*monitor->module->startMonitor)(monitor->handle);
monitor->state |= MONITOR_RUNNING;
} }
/** /**
@ -130,6 +133,7 @@ void
monitorStop(MONITOR *monitor) monitorStop(MONITOR *monitor)
{ {
monitor->module->stopMonitor(monitor->handle); monitor->module->stopMonitor(monitor->handle);
monitor->state &= ~MONITOR_RUNNING;
} }
/** /**
@ -200,6 +204,46 @@ MONITOR *ptr;
spinlock_release(&monLock); spinlock_release(&monLock);
} }
/**
* Show a single monitor
*
* @param dcb DCB for printing output
*/
void
monitorShow(DCB *dcb, MONITOR *monitor)
{
dcb_printf(dcb, "Monitor: %p\n", monitor);
dcb_printf(dcb, "\tName: %s\n", monitor->name);
if (monitor->module->diagnostics)
monitor->module->diagnostics(dcb, monitor->handle);
}
/**
* List all the monitors
*
* @param dcb DCB for printing output
*/
void
monitorList(DCB *dcb)
{
MONITOR *ptr;
spinlock_acquire(&monLock);
ptr = allMonitors;
dcb_printf(dcb, "+----------------------+---------------------\n");
dcb_printf(dcb, "| %-20s | Status\n", "Monitor");
dcb_printf(dcb, "+----------------------+---------------------\n");
while (ptr)
{
dcb_printf(dcb, "| %-20s | %s\n", ptr->name,
ptr->state & MONITOR_RUNNING ? "Running" : "Stopped");
ptr = ptr->next;
}
dcb_printf(dcb, "+----------------------+---------------------\n");
spinlock_release(&monLock);
}
/** /**
* Find a monitor by name * Find a monitor by name
* *
@ -249,6 +293,7 @@ void
monitorSetInterval (MONITOR *mon, unsigned long interval) monitorSetInterval (MONITOR *mon, unsigned long interval)
{ {
if (mon->module->setInterval != NULL) { if (mon->module->setInterval != NULL) {
mon->interval = interval;
mon->module->setInterval(mon->handle, interval); mon->module->setInterval(mon->handle, interval);
} }
} }

View File

@ -292,7 +292,8 @@ char *stat;
} }
} }
if (server->node_ts > 0) { if (server->node_ts > 0) {
dcb_printf(dcb, "\tLast Repl Heartbeat:\t%lu\n", server->node_ts); dcb_printf(dcb, "\tLast Repl Heartbeat:\t%s",
asctime(localtime(&server->node_ts)));
} }
dcb_printf(dcb, "\tNumber of connections: %d\n", server->stats.n_connections); dcb_printf(dcb, "\tNumber of connections: %d\n", server->stats.n_connections);
dcb_printf(dcb, "\tCurrent no. of conns: %d\n", server->stats.n_current); dcb_printf(dcb, "\tCurrent no. of conns: %d\n", server->stats.n_current);

View File

@ -282,6 +282,7 @@ void printDCB(DCB *); /* Debug print routine */
void dprintAllDCBs(DCB *); /* Debug to print all DCB in the system */ void dprintAllDCBs(DCB *); /* Debug to print all DCB in the system */
void dprintDCB(DCB *, DCB *); /* Debug to print a DCB in the system */ void dprintDCB(DCB *, DCB *); /* Debug to print a DCB in the system */
void dListDCBs(DCB *); /* List all DCBs in the system */ void dListDCBs(DCB *); /* List all DCBs in the system */
void dListClients(DCB *); /* List al the client DCBs */
const char *gw_dcb_state2string(int); /* DCB state to string */ const char *gw_dcb_state2string(int); /* DCB state to string */
void dcb_printf(DCB *, const char *, ...); /* DCB version of printf */ void dcb_printf(DCB *, const char *, ...); /* DCB version of printf */
int dcb_isclient(DCB *); /* the DCB is the client of the session */ int dcb_isclient(DCB *); /* the DCB is the client of the session */

View File

@ -38,7 +38,8 @@ typedef enum {
MODULE_IN_DEVELOPMENT = 0, MODULE_IN_DEVELOPMENT = 0,
MODULE_ALPHA_RELEASE, MODULE_ALPHA_RELEASE,
MODULE_BETA_RELEASE, MODULE_BETA_RELEASE,
MODULE_GA MODULE_GA,
MODULE_EXPERIMENTAL
} MODULE_STATUS; } MODULE_STATUS;
/** /**

View File

@ -78,13 +78,21 @@ typedef struct {
*/ */
#define MONITOR_VERSION {1, 0, 0} #define MONITOR_VERSION {1, 0, 0}
/**
* Monitor state bit mask values
*/
#define MONITOR_RUNNING 0x0001
/** /**
* Representation of the running monitor. * Representation of the running monitor.
*/ */
typedef struct monitor { typedef struct monitor {
char *name; /**< The name of the monitor module */ char *name; /**< The name of the monitor module */
unsigned int state; /**< The monitor status */
MONITOR_OBJECT *module; /**< The "monitor object" */ MONITOR_OBJECT *module; /**< The "monitor object" */
void *handle; /**< Handle returned from startMonitor */ void *handle; /**< Handle returned from startMonitor */
int interval; /**< The monitor interval */
struct monitor *next; /**< Next monitor in the linked list */ struct monitor *next; /**< Next monitor in the linked list */
} MONITOR; } MONITOR;
@ -97,6 +105,8 @@ extern void monitorStop(MONITOR *);
extern void monitorStart(MONITOR *); extern void monitorStart(MONITOR *);
extern void monitorStopAll(); extern void monitorStopAll();
extern void monitorShowAll(DCB *); extern void monitorShowAll(DCB *);
extern void monitorShow(DCB *, MONITOR *);
extern void monitorList(DCB *);
extern void monitorSetId(MONITOR *, unsigned long); extern void monitorSetId(MONITOR *, unsigned long);
extern void monitorSetInterval (MONITOR *, unsigned long); extern void monitorSetInterval (MONITOR *, unsigned long);
extern void monitorSetReplicationHeartbeat(MONITOR *, int); extern void monitorSetReplicationHeartbeat(MONITOR *, int);

View File

@ -390,11 +390,24 @@ struct timeval tv;
static void static void
diagnostic(FILTER *instance, void *fsession, DCB *dcb) diagnostic(FILTER *instance, void *fsession, DCB *dcb)
{ {
QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance;
QLA_SESSION *my_session = (QLA_SESSION *)fsession; QLA_SESSION *my_session = (QLA_SESSION *)fsession;
if (my_session) if (my_session)
{ {
dcb_printf(dcb, "\t\tLogging to file %s.\n", dcb_printf(dcb, "\t\tLogging to file %s.\n",
my_session->filename); my_session->filename);
} }
if (my_instance->source)
dcb_printf(dcb, "\t\tLimit logging to connections from %s\n",
my_instance->source);
if (my_instance->userName)
dcb_printf(dcb, "\t\tLimit logging to user %s\n",
my_instance->userName);
if (my_instance->match)
dcb_printf(dcb, "\t\tInclude queries that match %s\n",
my_instance->match);
if (my_instance->nomatch)
dcb_printf(dcb, "\t\tExclude queries that match %s\n",
my_instance->nomatch);
} }

View File

@ -345,6 +345,14 @@ REGEX_SESSION *my_session = (REGEX_SESSION *)fsession;
dcb_printf(dcb, "\t\tNo. of queries altered by filter: %d\n", dcb_printf(dcb, "\t\tNo. of queries altered by filter: %d\n",
my_session->replacements); my_session->replacements);
} }
if (my_instance->source)
dcb_printf(dcb,
"\t\tReplacement limited to connections from %s\n",
my_instance->source);
if (my_instance->user)
dcb_printf(dcb,
"\t\tReplacement limit to user %s\n",
my_instance->user);
} }
/** /**

View File

@ -118,7 +118,8 @@ typedef struct {
int active; /* filter is active? */ int active; /* filter is active? */
DCB *branch_dcb; /* Client DCB for "branch" service */ DCB *branch_dcb; /* Client DCB for "branch" service */
SESSION *branch_session;/* The branch service session */ SESSION *branch_session;/* The branch service session */
int n_duped; /* Number of duplicated querise */ int n_duped; /* Number of duplicated queries */
int n_rejected; /* Number of rejected queries */
int residual; /* Any outstanding SQL text */ int residual; /* Any outstanding SQL text */
} TEE_SESSION; } TEE_SESSION;
@ -418,6 +419,10 @@ GWBUF *clone = NULL;
my_session->n_duped++; my_session->n_duped++;
SESSION_ROUTE_QUERY(my_session->branch_session, clone); SESSION_ROUTE_QUERY(my_session->branch_session, clone);
} }
else
{
my_session->n_rejected++;
}
return rval; return rval;
} }
@ -435,11 +440,28 @@ GWBUF *clone = NULL;
static void static void
diagnostic(FILTER *instance, void *fsession, DCB *dcb) diagnostic(FILTER *instance, void *fsession, DCB *dcb)
{ {
TEE_INSTANCE *my_instance = (TEE_INSTANCE *)instance;
TEE_SESSION *my_session = (TEE_SESSION *)fsession; TEE_SESSION *my_session = (TEE_SESSION *)fsession;
if (my_instance->source)
dcb_printf(dcb, "\t\tLimit to connections from %s\n",
my_instance->source);
dcb_printf(dcb, "\t\tDuplicate statements to service %s\n",
my_instance->service->name);
if (my_instance->userName)
dcb_printf(dcb, "\t\tLimit to user %s\n",
my_instance->userName);
if (my_instance->match)
dcb_printf(dcb, "\t\tInclude queries that match %s\n",
my_instance->match);
if (my_instance->nomatch)
dcb_printf(dcb, "\t\tExclude queries that match %s\n",
my_instance->nomatch);
if (my_session) if (my_session)
{ {
dcb_printf(dcb, "\t\tNo. of statements duplicated: %d.\n", dcb_printf(dcb, "\t\tNo. of statements duplicated: %d.\n",
my_session->n_duped); my_session->n_duped);
dcb_printf(dcb, "\t\tNo. of statements rejected: %d.\n",
my_session->n_rejected);
} }
} }

View File

@ -539,11 +539,40 @@ int i, inserted;
static void static void
diagnostic(FILTER *instance, void *fsession, DCB *dcb) diagnostic(FILTER *instance, void *fsession, DCB *dcb)
{ {
TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *)instance;
TOPN_SESSION *my_session = (TOPN_SESSION *)fsession; TOPN_SESSION *my_session = (TOPN_SESSION *)fsession;
int i;
dcb_printf(dcb, "\t\tReport size %d\n",
my_instance->topN);
if (my_instance->source)
dcb_printf(dcb, "\t\tLimit logging to connections from %s\n",
my_instance->source);
if (my_instance->user)
dcb_printf(dcb, "\t\tLimit logging to user %s\n",
my_instance->user);
if (my_instance->match)
dcb_printf(dcb, "\t\tInclude queries that match %s\n",
my_instance->match);
if (my_instance->exclude)
dcb_printf(dcb, "\t\tExclude queries that match %s\n",
my_instance->exclude);
if (my_session) if (my_session)
{ {
dcb_printf(dcb, "\t\tLogging to file %s.\n", dcb_printf(dcb, "\t\tLogging to file %s.\n",
my_session->filename); my_session->filename);
dcb_printf(dcb, "\t\tCurrent Top %d:\n", my_instance->topN);
for (i = 0; i < my_instance->topN; i++)
{
if (my_session->top[i]->sql)
{
dcb_printf(dcb, "\t\t%d place:\n", i + 1);
dcb_printf(dcb, "\t\t\tExecution time: %.3f seconds\n",
(double)((my_session->top[i]->duration.tv_sec * 1000)
+ (my_session->top[i]->duration.tv_usec / 1000)) / 1000);
dcb_printf(dcb, "\t\t\tSQL: %s\n",
my_session->top[i]->sql);
}
}
} }
} }

View File

@ -128,6 +128,10 @@ struct subcommand showoptions[] = {
"Show all currently loaded modules", "Show all currently loaded modules",
"Show all currently loaded modules", "Show all currently loaded modules",
{0, 0, 0} }, {0, 0, 0} },
{ "monitor", 1, monitorShow,
"Show the monitor details",
"Show the monitor details",
{ARG_TYPE_MONITOR, 0, 0} },
{ "monitors", 0, monitorShowAll, { "monitors", 0, monitorShowAll,
"Show the monitors that are configured", "Show the monitors that are configured",
"Show the monitors that are configured", "Show the monitors that are configured",
@ -168,6 +172,10 @@ struct subcommand showoptions[] = {
* The subcommands of the list command * The subcommands of the list command
*/ */
struct subcommand listoptions[] = { struct subcommand listoptions[] = {
{ "clients", 0, dListClients,
"List all the client connections to MaxScale",
"List all the client connections to MaxScale",
{0, 0, 0} },
{ "dcbs", 0, dListDCBs, { "dcbs", 0, dListDCBs,
"List all the DCBs active within MaxScale", "List all the DCBs active within MaxScale",
"List all the DCBs active within MaxScale", "List all the DCBs active within MaxScale",
@ -181,8 +189,12 @@ struct subcommand listoptions[] = {
"List all the listeners defined within MaxScale", "List all the listeners defined within MaxScale",
{0, 0, 0} }, {0, 0, 0} },
{ "modules", 0, dprintAllModules, { "modules", 0, dprintAllModules,
"Show all currently loaded modules", "List all currently loaded modules",
"Show all currently loaded modules", "List all currently loaded modules",
{0, 0, 0} },
{ "monitors", 0, monitorList,
"List all monitors",
"List all monitors",
{0, 0, 0} }, {0, 0, 0} },
{ "services", 0, dListServices, { "services", 0, dListServices,
"List all the services defined within MaxScale", "List all the services defined within MaxScale",
@ -307,11 +319,23 @@ struct subcommand reloadoptions[] = {
static void enable_log_action(DCB *, char *); static void enable_log_action(DCB *, char *);
static void disable_log_action(DCB *, char *); static void disable_log_action(DCB *, char *);
static void enable_monitor_replication_heartbeat(DCB *dcb, MONITOR *monitor);
static void disable_monitor_replication_heartbeat(DCB *dcb, MONITOR *monitor);
static void enable_service_root(DCB *dcb, SERVICE *service);
static void disable_service_root(DCB *dcb, SERVICE *service);
/** /**
* * The subcommands of the enable command * * The subcommands of the enable command
* */ * */
struct subcommand enableoptions[] = { struct subcommand enableoptions[] = {
{
"heartbeat",
1,
enable_monitor_replication_heartbeat,
"Enable the monitor replication heartbeat, pass a monitor name as argument",
"Enable the monitor replication heartbeat, pass a monitor name as argument",
{ARG_TYPE_MONITOR, 0, 0}
},
{ {
"log", "log",
1, 1,
@ -322,6 +346,14 @@ struct subcommand enableoptions[] = {
"message E.g. enable log message.", "message E.g. enable log message.",
{ARG_TYPE_STRING, 0, 0} {ARG_TYPE_STRING, 0, 0}
}, },
{
"root",
1,
enable_service_root,
"Enable root access to a service, pass a service name to enable root access",
"Enable root access to a service, pass a service name to enable root access",
{ARG_TYPE_SERVICE, 0, 0}
},
{ {
NULL, NULL,
0, 0,
@ -337,24 +369,40 @@ struct subcommand enableoptions[] = {
* * The subcommands of the disable command * * The subcommands of the disable command
* */ * */
struct subcommand disableoptions[] = { struct subcommand disableoptions[] = {
{ {
"log", "heartbeat",
1, 1,
disable_log_action, disable_monitor_replication_heartbeat,
"Disable Log for MaxScale, Options: debug | trace | error | message " "Disable the monitor replication heartbeat",
"E.g. disable log debug", "Disable the monitor replication heartbeat",
"Disable Log for MaxScale, Options: debug | trace | error | message " {ARG_TYPE_MONITOR, 0, 0}
"E.g. disable log debug", },
{ARG_TYPE_STRING, 0, 0} {
}, "log",
{ 1,
disable_log_action,
"Disable Log for MaxScale, Options: debug | trace | error | message "
"E.g. disable log debug",
"Disable Log for MaxScale, Options: debug | trace | error | message "
"E.g. disable log debug",
{ARG_TYPE_STRING, 0, 0}
},
{
"root",
1,
disable_service_root,
"Disable root access to a service",
"Disable root access to a service",
{ARG_TYPE_SERVICE, 0, 0}
},
{
NULL, NULL,
0, 0,
NULL, NULL,
NULL, NULL,
NULL, NULL,
{0, 0, 0} {0, 0, 0}
} }
}; };
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
@ -850,7 +898,7 @@ unsigned int bitvalue;
static void static void
reload_dbusers(DCB *dcb, SERVICE *service) reload_dbusers(DCB *dcb, SERVICE *service)
{ {
dcb_printf(dcb, "Loaded %d database users for server %s.\n", dcb_printf(dcb, "Loaded %d database users for service %s.\n",
reload_mysql_users(service), service->name); reload_mysql_users(service), service->name);
} }
@ -958,6 +1006,55 @@ restart_monitor(DCB *dcb, MONITOR *monitor)
monitorStart(monitor); monitorStart(monitor);
} }
/**
* Enable replication heartbeat for a monitor
*
* @param dcb Connection to user interface
* @param monitor The monitor
*/
static void
enable_monitor_replication_heartbeat(DCB *dcb, MONITOR *monitor)
{
monitorSetReplicationHeartbeat(monitor, 1);
}
/**
* Disable replication heartbeat for a monitor
*
* @param dcb Connection to user interface
* @param monitor The monitor
*/
static void
disable_monitor_replication_heartbeat(DCB *dcb, MONITOR *monitor)
{
monitorSetReplicationHeartbeat(monitor, 0);
}
/**
* Enable root access to a service
*
* @param dcb Connection to user interface
* @param service The service
*/
static void
enable_service_root(DCB *dcb, SERVICE *service)
{
serviceEnableRootUser(service, 1);
}
/**
* Disable root access to a service
*
* @param dcb Connection to user interface
* @param service The service
*/
static void
disable_service_root(DCB *dcb, SERVICE *service)
{
serviceEnableRootUser(service, 0);
}
/** /**
* The log enable action * The log enable action
*/ */