Further development for web interface

Explicitly disabled https from libmicrohttpd (for now)
Created key and certificate, although not in use (for now)
Embedded font-awesome CSS
Added support for time range for MySQL and System
Added support for *_hour tables
Enabled digest auth in web ui (for now hardcoded credential, will fix in future commits)
Drafted a home page (not ready yet)
pull/1269/head
René Cannaò 9 years ago
parent 7f0f037480
commit 8adf68c002

2
deps/Makefile vendored

@ -20,7 +20,7 @@ endif
libmicrohttpd/libmicrohttpd/src/microhttpd/.libs/libmicrohttpd.a:
cd libmicrohttpd && rm -rf libmicrohttpd-0.9.55 || true
cd libmicrohttpd && tar -zxf libmicrohttpd-0.9.55.tar.gz
cd libmicrohttpd/libmicrohttpd && ./configure && CC=${CC} CXX=${CXX} ${MAKE}
cd libmicrohttpd/libmicrohttpd && ./configure --disable-https && CC=${CC} CXX=${CXX} ${MAKE}
microhttpd: libmicrohttpd/libmicrohttpd/src/microhttpd/.libs/libmicrohttpd.a
cityhash/cityhash/src/.libs/libcityhash.a:

@ -55,9 +55,9 @@ class ProxySQL_Statistics {
void MySQL_Threads_Handler_sets(SQLite3_result *);
void system_cpu_sets();
void system_memory_sets();
SQLite3_result * get_mysql_metrics();
SQLite3_result * get_system_cpu_metrics();
SQLite3_result * get_system_memory_metrics();
SQLite3_result * get_mysql_metrics(int interval);
SQLite3_result * get_system_cpu_metrics(int interval);
SQLite3_result * get_system_memory_metrics(int interval);
};
#endif /* CLASS_PROXYSQL_STATISTICS_H */

@ -73,7 +73,7 @@ default: libproxysql.a
_OBJ = c_tokenizer.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
_OBJ_CXX = ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo SpookyV2.oo MySQL_Authentication.oo gen_utils.oo sqlite3db.oo mysql_connection.oo MySQL_HostGroups_Manager.oo mysql_data_stream.oo MySQL_Thread.oo MySQL_Session.oo MySQL_Protocol.oo mysql_backend.oo Query_Processor.oo ProxySQL_Admin.oo MySQL_Monitor.oo MySQL_Logger.oo thread.oo MySQL_PreparedStatement.oo ProxySQL_Cluster.oo SQLite3_Server.oo ClickHouse_Authentication.oo ClickHouse_Server.oo ProxySQL_Statistics.oo Chart_bundle_js.oo ProxySQL_HTTP_Server.oo
_OBJ_CXX = ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo SpookyV2.oo MySQL_Authentication.oo gen_utils.oo sqlite3db.oo mysql_connection.oo MySQL_HostGroups_Manager.oo mysql_data_stream.oo MySQL_Thread.oo MySQL_Session.oo MySQL_Protocol.oo mysql_backend.oo Query_Processor.oo ProxySQL_Admin.oo MySQL_Monitor.oo MySQL_Logger.oo thread.oo MySQL_PreparedStatement.oo ProxySQL_Cluster.oo SQLite3_Server.oo ClickHouse_Authentication.oo ClickHouse_Server.oo ProxySQL_Statistics.oo Chart_bundle_js.oo ProxySQL_HTTP_Server.oo font-awesome.min.css.oo
OBJ_CXX = $(patsubst %,$(ODIR)/%,$(_OBJ_CXX))
%.ko: %.cpp

@ -40,6 +40,7 @@
#define READ_ONLY_ON "\x01\x00\x00\x01\x02\x23\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x0d\x56\x61\x72\x69\x61\x62\x6c\x65\x5f\x6e\x61\x6d\x65\x00\x0c\x21\x00\x0f\x00\x00\x00\xfd\x01\x00\x1f\x00\x00\x1b\x00\x00\x03\x03\x64\x65\x66\x00\x00\x00\x05\x56\x61\x6c\x75\x65\x00\x0c\x21\x00\x0f\x00\x00\x00\xfd\x01\x00\x1f\x00\x00\x05\x00\x00\x04\xfe\x00\x00\x02\x00\x0d\x00\x00\x05\x09\x72\x65\x61\x64\x5f\x6f\x6e\x6c\x79\x02\x4f\x4e\x05\x00\x00\x06\xfe\x00\x00\x02\x00"
struct MHD_Daemon *Admin_HTTP_Server;
extern ProxySQL_Statistics *GloProxyStats;
@ -3718,7 +3719,10 @@ void ProxySQL_Admin::flush_admin_variables___database_to_runtime(SQLite3DB *db,
Admin_HTTP_Server = MHD_start_daemon(MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
variables.web_port,
NULL, NULL, http_handler, NULL,
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120, MHD_OPTION_STRICT_FOR_CLIENT, (int) 1, MHD_OPTION_END);
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120, MHD_OPTION_STRICT_FOR_CLIENT, (int) 1,
MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) 4,
MHD_OPTION_NONCE_NC_SIZE, (unsigned int) 300,
MHD_OPTION_END);
} else {
MHD_stop_daemon(Admin_HTTP_Server);
Admin_HTTP_Server = NULL;
@ -3732,7 +3736,10 @@ void ProxySQL_Admin::flush_admin_variables___database_to_runtime(SQLite3DB *db,
Admin_HTTP_Server = MHD_start_daemon(MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
variables.web_port,
NULL, NULL, http_handler, NULL,
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120, MHD_OPTION_STRICT_FOR_CLIENT, (int) 1, MHD_OPTION_END);
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120, MHD_OPTION_STRICT_FOR_CLIENT, (int) 1,
MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) 4,
MHD_OPTION_NONCE_NC_SIZE, (unsigned int) 300,
MHD_OPTION_END);
}
variables.web_port_old = variables.web_port;
}

@ -40,9 +40,120 @@
extern ProxySQL_Statistics *GloProxyStats;
extern char * Chart_bundle_js_c;
extern char * font_awesome;
#define RATE_LIMIT_PAGE "<html><head><title>Rate Limit Page</title></head><body>Rate Limit Reached</body></html>"
#define DENIED "<html><head><title>ProxySQL status page</title></head><body>Access denied</body></html>"
#define OPAQUE "733b20011778ce330631c9afof70a870baddd964"
static char *div1= (char *)"<div style=\"margin-bottom: 3px;\"><a href=stats?metric=";
static char *style1 = (char *)" style=\"color: #1a3854 ; background-color: white; font-size: 12px; font-family: Verdana, sans-serif; border: 0px; text-decoration: none; padding-left: 5px; padding-right: 5px;\">";
static char *style2 = (char *)" style=\"color: #2969a5 ; background-color: white; font-size: 12px; font-family: Verdana, sans-serif; border: 0px; text-decoration: none; padding-left: 5px; padding-right: 5px;\">";
static char *generate_home() {
char *s = NULL;
string html = "";
char *link = (char *)"<a href=stats?metric=\"%s\" %s>30m</a>";
html.append("<div class=\"menu\" style=\"height: auto;\">\n");
//<span style=\"float: right; width: 20%;\">\n<div style=\"border-bottom-style: solid; border-bottom-color: #1a3854; border-bottom-width: 1px; margin-bottom: 3px; color: #1a3854 ; background-color: white; font-size: 13px; font-family: Verdana, sans-serif; font-weight: bold; text-decoration: none; padding-left: 5px; padding-right: 5px;\">&nbsp</div>\n");
// html.append(div1); html.append(base); html.append("&interval=1800"); html.append(style1); html.append("Last 1/2 hour</a></div>\n");
// html.append(div1); html.append(base); html.append("&interval=3600"); html.append(style1); html.append("Last 1 hour</a></div>\n");
// html.append(div1); html.append(base); html.append("&interval=7200"); html.append(style1); html.append("Last 2 hours</a></div>\n");
// html.append(div1); html.append(base); html.append("&interval=28800"); html.append(style1); html.append("Last 8 hours</a></div>\n");
html.append("<span style=\"float: left; width: 15%;\">\n<div><p></p></div>\n<div style=\"border-bottom-style: solid; border-bottom-color: #1a3854; border-bottom-width: 1px; margin-bottom: 3px; color: #2969a5 ; background-color: white; font-size: 13px; font-family: Verdana, sans-serif; font-weight: bold; text-decoration: none; padding-left: 5px; padding-right: 5px;\">Category:</div>\n");
html.append("<div style=\"margin-bottom: 3px;\"><a href=\"/\""); html.append(style2); html.append("Home</a></div>\n");
html.append(div1); html.append("system"); html.append(style2); html.append("System</a></div>\n");
html.append(div1); html.append("mysql"); html.append(style2); html.append("MySQL</a></div>\n");
html.append(div1); html.append("cache"); html.append(style2); html.append("Query Cache</a></div>\n");
html.append("</span>\n</div>\n");
html.append("<span style=\"float: left; width: 100%;\">\n");
html.append("<div style=\"height: auto;\">\n");
html.append("<p></p>\n");
html.append("<p></p>\n");
html.append("<h2 style=\"font-size: 25px; margin-top: 0em; margin-bottom: 0em;\">General information</h2>\n<hr style=\"align: centre\" width=\"100%\">\n");
html.append("<table style=\"font-size: 15px;\" border=0 width=\"100%\">\n");
html.append("<tr width=\"100%\">\n");
//html.append("<td style=\"align: left; width: 33%\">\n");
html.append("<td width=\"33%\">\n");
html.append("<b>Uptime = </b> 0d 0h00m44s<br>\n");
html.append("<b>OS version = </b>CentOS 7.3<br>\n");
html.append("<b>Worker threads = </b>8<br>\n");
html.append("<b>Idle threads = </b>enabled<br>\n");
html.append("<b>Monitor = </b>enabled<br>\n");
html.append("</td>\n");
html.append("<td width=\"33%\">\n");
html.append("<b>ProxySQL version = </b>1.4.3<br>\n");
html.append("<b>ProxySQL latest = </b>1.4.4<br>\n");
html.append("</td>\n");
html.append("<td width=\"33%\">\n");
//html.append("<td style=\"align: left; width: 33%\">\n");
html.append("<b>ProxySQL version = </b>1.4.3<br>\n");
html.append("<b>ProxySQL latest = </b>1.4.4<br>\n");
html.append("</td>\n");
html.append("</tr>\n");
html.append("</table>\n");
html.append("</div></span>\n");
s = strdup(html.c_str());
return s;
}
static char *generate_buttons(char *base) {
char *s = NULL;
//char *style = (char *)"style=\"color: white ; background-color: blue; font-size: 14px; border: 2px solid; border-radius: 5px; text-decoration: none; padding-left: 5px; padding-right: 5px;\"";
string html = "<div class=\"menu\" style=\"height: auto;\">\n<span style=\"float: right; width: 20%;\">\n<div style=\"border-bottom-style: solid; border-bottom-color: #1a3854; border-bottom-width: 1px; margin-bottom: 3px; color: #1a3854 ; background-color: white; font-size: 13px; font-family: Verdana, sans-serif; font-weight: bold; text-decoration: none; padding-left: 5px; padding-right: 5px;\">&nbsp</div>\n";
html.append(div1); html.append(base); html.append("&interval=1800"); html.append(style1); html.append("Last 1/2 hour</a></div>\n");
html.append(div1); html.append(base); html.append("&interval=3600"); html.append(style1); html.append("Last 1 hour</a></div>\n");
html.append(div1); html.append(base); html.append("&interval=7200"); html.append(style1); html.append("Last 2 hours</a></div>\n");
html.append(div1); html.append(base); html.append("&interval=28800"); html.append(style1); html.append("Last 8 hours</a></div>\n");
html.append("</span>\n<span style=\"float: right; width: 20%;\">\n<div style=\"border-bottom-style: solid; border-bottom-color: #1a3854; border-bottom-width: 1px; margin-bottom: 3px; color: #1a3854 ; background-color: white; font-size: 13px; font-family: Verdana, sans-serif; font-weight: bold; text-decoration: none; padding-left: 5px; padding-right: 5px;\">Time range:</div>\n");
html.append(div1); html.append(base); html.append("&interval=86400"); html.append(style1); html.append("Last 1 day</a></div>\n");
html.append(div1); html.append(base); html.append("&interval=259200"); html.append(style1); html.append("Last 3 days</a></div>\n");
html.append(div1); html.append(base); html.append("&interval=604800"); html.append(style1); html.append("Last 7 days</a></div>\n");
html.append(div1); html.append(base); html.append("&interval=2592000"); html.append(style1); html.append("Last 1 month</a></div>\n");
html.append(div1); html.append(base); html.append("&interval=7776000"); html.append(style1); html.append("Last 3 months</a></div>\n");
html.append("</span>\n</div>\n");
html.append("<div class=\"menu\" style=\"height: auto;\">\n");
//<span style=\"float: right; width: 20%;\">\n<div style=\"border-bottom-style: solid; border-bottom-color: #1a3854; border-bottom-width: 1px; margin-bottom: 3px; color: #1a3854 ; background-color: white; font-size: 13px; font-family: Verdana, sans-serif; font-weight: bold; text-decoration: none; padding-left: 5px; padding-right: 5px;\">&nbsp</div>\n");
// html.append(div1); html.append(base); html.append("&interval=1800"); html.append(style1); html.append("Last 1/2 hour</a></div>\n");
// html.append(div1); html.append(base); html.append("&interval=3600"); html.append(style1); html.append("Last 1 hour</a></div>\n");
// html.append(div1); html.append(base); html.append("&interval=7200"); html.append(style1); html.append("Last 2 hours</a></div>\n");
// html.append(div1); html.append(base); html.append("&interval=28800"); html.append(style1); html.append("Last 8 hours</a></div>\n");
html.append("<span style=\"float: left; width: 15%;\">\n<div><p></p></div>\n<div style=\"border-bottom-style: solid; border-bottom-color: #1a3854; border-bottom-width: 1px; margin-bottom: 3px; color: #2969a5 ; background-color: white; font-size: 13px; font-family: Verdana, sans-serif; font-weight: bold; text-decoration: none; padding-left: 5px; padding-right: 5px;\">Category:</div>\n");
html.append("<div style=\"margin-bottom: 3px;\"><a href=\"/\""); html.append(style2); html.append("Home</a></div>\n");
html.append(div1); html.append("system"); html.append(style2); html.append("System</a></div>\n");
html.append(div1); html.append("mysql"); html.append(style2); html.append("MySQL</a></div>\n");
html.append(div1); html.append("cache"); html.append(style2); html.append("Query Cache</a></div>\n");
html.append("</span>\n</div>\n");
/*
html.append("<a href=stats?metric="); html.append(base); html.append("?interval=30m "); html.append(style); html.append(">30mins</a>");
html.append("<a href=stats?metric="); html.append(base); html.append("?interval=60m "); html.append(style); html.append(">60mins</a>");
html.append("<a href=stats?metric="); html.append(base); html.append("?interval=120m "); html.append(style); html.append(">120mins</a>");
html.append("<a href=stats?metric="); html.append(base); html.append("?interval=8h "); html.append(style); html.append(">8hrs</a>");
html.append("<a href=stats?metric="); html.append(base); html.append("?interval=24h "); html.append(style); html.append(">24hrs</a>");
html.append("<a href=stats?metric="); html.append(base); html.append("?interval=72h "); html.append(style); html.append(">72hrs</a>");
html.append("<a href=stats?metric="); html.append(base); html.append("?interval=7d "); html.append(style); html.append(">7days</a>");
html.append("<a href=stats?metric="); html.append(base); html.append("?interval=30d "); html.append(style); html.append(">30days</a>");
html.append("<a href=stats?metric="); html.append(base); html.append("?interval=90d "); html.append(style); html.append(">90days</a>");
*/
s = strdup(html.c_str());
return s;
}
char * ProxySQL_HTTP_Server::extract_values(SQLite3_result *result, int idx, bool relative, double mult) {
string s = "[";
@ -102,9 +213,39 @@ int ProxySQL_HTTP_Server::handler(void *cls, struct MHD_Connection *connection,
struct MHD_Response *response;
int ret;
char *username;
const char *password = "testpass";
const char *realm = "Access to ProxySQL status page";
username = MHD_digest_auth_get_username(connection);
if (username == NULL || strcmp(username,"stats")) {
response = MHD_create_response_from_buffer(strlen(DENIED), (void *)DENIED, MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_auth_fail_response(connection, realm, OPAQUE, response, MHD_NO);
MHD_destroy_response(response);
return ret;
}
ret = MHD_digest_auth_check(connection, realm, username, password, 300);
free(username);
if ( (ret == MHD_INVALID_NONCE) || (ret == MHD_NO) ) {
response = MHD_create_response_from_buffer(strlen(DENIED), (void *)DENIED, MHD_RESPMEM_PERSISTENT);
if (NULL == response)
return MHD_NO;
ret = MHD_queue_auth_fail_response(connection, realm, OPAQUE, response, (ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO);
MHD_destroy_response(response);
return ret;
}
char *valmetric = NULL;
char *valinterval = NULL;
char *valunit = NULL;
char *interval_s = NULL;
int interval_i = 1800;
time_t now = time(NULL);
if (now != cur_time) {
@ -130,14 +271,33 @@ int ProxySQL_HTTP_Server::handler(void *cls, struct MHD_Connection *connection,
if (strcmp(url,"/stats")==0) {
valmetric = (char *)MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, (char *)"metric");
/*
valinterval = (char *)MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, (char *)"points");
valunit = (char *)MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, (char *)"unit");
*/
interval_s = (char *)MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, (char *)"interval");
//fprintf(stderr,"Interval = %s\n", interval_s);
if (valmetric == NULL) {
response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE), (void *) EMPTY_PAGE, MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response (response);
return ret;
}
int tmp_ = 0;
if (interval_s) {
tmp_ = atoi(interval_s);
}
switch (tmp_) {
case 1800:
case 3600:
case 7200:
case 28800:
interval_i = tmp_;
break;
default:
break;
}
/*
if (valunit == NULL) {
valunit = (char *)"second";
}
@ -158,19 +318,27 @@ int ProxySQL_HTTP_Server::handler(void *cls, struct MHD_Connection *connection,
valinterval = (char *)"365";
}
}
*/
if (strcmp(valmetric,"system")==0) {
string *s = generate_header((char *)"ProxySQL Graphs");
char *buttons = generate_buttons((char *)"system");
s->append(buttons);
free(buttons);
s->append("<div class=\"graphs\" style=\"clear: both; height: auto;\">\n");
string *s1 = generate_canvas((char *)"myChart1");
s->append(s1->c_str());
s->append("<p></p>\n");
s1 = generate_canvas((char *)"myChart2");
s->append(s1->c_str());
s->append("<p></p>\n");
s1 = generate_canvas((char *)"myChart3");
s->append(s1->c_str());
s->append("<p></p>\n");
s1 = generate_canvas((char *)"myChart4");
s->append(s1->c_str());
SQLite3_result *cpu_sqlite = GloProxyStats->get_system_cpu_metrics();
SQLite3_result *memory_sqlite = GloProxyStats->get_system_memory_metrics();
s->append("</div>\n");
SQLite3_result *cpu_sqlite = GloProxyStats->get_system_cpu_metrics(interval_i);
SQLite3_result *memory_sqlite = GloProxyStats->get_system_memory_metrics(interval_i);
//SQLite3_result *mysql_metrics_sqlite = GloProxyStats->get_mysql_metrics();
char **nm = NULL;
char **nl = NULL;
@ -237,17 +405,25 @@ int ProxySQL_HTTP_Server::handler(void *cls, struct MHD_Connection *connection,
if (strcmp(valmetric,"mysql")==0) {
string *s = generate_header((char *)"ProxySQL Graphs");
char *buttons = generate_buttons((char *)"mysql");
s->append(buttons);
free(buttons);
s->append("<div class=\"graphs\" style=\"clear: both; height: auto;\">\n");
string *s1 = generate_canvas((char *)"myChart1");
s->append(s1->c_str());
s->append("<p></p>\n");
s1 = generate_canvas((char *)"myChart2");
s->append(s1->c_str());
s->append("<p></p>\n");
s1 = generate_canvas((char *)"myChart3");
s->append(s1->c_str());
s->append("<p></p>\n");
s1 = generate_canvas((char *)"myChart4");
s->append(s1->c_str());
s->append("</div>\n");
//SQLite3_result *cpu_sqlite = GloProxyStats->get_system_cpu_metrics();
//SQLite3_result *memory_sqlite = GloProxyStats->get_system_memory_metrics();
SQLite3_result *mysql_metrics_sqlite = GloProxyStats->get_mysql_metrics();
SQLite3_result *mysql_metrics_sqlite = GloProxyStats->get_mysql_metrics(interval_i);
char **nm = NULL;
char **nl = NULL;
char **nv = NULL;
@ -315,7 +491,7 @@ int ProxySQL_HTTP_Server::handler(void *cls, struct MHD_Connection *connection,
free(ts);
s->append("</body></html>");
response = MHD_create_response_from_buffer(s->length(), (void *) s->c_str(), MHD_RESPMEM_MUST_COPY);
response = MHD_create_response_from_buffer(s->length(), (void *) s->c_str(), MHD_RESPMEM_MUST_COPY);
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
delete s;
@ -324,11 +500,29 @@ int ProxySQL_HTTP_Server::handler(void *cls, struct MHD_Connection *connection,
}
if (strcmp(url,"/Chart.bundle.js")==0) {
response = MHD_create_response_from_buffer(strlen(Chart_bundle_js_c), Chart_bundle_js_c, MHD_RESPMEM_PERSISTENT);
response = MHD_create_response_from_buffer(strlen(Chart_bundle_js_c), Chart_bundle_js_c, MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;
}
if (strcmp(url,"/font-awesome.min.css")==0) {
response = MHD_create_response_from_buffer(strlen(font_awesome), font_awesome, MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;
}
if (strcmp(url,"/")==0) {
string *s = generate_header((char *)"ProxySQL Home");
char *home = generate_home();
s->append(home);
free(home);
s->append("</body></html>");
response = MHD_create_response_from_buffer(s->length(), (void *) s->c_str(), MHD_RESPMEM_MUST_COPY);
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
delete s;
return ret;
}
response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE), (void *) EMPTY_PAGE, MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response (response);
@ -340,15 +534,21 @@ string * ProxySQL_HTTP_Server::generate_header(char *s) {
string *a = new string();
a->append("<head>\n<title>");
a->append(s);
a->append("</title>\n<script src=\"/Chart.bundle.js\"></script>\n</head>\n<body>\n");
a->append("</title>\n");
a->append("<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,600,900|Fira+Mono\">\n");
a->append("<link rel=\"stylesheet\" href=\"http://www.proxysql.com/assets/css/main-bundle.min.css\">\n");
//a->append("<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css\">\n");
a->append("<link rel=\"stylesheet\" href=\"/font-awesome.min.css\">\n");
a->append("<script src=\"/Chart.bundle.js\"></script>\n</head>\n<body style=\"background-color: white;\">\n");
a->append("<header class=\"header cf \" role=\"banner\">\n<a class=\"brand\" href=\"http://www.proxysql.com\"><span><strong>Proxy</strong>SQL</span>\n</a>");
return a;
}
string * ProxySQL_HTTP_Server::generate_canvas(char *s) {
string *a = new string();
a->append("<div class=\"wrapper\" style=\"width: 700px; height: 300px\"><canvas id=\"");
a->append("<div class=\"wrapper\" style=\"width: 750px; height: 350px\"><canvas id=\"");
a->append(s);
a->append("\" width=\"650\" height=\"280\"></canvas></div>\n");
a->append("\" width=\"700\" height=\"330\"></canvas></div>\n");
return a;
}
ProxySQL_HTTP_Server::ProxySQL_HTTP_Server() {

@ -173,11 +173,46 @@ bool ProxySQL_Statistics::system_memory_timetoget(unsigned long long curtime) {
return false;
}
SQLite3_result * ProxySQL_Statistics::get_mysql_metrics() {
SQLite3_result * ProxySQL_Statistics::get_mysql_metrics(int interval) {
SQLite3_result *resultset = NULL;
int cols;
int affected_rows;
char *error = NULL;
char *query = NULL;
char *query1 = (char *)"SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, Client_Connections_aborted, Client_Connections_connected, Client_Connections_created, Server_Connections_aborted, Server_Connections_connected, Server_Connections_created, ConnPool_get_conn_failure, ConnPool_get_conn_immediate, ConnPool_get_conn_success, Questions FROM mysql_connections WHERE timestamp BETWEEN %d AND %d ORDER BY timestamp";
char *query2 = (char *)"SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, Client_Connections_aborted, Client_Connections_connected, Client_Connections_created, Server_Connections_aborted, Server_Connections_connected, Server_Connections_created, ConnPool_get_conn_failure, ConnPool_get_conn_immediate, ConnPool_get_conn_success, Questions FROM mysql_connections_hour WHERE timestamp BETWEEN %d AND %d ORDER BY timestamp";
time_t ts = time(NULL);
switch (interval) {
case 1800:
case 3600:
case 7200:
query = (char *)malloc(strlen(query1)+128);
sprintf(query, query1, ts-interval, ts);
break;
case 28800:
case 86400:
case 259200:
case 604800:
case 2592000:
case 7776000:
query = (char *)malloc(strlen(query2)+128);
sprintf(query, query2, ts-interval, ts);
break;
default:
assert(0);
break;
}
//fprintf(stderr,"%s\n", query);
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
free(query);
if (error) {
if (resultset) {
delete resultset;
resultset = NULL;
}
free(error);
}
/*
char *query = (char *)"SELECT * FROM (SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, Client_Connections_aborted, Client_Connections_connected, Client_Connections_created, Server_Connections_aborted, Server_Connections_connected, Server_Connections_created, ConnPool_get_conn_failure, ConnPool_get_conn_immediate, ConnPool_get_conn_success, Questions FROM mysql_connections ORDER BY timestamp DESC LIMIT 100) t ORDER BY ts";
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
if (error) {
@ -187,16 +222,42 @@ SQLite3_result * ProxySQL_Statistics::get_mysql_metrics() {
}
free(error);
}
*/
return resultset;
}
SQLite3_result * ProxySQL_Statistics::get_system_memory_metrics() {
SQLite3_result * ProxySQL_Statistics::get_system_memory_metrics(int interval) {
SQLite3_result *resultset = NULL;
int cols;
int affected_rows;
char *error = NULL;
char *query = (char *)"SELECT * FROM (SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, allocated, resident, active, mapped, metadata, retained FROM system_memory ORDER BY timestamp DESC LIMIT 100) t ORDER BY ts";
char *query = NULL;
char *query1 = (char *)"SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, allocated, resident, active, mapped, metadata, retained FROM system_memory WHERE timestamp BETWEEN %d AND %d ORDER BY timestamp";
char *query2 = (char *)"SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, allocated, resident, active, mapped, metadata, retained FROM system_memory_hour WHERE timestamp BETWEEN %d AND %d ORDER BY timestamp";
time_t ts = time(NULL);
switch (interval) {
case 1800:
case 3600:
case 7200:
query = (char *)malloc(strlen(query1)+128);
sprintf(query, query1, ts-interval, ts);
break;
case 28800:
case 86400:
case 259200:
case 604800:
case 2592000:
case 7776000:
query = (char *)malloc(strlen(query2)+128);
sprintf(query, query2, ts-interval, ts);
break;
default:
assert(0);
break;
}
//fprintf(stderr,"%s\n", query);
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
free(query);
if (error) {
if (resultset) {
delete resultset;
@ -207,13 +268,37 @@ SQLite3_result * ProxySQL_Statistics::get_system_memory_metrics() {
return resultset;
}
SQLite3_result * ProxySQL_Statistics::get_system_cpu_metrics() {
SQLite3_result * ProxySQL_Statistics::get_system_cpu_metrics(int interval) {
SQLite3_result *resultset = NULL;
int cols;
int affected_rows;
char *error = NULL;
char *query = (char *)"SELECT * FROM (SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, tms_utime, tms_stime FROM system_cpu ORDER BY timestamp DESC LIMIT 100) t ORDER BY ts";
char *query = NULL;
char *query1 = (char *)"SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, tms_utime, tms_stime FROM system_cpu WHERE timestamp BETWEEN %d AND %d ORDER BY timestamp";
char *query2 = (char *)"SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, tms_utime, tms_stime FROM system_cpu_hour WHERE timestamp BETWEEN %d AND %d ORDER BY timestamp";
time_t ts = time(NULL);
switch (interval) {
case 1800:
case 3600:
case 7200:
query = (char *)malloc(strlen(query1)+128);
sprintf(query, query1, ts-interval, ts);
break;
case 28800:
case 259200:
case 604800:
case 2592000:
case 7776000:
query = (char *)malloc(strlen(query2)+128);
sprintf(query, query2, ts-interval, ts);
break;
default:
assert(0);
break;
}
//fprintf(stderr,"%s\n", query);
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
free(query);
if (error) {
if (resultset) {
delete resultset;
@ -250,7 +335,7 @@ void ProxySQL_Statistics::system_cpu_sets() {
int cols;
int affected_rows;
char *error = NULL;
char *query = (char *)"SELECT MAX(timestamp) FROM system_cpu";
char *query = (char *)"SELECT MAX(timestamp) FROM system_cpu_hour";
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
if (error) {
if (resultset) {
@ -261,15 +346,20 @@ void ProxySQL_Statistics::system_cpu_sets() {
} else {
char buf[256];
if (resultset->rows_count == 0) {
sprintf(buf,"INSERT INTO system_cpu_hour SELECT timestamp/3600 , SUM(tms_utime), SUM(tms_stime) FROM system_cpu WHERE timestamp < %ld GROUP BY timestamp/3600", (ts/3600)*3600);
sprintf(buf,"INSERT INTO system_cpu_hour SELECT timestamp/3600*3600 , SUM(tms_utime), SUM(tms_stime) FROM system_cpu WHERE timestamp < %ld GROUP BY timestamp/3600", (ts/3600)*3600);
statsdb_disk->execute(buf);
} else {
SQLite3_row *r = resultset->rows[0];
time_t t = atol(r->fields[0]);
if (ts >= t + 3600) {
sprintf(buf,"INSERT INTO system_cpu_hour SELECT timestamp/3600 , SUM(tms_utime), SUM(tms_stime) FROM system_cpu WHERE timestamp >= %ld AND timestamp < %ld GROUP BY timestamp/3600", t+3600 , (ts/3600)*3600);
if (r->fields[0]) {
time_t t = atol(r->fields[0]);
if (ts >= t + 3600) {
sprintf(buf,"INSERT INTO system_cpu_hour SELECT timestamp/3600*3600 , SUM(tms_utime), SUM(tms_stime) FROM system_cpu WHERE timestamp >= %ld AND timestamp < %ld GROUP BY timestamp/3600", t+3600 , (ts/3600)*3600);
statsdb_disk->execute(buf);
}
} else {
sprintf(buf,"INSERT INTO system_cpu_hour SELECT timestamp/3600*3600 , SUM(tms_utime), SUM(tms_stime) FROM system_cpu WHERE timestamp < %ld GROUP BY timestamp/3600", (ts/3600)*3600);
statsdb_disk->execute(buf);
}
}
}
delete resultset;
resultset = NULL;
@ -320,7 +410,7 @@ void ProxySQL_Statistics::system_memory_sets() {
int cols;
int affected_rows;
char *error = NULL;
char *query = (char *)"SELECT MAX(timestamp) FROM system_memory";
char *query = (char *)"SELECT MAX(timestamp) FROM system_memory_hour";
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
if (error) {
if (resultset) {
@ -331,15 +421,20 @@ void ProxySQL_Statistics::system_memory_sets() {
} else {
char buf[256];
if (resultset->rows_count == 0) {
sprintf(buf,"INSERT INTO system_memory_hour SELECT timestamp/3600 , AVG(allocated), AVG(resident), AVG(active), AVG(mapped), AVG(metadata), AVG(retained) FROM system_memory WHERE timestamp < %ld GROUP BY timestamp/3600", (ts/3600)*3600);
sprintf(buf,"INSERT INTO system_memory_hour SELECT timestamp/3600*3600 , AVG(allocated), AVG(resident), AVG(active), AVG(mapped), AVG(metadata), AVG(retained) FROM system_memory WHERE timestamp < %ld GROUP BY timestamp/3600", (ts/3600)*3600);
statsdb_disk->execute(buf);
} else {
SQLite3_row *r = resultset->rows[0];
time_t t = atol(r->fields[0]);
if (ts >= t + 3600) {
sprintf(buf,"INSERT INTO system_memory_hour SELECT timestamp/3600 , AVG(allocated), AVG(resident), AVG(active), AVG(mapped), AVG(metadata), AVG(retained) FROM system_memory WHERE timestamp >= %ld AND timestamp < %ld GROUP BY timestamp/3600", t+3600 , (ts/3600)*3600);
if (r->fields[0]) {
time_t t = atol(r->fields[0]);
if (ts >= t + 3600) {
sprintf(buf,"INSERT INTO system_memory_hour SELECT timestamp/3600*3600 , AVG(allocated), AVG(resident), AVG(active), AVG(mapped), AVG(metadata), AVG(retained) FROM system_memory WHERE timestamp >= %ld AND timestamp < %ld GROUP BY timestamp/3600", t+3600 , (ts/3600)*3600);
statsdb_disk->execute(buf);
}
} else {
sprintf(buf,"INSERT INTO system_memory_hour SELECT timestamp/3600*3600 , AVG(allocated), AVG(resident), AVG(active), AVG(mapped), AVG(metadata), AVG(retained) FROM system_memory WHERE timestamp < %ld GROUP BY timestamp/3600", (ts/3600)*3600);
statsdb_disk->execute(buf);
}
}
}
delete resultset;
resultset = NULL;
@ -433,4 +528,43 @@ void ProxySQL_Statistics::MySQL_Threads_Handler_sets(SQLite3_result *resultset)
rc=sqlite3_clear_bindings(statement1); assert(rc==SQLITE_OK);
rc=sqlite3_reset(statement1); //assert(rc==SQLITE_OK);
sqlite3_finalize(statement1);
SQLite3_result *resultset2 = NULL;
int cols;
int affected_rows;
char *error = NULL;
time_t ts = time(NULL);
char *query = (char *)"SELECT MAX(timestamp) FROM mysql_connections_hour";
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset2);
if (error) {
if (resultset2) {
delete resultset2;
resultset2 = NULL;
}
free(error);
} else {
char buf[512];
if (resultset2->rows_count == 0) {
sprintf(buf,"INSERT INTO mysql_connections_hour SELECT timestamp/3600*3600 , MAX(Client_Connections_aborted), AVG(Client_Connections_connected), MAX(Client_Connections_created), MAX(Server_Connections_aborted), AVG(Server_Connections_connected), MAX(Server_Connections_created), MAX(ConnPool_get_conn_failure), MAX(ConnPool_get_conn_immediate), MAX(ConnPool_get_conn_success), MAX(Questions), MAX(Slow_queries) FROM mysql_connections WHERE timestamp < %ld GROUP BY timestamp/3600", (ts/3600)*3600);
statsdb_disk->execute(buf);
} else {
SQLite3_row *r = resultset2->rows[0];
if (r->fields[0]) {
time_t t = atol(r->fields[0]);
if (ts >= t + 3600) {
sprintf(buf,"INSERT INTO mysql_connections_hour SELECT timestamp/3600*3600 , MAX(Client_Connections_aborted), AVG(Client_Connections_connected), MAX(Client_Connections_created), MAX(Server_Connections_aborted), AVG(Server_Connections_connected), MAX(Server_Connections_created), MAX(ConnPool_get_conn_failure), MAX(ConnPool_get_conn_immediate), MAX(ConnPool_get_conn_success), MAX(Questions), MAX(Slow_queries) FROM mysql_connections WHERE timestamp >= %ld AND timestamp < %ld GROUP BY timestamp/3600", t+3600 , (ts/3600)*3600);
statsdb_disk->execute(buf);
}
} else {
sprintf(buf,"INSERT INTO mysql_connections_hour SELECT timestamp/3600*3600 , MAX(Client_Connections_aborted), AVG(Client_Connections_connected), MAX(Client_Connections_created), MAX(Server_Connections_aborted), AVG(Server_Connections_connected), MAX(Server_Connections_created), MAX(ConnPool_get_conn_failure), MAX(ConnPool_get_conn_immediate), MAX(ConnPool_get_conn_success), MAX(Questions), MAX(Slow_queries) FROM mysql_connections WHERE timestamp < %ld GROUP BY timestamp/3600", (ts/3600)*3600);
statsdb_disk->execute(buf);
}
}
delete resultset2;
resultset2 = NULL;
sprintf(buf,"DELETE FROM system_memory WHERE timestamp < %ld", ts - 3600*24*7);
statsdb_disk->execute(buf);
sprintf(buf,"DELETE FROM system_memory_hour WHERE timestamp < %ld", ts - 3600*24*365);
statsdb_disk->execute(buf);
}
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDa6rriYRLPcCV+HlaS1arXoK3p9uFKbMGsV4xtHJqZ7dw39NHK
W6GzgL53mNGnaIXtqwvSRRQRl/2IwwRgG38l+eidJFFs8AeBL717YnYua3E0iG2v
3fPmeul4jkjsN7sdx9sUUl0zLUFECNy/NCwfEqIHiEZG6tjRlV1UA9aZHwIDAQAB
AoGABsA4VSTTNKxrq5D58HtAUnf1BQME/YuPCWaFwROhvN917A/TrF7ZBLUSqpN+
25/AiYy9x5UzwjsiqWYCK4iNiiqf57sj9z6lP18JDwWFwCMIAK+thSQPjpDq8V+l
MMBrgRju5hQawhhfwRIqbaT5lyK1mZvNJuMFu8LCzvthy2kCQQD+u528ivsN0sqf
pCMaCvYaPoi99zfS7eO9tLEPyvJJlgXxmyu7IwZ0YL7K0oSBwizetCuMzGNyy+NF
SIEENjgFAkEA3AGBPH4RSJ6ba2/abQ4pJPjyAaosWPa7HEVWDMw1QtrMih8ZfCP7
bkmZpXdQ8JQ9aCaRMjpW+Eni+gAVOQlJ0wJBAN+nUL4K9JRVgCwcS+mAuEWgpCTO
W0gqMCwO6usn0AUF4KAaEpJTFUa27q1bmpXnK8g5Pod3qNVQ6HGbUBOnmxUCQF2h
9lK8hLaXaiYLcLbBNBmcKcMznbQvLesWR00jC/fsDukp2zrORY/mmxGk+jmpnYja
ASmTUrhRGdy0dFPV9CkCQCwvn7tBno1ONOPjg5z2LcT5KltMkHOgd1Qu1UxNnXAh
Ohqkg9sIhfZy9aTtiQmMkowuWWzjluEHmE24qY1qyng=
-----END RSA PRIVATE KEY-----

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIIChDCCAe2gAwIBAgIJAOtQYwItW44rMA0GCSqGSIb3DQEBCwUAMFsxCzAJBgNV
BAYTAk1UMRMwEQYDVQQIDApTb21lLVN0YXRlMRUwEwYDVQQKDAxQcm94eVNRTCBM
TEMxIDAeBgkqhkiG9w0BCQEWEWluZm9AcHJveHlzcWwuY29tMB4XDTE3MTExOTAw
NDQxM1oXDTI3MTExNzAwNDQxM1owWzELMAkGA1UEBhMCTVQxEzARBgNVBAgMClNv
bWUtU3RhdGUxFTATBgNVBAoMDFByb3h5U1FMIExMQzEgMB4GCSqGSIb3DQEJARYR
aW5mb0Bwcm94eXNxbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANrq
uuJhEs9wJX4eVpLVqtegren24UpswaxXjG0cmpnt3Df00cpbobOAvneY0adohe2r
C9JFFBGX/YjDBGAbfyX56J0kUWzwB4EvvXtidi5rcTSIba/d8+Z66XiOSOw3ux3H
2xRSXTMtQUQI3L80LB8SogeIRkbq2NGVXVQD1pkfAgMBAAGjUDBOMB0GA1UdDgQW
BBTRGiA7HWP+8ntdu8+vrTd8DrzJ4zAfBgNVHSMEGDAWgBTRGiA7HWP+8ntdu8+v
rTd8DrzJ4zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAEsTu6LVQFxr
3fI7KcacssUrFcsFQhW0Ld6fTJLnd18Jy4rj4wHxTiKiyvgToHtWHP5lqhjoDEZs
D2ggix3sPkF+sMddkaesoOlHRHlKcTNrpPcef9J9qgQHS6nGvNcECyj9MLVlFIhC
Mj5dZlLYQRGUR4Zif8FnbGRy97mcF2aM
-----END CERTIFICATE-----
Loading…
Cancel
Save