Merge branch 'v1.4.4-graphs' into v1.4.4

pull/1243/head
René Cannaò 9 years ago
commit 78c32c6fba

2
.gitignore vendored

@ -95,7 +95,7 @@ deps/memcached/memcached-1.4.20/
deps/libconfig/libconfig-1.4.9/
#libmicrohttpd
deps/libmicrohttpd/libmicrohttpd-0.9.52/
deps/libmicrohttpd/libmicrohttpd-0.9.55/
#clickhouse
deps/clickhouse-cpp/clickhouse-cpp/

10
deps/Makefile vendored

@ -11,12 +11,17 @@ endif
PROXYSQLCLICKHOUSE := $(shell echo $(PROXYSQLCLICKHOUSE))
ifeq ($(PROXYSQLCLICKHOUSE),1)
default: libconfig libdaemon jemalloc mariadb_client re2 sqlite3 pcre clickhouse-cpp lz4 cityhash
default: libconfig libdaemon jemalloc mariadb_client re2 sqlite3 pcre clickhouse-cpp lz4 cityhash microhttpd
else
default: libconfig libdaemon jemalloc mariadb_client re2 sqlite3 pcre
default: libconfig libdaemon jemalloc mariadb_client re2 sqlite3 pcre microhttpd
endif
.PHONY: default
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}
microhttpd: libmicrohttpd/libmicrohttpd/src/microhttpd/.libs/libmicrohttpd.a
cityhash/cityhash/src/.libs/libcityhash.a:
cd cityhash && rm -rf cityhash || true
@ -127,5 +132,6 @@ cleanall:
cd sqlite3/sqlite3 && rm -rf * || true
cd clickhouse-cpp/clickhouse-cpp && rm -rf * || true
cd lz4 && rm -rf lz4-1.7.5 || true
cd libmicrohttpd && rm -rf libmicrohttpd-0.9.55 || true
.PHONY: cleanall

@ -0,0 +1 @@
libmicrohttpd-0.9.55

Binary file not shown.

@ -441,7 +441,7 @@ class MySQL_Threads_Handler
void stop_listeners();
void signal_all_threads(unsigned char _c=0);
SQLite3_result * SQL3_Processlist();
SQLite3_result * SQL3_GlobalStatus();
SQLite3_result * SQL3_GlobalStatus(bool _memory);
bool kill_session(uint32_t _thread_session_id);
unsigned long long get_total_mirror_queue();
unsigned long long get_total_backend_stmt_prepare();

@ -0,0 +1,27 @@
#ifndef CLASS_PROXYSQL_HTTP_SERVER_H
#define CLASS_PROXYSQL_HTTP_SERVER_H
#include "proxysql.h"
#include "cpp.h"
#include <string>
#define ProxySQL_HTTP_Server_Rate_Limit 100
class ProxySQL_HTTP_Server {
unsigned int page_sec;
time_t cur_time;
public:
struct {
} variables;
ProxySQL_HTTP_Server();
~ProxySQL_HTTP_Server();
void init();
int handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr);
void print_version();
std::string * generate_header(char *);
std::string * generate_canvas(char *);
std::string * generate_chart(char *chart_name, char *ts, int nsets, char **dname, char **llabel, char **values);
char *extract_values(SQLite3_result *result, int idx, bool relative, double mult=1);
char *extract_ts(SQLite3_result *result, bool relative);
};
#endif /* CLASS_PROXYSQL_HTTP_SERVER */

@ -0,0 +1,63 @@
#ifndef CLASS_PROXYSQL_STATISTICS_H
#define CLASS_PROXYSQL_STATISTICS_H
#include "proxysql.h"
#include "cpp.h"
//#include "thread.h"
//#include "wqueue.h"
#define STATSDB_SQLITE_TABLE_MYSQL_CONNECTIONS "CREATE TABLE mysql_connections (timestamp INT NOT NULL, Client_Connections_aborted INT NOT NULL, Client_Connections_connected INT NOT NULL, Client_Connections_created INT NOT NULL, Server_Connections_aborted INT NOT NULL, Server_Connections_connected INT NOT NULL, Server_Connections_created INT NOT NULL, ConnPool_get_conn_failure INT NOT NULL, ConnPool_get_conn_immediate INT NOT NULL, ConnPool_get_conn_success INT NOT NULL, Questions INT NOT NULL, Slow_queries INT NOT NULL, PRIMARY KEY (timestamp))"
#define STATSDB_SQLITE_TABLE_SYSTEM_CPU "CREATE TABLE system_cpu (timestamp INT NOT NULL, tms_utime INT NOT NULL, tms_stime INT NOT NULL, PRIMARY KEY (timestamp))"
#define STATSDB_SQLITE_TABLE_SYSTEM_MEMORY "CREATE TABLE system_memory (timestamp INT NOT NULL, allocated INT NOT NULL, resident INT NOT NULL, active INT NOT NULL, mapped INT NOT NULL, metadata INT NOT NULL, retained INT NOT NULL, PRIMARY KEY (timestamp))"
#define STATSDB_SQLITE_TABLE_MYSQL_CONNECTIONS_HOUR "CREATE TABLE mysql_connections_hour (timestamp INT NOT NULL, Client_Connections_aborted INT NOT NULL, Client_Connections_connected INT NOT NULL, Client_Connections_created INT NOT NULL, Server_Connections_aborted INT NOT NULL, Server_Connections_connected INT NOT NULL, Server_Connections_created INT NOT NULL, ConnPool_get_conn_failure INT NOT NULL, ConnPool_get_conn_immediate INT NOT NULL, ConnPool_get_conn_success INT NOT NULL, Questions INT NOT NULL, Slow_queries INT NOT NULL, PRIMARY KEY (timestamp))"
#define STATSDB_SQLITE_TABLE_SYSTEM_CPU_HOUR "CREATE TABLE system_cpu_hour (timestamp INT NOT NULL, tms_utime INT NOT NULL, tms_stime INT NOT NULL, PRIMARY KEY (timestamp))"
#define STATSDB_SQLITE_TABLE_SYSTEM_MEMORY_HOUR "CREATE TABLE system_memory_hour (timestamp INT NOT NULL, allocated INT NOT NULL, resident INT NOT NULL, active INT NOT NULL, mapped INT NOT NULL, metadata INT NOT NULL, retained INT NOT NULL, PRIMARY KEY (timestamp))"
#define STATSDB_SQLITE_TABLE_MYSQL_CONNECTIONS_DAY "CREATE TABLE mysql_connections_day (timestamp INT NOT NULL, Client_Connections_aborted INT NOT NULL, Client_Connections_connected INT NOT NULL, Client_Connections_created INT NOT NULL, Server_Connections_aborted INT NOT NULL, Server_Connections_connected INT NOT NULL, Server_Connections_created INT NOT NULL, ConnPool_get_conn_failure INT NOT NULL, ConnPool_get_conn_immediate INT NOT NULL, ConnPool_get_conn_success INT NOT NULL, Questions INT NOT NULL, Slow_queries INT NOT NULL, PRIMARY KEY (timestamp))"
#define STATSDB_SQLITE_TABLE_SYSTEM_CPU_DAY "CREATE TABLE system_cpu_day (timestamp INT NOT NULL, tms_utime INT NOT NULL, tms_stime INT NOT NULL, PRIMARY KEY (timestamp))"
#define STATSDB_SQLITE_TABLE_SYSTEM_MEMORY_DAY "CREATE TABLE system_memory_day (timestamp INT NOT NULL, allocated INT NOT NULL, resident INT NOT NULL, active INT NOT NULL, mapped INT NOT NULL, metadata INT NOT NULL, retained INT NOT NULL, PRIMARY KEY (timestamp))"
class ProxySQL_Statistics {
SQLite3DB *statsdb_mem; // internal statistics DB
std::vector<table_def_t *> *tables_defs_statsdb_mem;
std::vector<table_def_t *> *tables_defs_statsdb_disk;
// this is copied from ProxySQL Admin
void insert_into_tables_defs(std::vector<table_def_t *> *, const char *table_name, const char *table_def);
void drop_tables_defs(std::vector<table_def_t *> *tables_defs);
void check_and_build_standard_tables(SQLite3DB *db, std::vector<table_def_t *> *tables_defs);
unsigned long long next_timer_MySQL_Threads_Handler;
unsigned long long next_timer_system_cpu;
unsigned long long next_timer_system_memory;
public:
struct {
int stats_mysql_connection_pool;
int stats_mysql_connections;
int stats_mysql_query_cache;
int stats_system_cpu;
int stats_system_memory;
} variables;
ProxySQL_Statistics();
~ProxySQL_Statistics();
SQLite3DB *statsdb_disk; // internal statistics DB
void init();
void print_version();
bool MySQL_Threads_Handler_timetoget(unsigned long long);
bool system_cpu_timetoget(unsigned long long);
bool system_memory_timetoget(unsigned long long);
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();
};
#endif /* CLASS_PROXYSQL_STATISTICS_H */

@ -25,6 +25,8 @@
#include "MySQL_Logger.hpp"
#include "MySQL_PreparedStatement.h"
#include "ProxySQL_Cluster.hpp" // cluster
#include "ProxySQL_Statistics.hpp" // statistics
#include "ProxySQL_HTTP_Server.hpp" // HTTP server
#undef swap
#undef min
#undef max

@ -96,6 +96,15 @@ class ProxySQL_Admin {
bool cluster_mysql_servers_save_to_disk;
bool cluster_mysql_users_save_to_disk;
bool cluster_proxysql_servers_save_to_disk;
int stats_mysql_connection_pool;
int stats_mysql_connections;
int stats_mysql_query_cache;
int stats_system_cpu;
int stats_system_memory;
bool web_enabled;
bool web_enabled_old;
int web_port;
int web_port_old;
#ifdef DEBUG
bool debug;
#endif /* DEBUG */
@ -179,6 +188,7 @@ class ProxySQL_Admin {
SQLite3DB *statsdb; // in memory
SQLite3DB *configdb; // on disk
SQLite3DB *monitordb; // in memory
SQLite3DB *statsdb_disk; // on disk
int pipefd[2];
void print_version();
bool init();
@ -266,6 +276,8 @@ class ProxySQL_Admin {
void load_sqliteserver_variables_to_runtime() { flush_sqliteserver_variables___database_to_runtime(admindb, true); }
void save_sqliteserver_variables_from_runtime() { flush_sqliteserver_variables___runtime_to_database(admindb, true, true, false); }
ProxySQL_HTTP_Server *AdminHTTPServer;
#ifdef PROXYSQLCLICKHOUSE
// ClickHouse
void init_clickhouse_variables();

@ -51,6 +51,7 @@ class ProxySQL_GlobalVariables {
char *config_file;
char *datadir;
char *admindb;
char *statsdb_disk;
char *errorlog;
char *pid;
struct {

File diff suppressed because one or more lines are too long

@ -26,9 +26,12 @@ SQLITE3_DIR=$(DEPS_PATH)/sqlite3/sqlite3
CLICKHOUSE_CPP_DIR=$(DEPS_PATH)/clickhouse-cpp/clickhouse-cpp
MICROHTTPD_DIR=$(DEPS_PATH)/libmicrohttpd/libmicrohttpd
MICROHTTPD_IDIR=-I$(MICROHTTPD_DIR) -I$(MICROHTTPD_DIR)/src/include
IDIR=../include
IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBCONFIG_IDIR) -I$(RE2_IDIR) -I$(SQLITE3_DIR) -I$(PCRE_PATH) -I/usr/local/include -I$(CLICKHOUSE_CPP_DIR)
IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBCONFIG_IDIR) -I$(RE2_IDIR) -I$(SQLITE3_DIR) -I$(PCRE_PATH) -I/usr/local/include -I$(CLICKHOUSE_CPP_DIR) $(MICROHTTPD_IDIR)
LDIRS=-L$(JEMALLOC_PATH)/lib -L$(RE2_PATH)/obj -L$(INJECTION_PATH)
@ -70,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
_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 = $(patsubst %,$(ODIR)/%,$(_OBJ_CXX))
%.ko: %.cpp

@ -3344,13 +3344,15 @@ void MySQL_Thread::listener_handle_new_connection(MySQL_Data_Stream *myds, unsig
}
}
SQLite3_result * MySQL_Threads_Handler::SQL3_GlobalStatus() {
SQLite3_result * MySQL_Threads_Handler::SQL3_GlobalStatus(bool _memory) {
const int colnum=2;
char buf[256];
char **pta=(char **)malloc(sizeof(char *)*colnum);
Get_Memory_Stats();
if (_memory == true) {
Get_Memory_Stats();
}
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 4, "Dumping MySQL Global Status\n");
SQLite3_result *result=new SQLite3_result(colnum);
SQLite3_result *result=new SQLite3_result(colnum);
result->add_column_definition(SQLITE_TEXT,"Variable_Name");
result->add_column_definition(SQLITE_TEXT,"Variable_Value");
// NOTE: as there is no string copy, we do NOT free pta[0] and pta[1]

@ -23,6 +23,10 @@
#include <fcntl.h>
#include <sys/utsname.h>
#include "platform.h"
#include "microhttpd.h"
//#define MYSQL_THREAD_IMPLEMENTATION
#define SELECT_VERSION_COMMENT "select @@version_comment limit 1"
@ -36,6 +40,10 @@
#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;
#ifdef __APPLE__
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
@ -149,7 +157,6 @@ extern ClickHouse_Server *GloClickHouseServer;
extern SQLite3_Server *GloSQLite3Server;
#define PANIC(msg) { perror(msg); exit(EXIT_FAILURE); }
int rc, arg_on=1, arg_off=0;
@ -158,6 +165,11 @@ pthread_mutex_t sock_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t admin_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t users_mutex = PTHREAD_MUTEX_INITIALIZER;
static int http_handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) {
return GloAdmin->AdminHTTPServer->handler(cls, connection, url, method, version, upload_data, upload_data_size, ptr);
}
#define LINESIZE 2048
#define ADMIN_SQLITE_TABLE_MYSQL_SERVERS "CREATE TABLE mysql_servers (hostgroup_id INT NOT NULL DEFAULT 0 , hostname VARCHAR NOT NULL , port INT NOT NULL DEFAULT 3306 , status VARCHAR CHECK (UPPER(status) IN ('ONLINE','SHUNNED','OFFLINE_SOFT', 'OFFLINE_HARD')) NOT NULL DEFAULT 'ONLINE' , weight INT CHECK (weight >= 0) NOT NULL DEFAULT 1 , compression INT CHECK (compression >=0 AND compression <= 102400) NOT NULL DEFAULT 0 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 1000 , max_replication_lag INT CHECK (max_replication_lag >= 0 AND max_replication_lag <= 126144000) NOT NULL DEFAULT 0 , use_ssl INT CHECK (use_ssl IN(0,1)) NOT NULL DEFAULT 0 , max_latency_ms INT UNSIGNED CHECK (max_latency_ms>=0) NOT NULL DEFAULT 0 , comment VARCHAR NOT NULL DEFAULT '' , PRIMARY KEY (hostgroup_id, hostname, port) )"
@ -287,12 +299,17 @@ pthread_mutex_t users_mutex = PTHREAD_MUTEX_INITIALIZER;
static char * admin_variables_names[]= {
(char *)"admin_credentials",
(char *)"stats_credentials",
(char *)"mysql_ifaces",
(char *)"telnet_admin_ifaces",
(char *)"telnet_stats_ifaces",
(char *)"refresh_interval",
(char *)"admin_credentials",
(char *)"stats_credentials",
(char *)"stats_mysql_connections",
(char *)"stats_mysql_connection_pool",
(char *)"stats_mysql_query_cache",
(char *)"stats_system_cpu",
(char *)"stats_system_memory",
(char *)"mysql_ifaces",
(char *)"telnet_admin_ifaces",
(char *)"telnet_stats_ifaces",
(char *)"refresh_interval",
(char *)"read_only",
(char *)"hash_passwords",
(char *)"version",
@ -311,6 +328,8 @@ static char * admin_variables_names[]= {
(char *)"checksum_mysql_query_rules",
(char *)"checksum_mysql_servers",
(char *)"checksum_mysql_users",
(char *)"web_enabled",
(char *)"web_port",
#ifdef DEBUG
(char *)"debug",
#endif /* DEBUG */
@ -3053,6 +3072,23 @@ static void * admin_main_loop(void *arg)
fds[i].revents=0;
}
__end_while_pool:
{
if (GloProxyStats->MySQL_Threads_Handler_timetoget(curtime)) {
if (GloMTH) {
SQLite3_result * resultset=GloMTH->SQL3_GlobalStatus(false);
if (resultset) {
GloProxyStats->MySQL_Threads_Handler_sets(resultset);
delete resultset;
}
}
}
if (GloProxyStats->system_cpu_timetoget(curtime)) {
GloProxyStats->system_cpu_sets();
}
if (GloProxyStats->system_memory_timetoget(curtime)) {
GloProxyStats->system_memory_sets();
}
}
if (S_amll.get_version()!=version) {
S_amll.wrlock();
version=S_amll.get_version();
@ -3177,6 +3213,22 @@ ProxySQL_Admin::ProxySQL_Admin() {
variables.cluster_mysql_servers_save_to_disk = true;
variables.cluster_mysql_users_save_to_disk = true;
variables.cluster_proxysql_servers_save_to_disk = true;
variables.stats_mysql_connection_pool = 60;
variables.stats_mysql_connections = 60;
variables.stats_mysql_query_cache = 60;
variables.stats_system_cpu = 60;
variables.stats_system_memory = 60;
GloProxyStats->variables.stats_mysql_connection_pool = 60;
GloProxyStats->variables.stats_mysql_connections = 60;
GloProxyStats->variables.stats_mysql_query_cache = 60;
GloProxyStats->variables.stats_system_cpu = 60;
GloProxyStats->variables.stats_system_memory = 60;
variables.web_enabled = true;
variables.web_enabled_old = false;
variables.web_port = 6080;
variables.web_port_old = variables.web_port;
#ifdef DEBUG
variables.debug=GloVars.global.gdbg;
#endif /* DEBUG */
@ -3232,6 +3284,11 @@ void ProxySQL_Admin::print_version() {
bool ProxySQL_Admin::init() {
cpu_timer cpt;
Admin_HTTP_Server = NULL;
AdminHTTPServer = new ProxySQL_HTTP_Server();
AdminHTTPServer->init();
AdminHTTPServer->print_version();
child_func[0]=child_mysql;
child_func[1]=child_telnet;
child_func[2]=child_telnet_also;
@ -3273,6 +3330,17 @@ bool ProxySQL_Admin::init() {
monitordb = new SQLite3DB();
monitordb->open((char *)"file:mem_monitordb?mode=memory&cache=shared", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX);
statsdb_disk = new SQLite3DB();
statsdb_disk->open((char *)GloVars.statsdb_disk, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX);
// char *dbname = (char *)malloc(strlen(GloVars.statsdb_disk)+50);
// sprintf(dbname,"%s?mode=memory&cache=shared",GloVars.statsdb_disk);
// statsdb_disk->open(dbname, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_FULLMUTEX);
// free(dbname);
statsdb_disk->execute("PRAGMA synchronous=0");
// GloProxyStats->statsdb_disk = configdb;
GloProxyStats->init();
tables_defs_admin=new std::vector<table_def_t *>;
tables_defs_stats=new std::vector<table_def_t *>;
tables_defs_config=new std::vector<table_def_t *>;
@ -3364,6 +3432,8 @@ bool ProxySQL_Admin::init() {
__attach_db(admindb, statsdb, (char *)"stats");
__attach_db(admindb, monitordb, (char *)"monitor");
__attach_db(statsdb, monitordb, (char *)"monitor");
__attach_db(admindb, statsdb_disk, (char *)"stats_history");
__attach_db(statsdb, statsdb_disk, (char *)"stats_history");
dump_mysql_collations();
@ -3475,6 +3545,14 @@ void ProxySQL_Admin::init_sqliteserver_variables() {
void ProxySQL_Admin::admin_shutdown() {
int i;
// do { usleep(50); } while (main_shutdown==0);
if (Admin_HTTP_Server) {
if (variables.web_enabled) {
MHD_stop_daemon(Admin_HTTP_Server);
Admin_HTTP_Server = NULL;
}
}
delete AdminHTTPServer;
AdminHTTPServer = NULL;
pthread_join(admin_thr, NULL);
delete admindb;
delete statsdb;
@ -3617,7 +3695,6 @@ void ProxySQL_Admin::flush_admin_variables___database_to_runtime(SQLite3DB *db,
}
sprintf(q,"INSERT OR REPLACE INTO global_variables VALUES(\"admin-%s\",\"%s\")",r->fields[0],val);
db->execute(q);
free(val);
} else {
if (strcmp(r->fields[0],(char *)"debug")==0) {
sprintf(q,"DELETE FROM disk.global_variables WHERE variable_name=\"admin-%s\"",r->fields[0]);
@ -3635,6 +3712,32 @@ void ProxySQL_Admin::flush_admin_variables___database_to_runtime(SQLite3DB *db,
}
//commit(); NOT IMPLEMENTED
wrunlock();
{
if (variables.web_enabled != variables.web_enabled_old) {
if (variables.web_enabled) {
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);
} else {
MHD_stop_daemon(Admin_HTTP_Server);
Admin_HTTP_Server = NULL;
}
variables.web_enabled_old = variables.web_enabled;
} else {
if (variables.web_port != variables.web_port_old) {
if (variables.web_enabled) {
MHD_stop_daemon(Admin_HTTP_Server);
Admin_HTTP_Server = NULL;
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);
}
variables.web_port_old = variables.web_port;
}
}
}
}
if (resultset) delete resultset;
}
@ -4030,8 +4133,31 @@ char * ProxySQL_Admin::get_variable(char *name) {
if (!strcasecmp(name,"version")) return s_strdup(variables.admin_version);
if (!strcasecmp(name,"cluster_username")) return s_strdup(variables.cluster_username);
if (!strcasecmp(name,"cluster_password")) return s_strdup(variables.cluster_password);
if (!strncasecmp(name,"stats_",strlen("stats_"))) {
if (!strcasecmp(name,"stats_credentials"))
return s_strdup(variables.stats_credentials);
if (!strcasecmp(name,"stats_mysql_connection_pool")) {
sprintf(intbuf,"%d",variables.stats_mysql_connection_pool);
return strdup(intbuf);
}
if (!strcasecmp(name,"stats_mysql_connections")) {
sprintf(intbuf,"%d",variables.stats_mysql_connections);
return strdup(intbuf);
}
if (!strcasecmp(name,"stats_mysql_query_cache")) {
sprintf(intbuf,"%d",variables.stats_mysql_query_cache);
return strdup(intbuf);
}
if (!strcasecmp(name,"stats_system_cpu")) {
sprintf(intbuf,"%d",variables.stats_system_cpu);
return strdup(intbuf);
}
if (!strcasecmp(name,"stats_system_memory")) {
sprintf(intbuf,"%d",variables.stats_system_memory);
return strdup(intbuf);
}
}
if (!strcasecmp(name,"admin_credentials")) return s_strdup(variables.admin_credentials);
if (!strcasecmp(name,"stats_credentials")) return s_strdup(variables.stats_credentials);
if (!strcasecmp(name,"mysql_ifaces")) return s_strdup(variables.mysql_ifaces);
if (!strcasecmp(name,"telnet_admin_ifaces")) return s_strdup(variables.telnet_admin_ifaces);
if (!strcasecmp(name,"telnet_stats_ifaces")) return s_strdup(variables.telnet_stats_ifaces);
@ -4090,6 +4216,13 @@ char * ProxySQL_Admin::get_variable(char *name) {
if (!strcasecmp(name,"checksum_mysql_users")) {
return strdup((checksum_variables.checksum_mysql_users ? "true" : "false"));
}
if (!strcasecmp(name,"web_enabled")) {
return strdup((variables.web_enabled ? "true" : "false"));
}
if (!strcasecmp(name,"web_port")) {
sprintf(intbuf,"%d",variables.web_port);
return strdup(intbuf);
}
#ifdef DEBUG
if (!strcasecmp(name,"debug")) {
return strdup((variables.debug ? "true" : "false"));
@ -4198,6 +4331,173 @@ bool ProxySQL_Admin::set_variable(char *name, char *value) { // this is the pub
return false;
}
}
if (!strncasecmp(name,"stats_",strlen("stats_"))) {
if (!strcasecmp(name,"stats_mysql_connection_pool")) {
int intv=atoi(value);
if (intv >= 0 && intv <= 300) {
if (intv > 120) {
intv = 300;
} else {
if (intv > 60) {
intv = 120;
} else {
if (intv > 30) {
intv = 60;
} else {
if (intv > 10) {
intv = 30;
} else {
if (intv > 5) {
intv = 10;
} else {
if (intv > 1) {
intv = 5;
}
}
}
}
}
}
variables.stats_mysql_connection_pool=intv;
GloProxyStats->variables.stats_mysql_connection_pool=intv;
return true;
} else {
return false;
}
}
if (!strcasecmp(name,"stats_mysql_connections")) {
int intv=atoi(value);
if (intv >= 0 && intv <= 300) {
if (intv > 120) {
intv = 300;
} else {
if (intv > 60) {
intv = 120;
} else {
if (intv > 30) {
intv = 60;
} else {
if (intv > 10) {
intv = 30;
} else {
if (intv > 5) {
intv = 10;
} else {
if (intv > 1) {
intv = 5;
}
}
}
}
}
}
variables.stats_mysql_connections=intv;
GloProxyStats->variables.stats_mysql_connections=intv;
return true;
} else {
return false;
}
}
if (!strcasecmp(name,"stats_mysql_query_cache")) {
int intv=atoi(value);
if (intv >= 0 && intv <= 300) {
if (intv > 120) {
intv = 300;
} else {
if (intv > 60) {
intv = 120;
} else {
if (intv > 30) {
intv = 60;
} else {
if (intv > 10) {
intv = 30;
} else {
if (intv > 5) {
intv = 10;
} else {
if (intv > 1) {
intv = 5;
}
}
}
}
}
}
variables.stats_mysql_query_cache=intv;
GloProxyStats->variables.stats_mysql_query_cache=intv;
return true;
} else {
return false;
}
}
if (!strcasecmp(name,"stats_system_cpu")) {
int intv=atoi(value);
if (intv >= 0 && intv <= 600) {
if (intv > 120) {
intv = 300;
} else {
if (intv > 60) {
intv = 120;
} else {
if (intv > 30) {
intv = 60;
} else {
if (intv > 10) {
intv = 30;
} else {
if (intv > 5) {
intv = 10;
} else {
if (intv > 1) {
intv = 5;
}
}
}
}
}
}
variables.stats_system_cpu=intv;
GloProxyStats->variables.stats_system_cpu=intv;
return true;
} else {
return false;
}
}
if (!strcasecmp(name,"stats_system_memory")) {
int intv=atoi(value);
if (intv >= 0 && intv <= 600) {
if (intv > 120) {
intv = 300;
} else {
if (intv > 60) {
intv = 120;
} else {
if (intv > 30) {
intv = 60;
} else {
if (intv > 10) {
intv = 30;
} else {
if (intv > 5) {
intv = 10;
} else {
if (intv > 1) {
intv = 5;
}
}
}
}
}
}
variables.stats_system_memory=intv;
GloProxyStats->variables.stats_system_memory=intv;
return true;
} else {
return false;
}
}
}
if (!strcasecmp(name,"mysql_ifaces")) {
if (vallen) {
bool update_creds=false;
@ -4351,6 +4651,26 @@ bool ProxySQL_Admin::set_variable(char *name, char *value) { // this is the pub
}
return false;
}
if (!strcasecmp(name,"web_enabled")) {
if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) {
variables.web_enabled=true;
return true;
}
if (strcasecmp(value,"false")==0 || strcasecmp(value,"0")==0) {
variables.web_enabled=false;
return true;
}
return false;
}
if (!strcasecmp(name,"web_port")) {
int intv=atoi(value);
if (intv > 0 && intv < 65535) {
variables.web_port=intv;
return true;
} else {
return false;
}
}
if (!strcasecmp(name,"cluster_mysql_query_rules_save_to_disk")) {
if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) {
variables.cluster_mysql_query_rules_save_to_disk=true;
@ -4593,7 +4913,7 @@ void ProxySQL_Admin::stats___memory_metrics() {
void ProxySQL_Admin::stats___mysql_global() {
if (!GloMTH) return;
SQLite3_result * resultset=GloMTH->SQL3_GlobalStatus();
SQLite3_result * resultset=GloMTH->SQL3_GlobalStatus(true);
if (resultset==NULL) return;
statsdb->execute("BEGIN");
statsdb->execute("DELETE FROM stats_mysql_global");

@ -0,0 +1,435 @@
#include <iostream> // std::cout
#include <algorithm> // std::sort
#include <vector> // std::vector
#include "re2/re2.h"
#include "re2/regexp.h"
#include "proxysql.h"
#include "cpp.h"
#include <search.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "SpookyV2.h"
#include <fcntl.h>
#include <sys/utsname.h>
#include "platform.h"
#include "microhttpd.h"
#ifdef DEBUG
#define DEB "_DEBUG"
#else
#define DEB ""
#endif /* DEBUG */
#define PROXYSQL_HTTP_SERVER_VERSION "1.4.1031" DEB
//extern struct MHD_Daemon *Admin_HTTP_Server;
extern ProxySQL_Statistics *GloProxyStats;
extern char * Chart_bundle_js_c;
#define RATE_LIMIT_PAGE "<html><head><title>Rate Limit Page</title></head><body>Rate Limit Reached</body></html>"
char * ProxySQL_HTTP_Server::extract_values(SQLite3_result *result, int idx, bool relative, double mult) {
string s = "[";
int i;
for ( i= (relative ? 1 : 0) ; i < result->rows_count ; i++) {
SQLite3_row *r1 = ( relative ? result->rows[i-1] : NULL );
SQLite3_row *r2 = result->rows[i];
double v;
if (relative) {
double d2 = atol(r2->fields[idx]);
double d1 = atol(r1->fields[idx]);
double diff = (atol(r2->fields[1])-atol(r1->fields[1]));
v = (d2-d1)/diff;
} else {
v = atol(r2->fields[idx]);
}
v *= mult;
if (v<0) v=0;
s.append(std::to_string(v));
if (i != result->rows_count-1) {
s.append(", ");
}
}
s.append("];");
char *ret=strdup(s.c_str());
return ret;
}
char * ProxySQL_HTTP_Server::extract_ts(SQLite3_result *result, bool relative) {
string s = "[";
int i;
for ( i= (relative ? 1 : 0) ; i < result->rows_count ; i++) {
SQLite3_row *r2 = result->rows[i];
s.append("\"");
s.append(r2->fields[0]);
s.append("\"");
if (i != result->rows_count-1) {
s.append(", ");
}
}
s.append("];");
char *ret=strdup(s.c_str());
return ret;
}
void ProxySQL_HTTP_Server::init() {
}
void ProxySQL_HTTP_Server::print_version() {
fprintf(stderr,"Standard ProxySQL HTTP Server Handler rev. %s -- %s -- %s\n", PROXYSQL_HTTP_SERVER_VERSION, __FILE__, __TIMESTAMP__);
}
#define EMPTY_PAGE "<html><head><title>File not found</title></head><body>File not found<br/><a href=\"/\">Go back home</a></body></html>"
int ProxySQL_HTTP_Server::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) {
struct MHD_Response *response;
int ret;
char *valmetric = NULL;
char *valinterval = NULL;
char *valunit = NULL;
time_t now = time(NULL);
if (now != cur_time) {
page_sec = 0;
cur_time = now;
}
page_sec++;
if (page_sec > ProxySQL_HTTP_Server_Rate_Limit) {
response = MHD_create_response_from_buffer(strlen(RATE_LIMIT_PAGE), (void *) RATE_LIMIT_PAGE, MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;
}
if (0 != strcmp (method, "GET"))
return MHD_NO; /* unexpected method */
// if (&aptr != *ptr) {
// /* do never respond on first call */
// *ptr = &aptr;
// return MHD_YES;
// }
// *ptr = NULL; /* reset when done */
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");
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;
}
if (valunit == NULL) {
valunit = (char *)"second";
}
if ( (strcmp(valunit,"second")) && (strcmp(valunit,"hour")) && (strcmp(valunit,"day")) ) {
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;
}
if (valinterval == NULL) {
if ((strcmp(valunit,(char *)"second") == 0)) {
valinterval = (char *)"14400";
}
if ((strcmp(valunit,(char *)"hour") == 0)) {
valinterval = (char *)"720";
}
if ((strcmp(valunit,"day") == 0)) {
valinterval = (char *)"365";
}
}
if (strcmp(valmetric,"system")==0) {
string *s = generate_header((char *)"ProxySQL Graphs");
string *s1 = generate_canvas((char *)"myChart1");
s->append(s1->c_str());
s1 = generate_canvas((char *)"myChart2");
s->append(s1->c_str());
s1 = generate_canvas((char *)"myChart3");
s->append(s1->c_str());
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();
//SQLite3_result *mysql_metrics_sqlite = GloProxyStats->get_mysql_metrics();
char **nm = NULL;
char **nl = NULL;
char **nv = NULL;
char *ts = NULL;
nm = (char **)malloc(sizeof(char *)*2);
nm[0] = (char *)"utime";
nm[1] = (char *)"stime";
nl = (char **)malloc(sizeof(char *)*2);
nl[0] = (char *)"User Time";
nl[1] = (char *)"System Time";
nv = (char **)malloc(sizeof(char *)*2);
nv[0] = extract_values(cpu_sqlite,2,true,(double)1/sysconf(_SC_CLK_TCK));
nv[1] = extract_values(cpu_sqlite,3,true,(double)1/sysconf(_SC_CLK_TCK));
ts = extract_ts(cpu_sqlite,true);
s1 = generate_chart((char *)"myChart1",ts,2,nm,nl,nv);
s->append(s1->c_str());
free(nm);
free(nl);
free(nv[0]);
free(nv[1]);
free(nv);
free(ts);
nm = (char **)malloc(sizeof(char *)*5);
nm[0] = (char *)"allocated";
nm[1] = (char *)"resident";
nm[2] = (char *)"active";
nm[3] = (char *)"mapped";
nm[4] = (char *)"metadata";
nl = (char **)malloc(sizeof(char *)*5);
nl[0] = (char *)"Allocated";
nl[1] = (char *)"Resident";
nl[2] = (char *)"Active";
nl[3] = (char *)"Mapped";
nl[4] = (char *)"Metadata";
nv = (char **)malloc(sizeof(char *)*5);
nv[0] = extract_values(memory_sqlite,2,false);
nv[1] = extract_values(memory_sqlite,3,false);
nv[2] = extract_values(memory_sqlite,4,false);
nv[3] = extract_values(memory_sqlite,5,false);
nv[4] = extract_values(memory_sqlite,6,false);
ts = extract_ts(cpu_sqlite,true);
s1 = generate_chart((char *)"myChart2",ts,5,nm,nl,nv);
s->append(s1->c_str());
free(nm);
free(nl);
free(nv[0]);
free(nv[1]);
free(nv[2]);
free(nv[3]);
free(nv[4]);
free(nv);
free(ts);
s->append("</body></html>");
response = MHD_create_response_from_buffer(s->length(), (void *) s->c_str(), MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;
}
if (strcmp(valmetric,"mysql")==0) {
string *s = generate_header((char *)"ProxySQL Graphs");
string *s1 = generate_canvas((char *)"myChart1");
s->append(s1->c_str());
s1 = generate_canvas((char *)"myChart2");
s->append(s1->c_str());
s1 = generate_canvas((char *)"myChart3");
s->append(s1->c_str());
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();
SQLite3_result *mysql_metrics_sqlite = GloProxyStats->get_mysql_metrics();
char **nm = NULL;
char **nl = NULL;
char **nv = NULL;
char *ts = NULL;
//Client_Connections_aborted, Client_Connections_connected, Client_Connections_created, Server_Connections_aborted, Server_Connections_connected, Server_Connections_created, ConnPool_get_conn_immediate, ConnPool_get_conn_success, Questions
nm = (char **)malloc(sizeof(char *)*6);
nm[0] = (char *)"Client_Connections_aborted";
nm[1] = (char *)"Client_Connections_connected";
nm[2] = (char *)"Client_Connections_created";
nm[3] = (char *)"Server_Connections_aborted";
nm[4] = (char *)"Server_Connections_connected";
nm[5] = (char *)"Server_Connections_created";
nl = (char **)malloc(sizeof(char *)*6);
nl[0] = (char *)"Client Connections aborted";
nl[1] = (char *)"Client Connections connected";
nl[2] = (char *)"Client Connections created";
nl[3] = (char *)"Server Connections aborted";
nl[4] = (char *)"Server Connections connected";
nl[5] = (char *)"Server Connections created";
nv = (char **)malloc(sizeof(char *)*6);
nv[0] = extract_values(mysql_metrics_sqlite,2,true,(double)1);
nv[1] = extract_values(mysql_metrics_sqlite,3,false,(double)1);
nv[2] = extract_values(mysql_metrics_sqlite,4,true,(double)1);
nv[3] = extract_values(mysql_metrics_sqlite,5,true,(double)1);
nv[4] = extract_values(mysql_metrics_sqlite,6,false,(double)1);
nv[5] = extract_values(mysql_metrics_sqlite,7,true,(double)1);
ts = extract_ts(mysql_metrics_sqlite,true);
s1 = generate_chart((char *)"myChart1",ts,6,nm,nl,nv);
s->append(s1->c_str());
free(nm);
free(nl);
for (int aa=0 ; aa<6 ; aa++) {
free(nv[aa]);
}
free(nv);
free(ts);
nm = (char **)malloc(sizeof(char *)*4);
nm[0] = (char *)"ConnPool_get_conn_failure";
nm[1] = (char *)"ConnPool_get_conn_immediate";
nm[2] = (char *)"ConnPool_get_conn_success";
nm[3] = (char *)"Questions";
nl = (char **)malloc(sizeof(char *)*4);
nl[0] = (char *)"ConnPool failure";
nl[1] = (char *)"ConnPool immediate";
nl[2] = (char *)"ConnPool success";
nl[3] = (char *)"Questions";
nv = (char **)malloc(sizeof(char *)*4);
nv[0] = extract_values(mysql_metrics_sqlite,8,true);
nv[1] = extract_values(mysql_metrics_sqlite,9,true);
nv[2] = extract_values(mysql_metrics_sqlite,10,true);
nv[3] = extract_values(mysql_metrics_sqlite,11,true);
ts = extract_ts(mysql_metrics_sqlite,true);
s1 = generate_chart((char *)"myChart2",ts,4,nm,nl,nv);
s->append(s1->c_str());
free(nm);
free(nl);
for (int aa=0 ; aa<4 ; aa++) {
free(nv[aa]);
}
free(nv);
free(ts);
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;
}
}
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);
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
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);
return ret;
}
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");
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(s);
a->append("\" width=\"650\" height=\"280\"></canvas></div>\n");
return a;
}
ProxySQL_HTTP_Server::ProxySQL_HTTP_Server() {
page_sec = 0;
cur_time = time(NULL);
}
ProxySQL_HTTP_Server::~ProxySQL_HTTP_Server() {
}
string * ProxySQL_HTTP_Server::generate_chart(char *chart_name, char *ts, int nsets, char **dname, char **llabel, char **values) {
char *h=(char *)"0123456789abcdef";
string *ret= new string();
int i;
ret->append("<script>\n");
ret->append("var ts = ");
ret->append(ts);
ret->append("\n");
for (i=0;i<nsets;i++) {
ret->append("var ");
ret->append(dname[i]);
ret->append(" = ");
ret->append(values[i]);
ret->append("\n");
}
ret->append("var ctx = document.getElementById(\"");
ret->append(chart_name);
ret->append("\");\nvar ");
ret->append(chart_name);
ret->append(" = new Chart(ctx, { \n");
ret->append("type: 'line', \n");
ret->append(" data: { \n");
ret->append(" labels: ts,\n");
ret->append(" datasets: [ \n");
for (i=0;i<nsets;i++) {
ret->append(" {\n");
ret->append(" data: "); ret->append(dname[i]); ret->append(",\n");
ret->append(" label: \""); ret->append(llabel[i]); ret->append("\",\n");
int j;
char pal[7];
for (j=0; j<6; j++) { pal[j]=h[rand()%16]; }
pal[6]='\0';
ret->append(" borderColor: \"#"); ret->append(pal); ret->append("\",\n");
ret->append(" fill: false\n");
ret->append(" }");
if (i<nsets-1) {
ret->append(",");
}
ret->append("\n");
}
ret->append(" ]\n");
ret->append(" }\n");
ret->append("});\n");
ret->append("</script>\n");
return ret;
}
/*
<script>\n";
char *script5 = "\
var ctx = document.getElementById(\"myChart1\"); var myChart1 = new Chart(ctx, { \n\
type: 'line', \n\
data: { \n\
labels: ts, \n\
datasets: [ \n\
{ \n\
data: utime, \n\
label: \"User Time\", \n\
borderColor: \"#3e95cd\", \n\
fill: false \n\
}, \n\
{ \n\
data: stime, \n\
label: \"System Time\", \n\
borderColor: \"#8e5ea2\", \n\
fill: false \n\
} \n\
] \n\
} \n\
});\n";
*/

@ -0,0 +1,436 @@
#include <map>
#include <mutex>
//#include <thread>
#include "proxysql.h"
#include "cpp.h"
//#include "thread.h"
//#include "wqueue.h"
#include <fcntl.h>
#include <sys/times.h>
#ifdef DEBUG
#define DEB "_DEBUG"
#else
#define DEB ""
#endif /* DEBUG */
#define PROXYSQL_STATISTICS_VERSION "1.4.1027" DEB
extern ProxySQL_Admin *GloAdmin;
extern MySQL_Threads_Handler *GloMTH;
#define SAFE_SQLITE3_STEP(_stmt) do {\
do {\
rc=sqlite3_step(_stmt);\
if (rc!=SQLITE_DONE) {\
assert(rc==SQLITE_LOCKED)\
usleep(100);\
}\
} while (rc!=SQLITE_DONE );\
} while (0)
#define SAFE_SQLITE3_STEP2(_stmt) do {\
do {\
rc=sqlite3_step(_stmt);\
if (rc==SQLITE_LOCKED || rc==SQLITE_BUSY) {\
usleep(100);\
}\
} while (rc==SQLITE_LOCKED || rc==SQLITE_BUSY);\
} while (0)
ProxySQL_Statistics::ProxySQL_Statistics() {
statsdb_mem = new SQLite3DB();
statsdb_mem->open((char *)"file:statsdb_mem?mode=memory&cache=shared", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX);
// statsdb_disk = GloAdmin->statsdb_disk;
statsdb_disk = new SQLite3DB();
// char *dbname = (char *)malloc(strlen(GloVars.statsdb_disk)+50);
// sprintf(dbname,"file:%s?cache=shared",GloVars.statsdb_disk);
statsdb_disk->open((char *)GloVars.statsdb_disk, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX );
// statsdb_disk->open((char *)GloVars.statsdb_disk, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_NOMUTEX);
// statsdb_disk->open(dbname, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_NOMUTEX);
// free(dbname);
statsdb_disk->execute("PRAGMA synchronous=0");
next_timer_MySQL_Threads_Handler = 0;
next_timer_system_cpu = 0;
next_timer_system_memory = 0;
}
ProxySQL_Statistics::~ProxySQL_Statistics() {
drop_tables_defs(tables_defs_statsdb_mem);
delete tables_defs_statsdb_mem;
drop_tables_defs(tables_defs_statsdb_disk);
delete tables_defs_statsdb_disk;
delete statsdb_mem;
// delete statsdb_disk;
}
void ProxySQL_Statistics::init() {
tables_defs_statsdb_mem = new std::vector<table_def_t *>;
tables_defs_statsdb_disk = new std::vector<table_def_t *>;
insert_into_tables_defs(tables_defs_statsdb_mem,"mysql_connections", STATSDB_SQLITE_TABLE_MYSQL_CONNECTIONS);
insert_into_tables_defs(tables_defs_statsdb_disk,"mysql_connections", STATSDB_SQLITE_TABLE_MYSQL_CONNECTIONS);
insert_into_tables_defs(tables_defs_statsdb_disk,"system_cpu", STATSDB_SQLITE_TABLE_SYSTEM_CPU);
insert_into_tables_defs(tables_defs_statsdb_disk,"system_memory", STATSDB_SQLITE_TABLE_SYSTEM_MEMORY);
insert_into_tables_defs(tables_defs_statsdb_disk,"mysql_connections_hour", STATSDB_SQLITE_TABLE_MYSQL_CONNECTIONS_HOUR);
insert_into_tables_defs(tables_defs_statsdb_disk,"system_cpu_hour", STATSDB_SQLITE_TABLE_SYSTEM_CPU_HOUR);
insert_into_tables_defs(tables_defs_statsdb_disk,"system_memory_hour", STATSDB_SQLITE_TABLE_SYSTEM_MEMORY_HOUR);
insert_into_tables_defs(tables_defs_statsdb_disk,"mysql_connections_day", STATSDB_SQLITE_TABLE_MYSQL_CONNECTIONS_DAY);
insert_into_tables_defs(tables_defs_statsdb_disk,"system_cpu_day", STATSDB_SQLITE_TABLE_SYSTEM_CPU_DAY);
insert_into_tables_defs(tables_defs_statsdb_disk,"system_memory_day", STATSDB_SQLITE_TABLE_SYSTEM_MEMORY_DAY);
check_and_build_standard_tables(statsdb_mem, tables_defs_statsdb_disk);
check_and_build_standard_tables(statsdb_disk, tables_defs_statsdb_disk);
}
void ProxySQL_Statistics::print_version() {
fprintf(stderr,"Standard ProxySQL Statistics rev. %s -- %s -- %s\n", PROXYSQL_STATISTICS_VERSION, __FILE__, __TIMESTAMP__);
}
void ProxySQL_Statistics::check_and_build_standard_tables(SQLite3DB *db, std::vector<table_def_t *> *tables_defs) {
table_def_t *td;
db->execute("PRAGMA foreign_keys = OFF");
for (std::vector<table_def_t *>::iterator it=tables_defs->begin(); it!=tables_defs->end(); ++it) {
td=*it;
db->check_and_build_table(td->table_name, td->table_def);
}
db->execute("PRAGMA foreign_keys = ON");
}
void ProxySQL_Statistics::insert_into_tables_defs(std::vector<table_def_t *> *tables_defs, const char *table_name, const char *table_def) {
table_def_t *td = new table_def_t;
td->table_name=strdup(table_name);
td->table_def=strdup(table_def);
tables_defs->push_back(td);
}
void ProxySQL_Statistics::drop_tables_defs(std::vector<table_def_t *> *tables_defs) {
table_def_t *td;
while (!tables_defs->empty()) {
td=tables_defs->back();
free(td->table_name);
td->table_name=NULL;
free(td->table_def);
td->table_def=NULL;
tables_defs->pop_back();
delete td;
}
}
bool ProxySQL_Statistics::MySQL_Threads_Handler_timetoget(unsigned long long curtime) {
unsigned int i = (unsigned int)variables.stats_mysql_connections;
if (i) {
if (
( curtime > next_timer_MySQL_Threads_Handler )
||
( curtime + i*1000*1000 < next_timer_MySQL_Threads_Handler )
) {
next_timer_MySQL_Threads_Handler = curtime/1000/1000 + i;
next_timer_MySQL_Threads_Handler = next_timer_MySQL_Threads_Handler * 1000 * 1000;
return true;
}
}
return false;
}
bool ProxySQL_Statistics::system_cpu_timetoget(unsigned long long curtime) {
unsigned int i = (unsigned int)variables.stats_system_cpu;
if (i) {
if (
( curtime > next_timer_system_cpu )
||
( curtime + i*1000*1000 < next_timer_system_cpu )
) {
next_timer_system_cpu = curtime/1000/1000 + i;
next_timer_system_cpu = next_timer_system_cpu * 1000 * 1000;
return true;
}
}
return false;
}
bool ProxySQL_Statistics::system_memory_timetoget(unsigned long long curtime) {
unsigned int i = (unsigned int)variables.stats_system_memory;
if (i) {
if (
( curtime > next_timer_system_memory )
||
( curtime + i*1000*1000 < next_timer_system_memory )
) {
next_timer_system_memory = curtime/1000/1000 + i;
next_timer_system_memory = next_timer_system_memory * 1000 * 1000;
return true;
}
}
return false;
}
SQLite3_result * ProxySQL_Statistics::get_mysql_metrics() {
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, 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) {
if (resultset) {
delete resultset;
resultset = NULL;
}
free(error);
}
return resultset;
}
SQLite3_result * ProxySQL_Statistics::get_system_memory_metrics() {
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";
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
if (error) {
if (resultset) {
delete resultset;
resultset = NULL;
}
free(error);
}
return resultset;
}
SQLite3_result * ProxySQL_Statistics::get_system_cpu_metrics() {
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";
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
if (error) {
if (resultset) {
delete resultset;
resultset = NULL;
}
free(error);
}
return resultset;
}
void ProxySQL_Statistics::system_cpu_sets() {
int rc;
struct tms buf;
if (times(&buf) > -1) {
sqlite3 *mydb3=statsdb_disk->get_db();
sqlite3_stmt *statement1=NULL;
char *query1=NULL;
query1=(char *)"INSERT INTO system_cpu VALUES (?1, ?2, ?3)";
rc=sqlite3_prepare_v2(mydb3, query1, -1, &statement1, 0);
time_t ts = time(NULL);
rc = sqlite3_bind_int64(statement1, 1, ts); assert(rc==SQLITE_OK);
rc = sqlite3_bind_int64(statement1, 2, buf.tms_utime); assert(rc==SQLITE_OK);
rc = sqlite3_bind_int64(statement1, 3, buf.tms_stime); assert(rc==SQLITE_OK);
assert(rc==SQLITE_OK);
SAFE_SQLITE3_STEP2(statement1);
rc=sqlite3_clear_bindings(statement1); assert(rc==SQLITE_OK);
rc=sqlite3_reset(statement1);
sqlite3_finalize(statement1);
SQLite3_result *resultset = NULL;
int cols;
int affected_rows;
char *error = NULL;
char *query = (char *)"SELECT MAX(timestamp) FROM system_cpu";
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
if (error) {
if (resultset) {
delete resultset;
resultset = NULL;
}
free(error);
} 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);
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);
statsdb_disk->execute(buf);
}
}
delete resultset;
resultset = NULL;
sprintf(buf,"DELETE FROM system_cpu WHERE timestamp < %ld", ts - 3600*24*7);
statsdb_disk->execute(buf);
sprintf(buf,"DELETE FROM system_cpu_hour WHERE timestamp < %ld", ts - 3600*24*365);
statsdb_disk->execute(buf);
}
}
}
void ProxySQL_Statistics::system_memory_sets() {
int rc;
struct tms buf;
if (times(&buf) > -1) {
sqlite3 *mydb3=statsdb_disk->get_db();
sqlite3_stmt *statement1=NULL;
char *query1=NULL;
query1=(char *)"INSERT INTO system_memory VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)";
rc=sqlite3_prepare_v2(mydb3, query1, -1, &statement1, 0);
time_t ts = time(NULL);
size_t allocated = 0, resident = 0, active = 0, mapped = 0 , metadata = 0, retained = 0 , sz = sizeof(size_t);
mallctl("stats.resident", &resident, &sz, NULL, 0);
mallctl("stats.active", &active, &sz, NULL, 0);
mallctl("stats.allocated", &allocated, &sz, NULL, 0);
mallctl("stats.mapped", &mapped, &sz, NULL, 0);
mallctl("stats.metadata", &metadata, &sz, NULL, 0);
mallctl("stats.retained", &retained, &sz, NULL, 0);
rc = sqlite3_bind_int64(statement1, 1, ts); assert(rc==SQLITE_OK);
rc = sqlite3_bind_int64(statement1, 2, allocated); assert(rc==SQLITE_OK);
rc = sqlite3_bind_int64(statement1, 3, resident); assert(rc==SQLITE_OK);
rc = sqlite3_bind_int64(statement1, 4, active); assert(rc==SQLITE_OK);
rc = sqlite3_bind_int64(statement1, 5, mapped); assert(rc==SQLITE_OK);
rc = sqlite3_bind_int64(statement1, 6, metadata); assert(rc==SQLITE_OK);
rc = sqlite3_bind_int64(statement1, 7, retained); assert(rc==SQLITE_OK);
assert(rc==SQLITE_OK);
SAFE_SQLITE3_STEP2(statement1);
rc=sqlite3_clear_bindings(statement1); assert(rc==SQLITE_OK);
rc=sqlite3_reset(statement1);
sqlite3_finalize(statement1);
SQLite3_result *resultset = NULL;
int cols;
int affected_rows;
char *error = NULL;
char *query = (char *)"SELECT MAX(timestamp) FROM system_memory";
statsdb_disk->execute_statement(query, &error , &cols , &affected_rows , &resultset);
if (error) {
if (resultset) {
delete resultset;
resultset = NULL;
}
free(error);
} 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);
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);
statsdb_disk->execute(buf);
}
}
delete resultset;
resultset = 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);
}
}
}
void ProxySQL_Statistics::MySQL_Threads_Handler_sets(SQLite3_result *resultset) {
int rc;
if (resultset == NULL)
return;
sqlite3 *mydb3=statsdb_disk->get_db();
sqlite3_stmt *statement1=NULL;
//sqlite3_stmt *statement2=NULL;
//sqlite3_stmt *statement3=NULL;
char *query1=NULL;
//char *query2=NULL;
//char *query3=NULL;
query1=(char *)"INSERT INTO mysql_connections VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)";
rc=sqlite3_prepare_v2(mydb3, query1, -1, &statement1, 0);
assert(rc==SQLITE_OK);
//rc=sqlite3_prepare_v2(mydb3, query2, -1, &statement2, 0);
//assert(rc==SQLITE_OK);
//rc=sqlite3_prepare_v2(mydb3, query3, -1, &statement3, 0);
//assert(rc==SQLITE_OK);
int mysql_connections_values[12];
for (int i=0; i<12; i++) {
mysql_connections_values[i]=0;
}
mysql_connections_values[0] = time(NULL);
for (std::vector<SQLite3_row *>::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) {
SQLite3_row *r1=*it;
if (!strcasecmp(r1->fields[0],"Client_Connections_aborted")) {
mysql_connections_values[1]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"Client_Connections_connected")) {
mysql_connections_values[2]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"Client_Connections_created")) {
mysql_connections_values[3]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"Server_Connections_aborted")) {
mysql_connections_values[4]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"Server_Connections_connected")) {
mysql_connections_values[5]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"Server_Connections_created")) {
mysql_connections_values[6]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"ConnPool_get_conn_failure")) {
mysql_connections_values[7]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"ConnPool_get_conn_immediate")) {
mysql_connections_values[8]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"ConnPool_get_conn_success")) {
mysql_connections_values[9]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"Questions")) {
mysql_connections_values[10]=atoi(r1->fields[1]);
continue;
}
if (!strcasecmp(r1->fields[0],"Slow_queries")) {
mysql_connections_values[11]=atoi(r1->fields[1]);
continue;
}
}
for (int i=0; i<12; i++) {
rc=sqlite3_bind_int64(statement1, i+1, mysql_connections_values[i]); assert(rc==SQLITE_OK);
}
SAFE_SQLITE3_STEP2(statement1);
rc=sqlite3_clear_bindings(statement1); assert(rc==SQLITE_OK);
rc=sqlite3_reset(statement1); //assert(rc==SQLITE_OK);
sqlite3_finalize(statement1);
}

@ -36,10 +36,14 @@ LZ4_DIR=$(DEPS_PATH)/lz4/lz4
CLICKHOUSE_CPP_DIR=$(DEPS_PATH)/clickhouse-cpp/clickhouse-cpp
MICROHTTPD_DIR=$(DEPS_PATH)/libmicrohttpd/libmicrohttpd/src
MICROHTTPD_IDIR=$(MICROHTTPD_DIR)/include
MICROHTTPD_LDIR=$(MICROHTTPD_DIR)/microhttpd/.libs
IDIR=../include
LDIR=../lib
IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBCONFIG_IDIR) -I$(DAEMONPATH_IDIR) -I$(SQLITE3_DIR) -I$(CLICKHOUSE_CPP_DIR)
LDIRS=-L$(LDIR) -L$(JEMALLOC_LDIR) $(LIBCONFIG_LDIR) -L$(RE2_PATH)/obj -L$(MARIADB_LDIR) -L$(DAEMONPATH_LDIR) -L$(PCRE_LDIR)
IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBCONFIG_IDIR) -I$(DAEMONPATH_IDIR) -I$(SQLITE3_DIR) -I$(CLICKHOUSE_CPP_DIR) -I$(MICROHTTPD_IDIR)
LDIRS=-L$(LDIR) -L$(JEMALLOC_LDIR) $(LIBCONFIG_LDIR) -L$(RE2_PATH)/obj -L$(MARIADB_LDIR) -L$(DAEMONPATH_LDIR) -L$(PCRE_LDIR) -L$(MICROHTTPD_LDIR)
UNAME_S := $(shell uname -s)
@ -60,9 +64,9 @@ MYCXXFLAGS=-std=c++11 $(IDIRS) $(OPTZ) $(DEBUG) $(PSQLCH)
LDFLAGS+=
NOJEMALLOC := $(shell echo $(NOJEMALLOC))
ifeq ($(NOJEMALLOC),1)
MYLIBS=-Wl,--export-dynamic -Wl,-Bstatic -lconfig -lproxysql -ldaemon -lconfig++ -lre2 -lpcrecpp -lpcre -lmariadbclient -Wl,-Bdynamic -lpthread -lm -lz -lrt -lcrypto -lssl $(EXTRALINK)
MYLIBS=-Wl,--export-dynamic -Wl,-Bstatic -lconfig -lproxysql -ldaemon -lconfig++ -lre2 -lpcrecpp -lpcre -lmariadbclient -lmicrohttpd -Wl,-Bdynamic -lpthread -lm -lz -lrt -lcrypto -lssl $(EXTRALINK)
else
MYLIBS=-Wl,--export-dynamic -Wl,-Bstatic -lconfig -lproxysql -ldaemon -ljemalloc -lconfig++ -lre2 -lpcrecpp -lpcre -lmariadbclient -Wl,-Bdynamic -lpthread -lm -lz -lrt -lcrypto -lssl $(EXTRALINK)
MYLIBS=-Wl,--export-dynamic -Wl,-Bstatic -lconfig -lproxysql -ldaemon -ljemalloc -lconfig++ -lre2 -lpcrecpp -lpcre -lmariadbclient -lmicrohttpd -Wl,-Bdynamic -lpthread -lm -lz -lrt -lcrypto -lssl $(EXTRALINK)
endif
ifeq ($(UNAME_S),Darwin)

@ -202,6 +202,9 @@ ClickHouse_Server *GloClickHouseServer;
ProxySQL_Cluster *GloProxyCluster = NULL;
ProxySQL_Statistics *GloProxyStats = NULL;
void * mysql_worker_thread_func(void *arg) {
// __thr_sfp=l_mem_init();
@ -311,6 +314,9 @@ void ProxySQL_Main_process_global_variables(int argc, const char **argv) {
GloVars.admindb=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"proxysql.db")+2);
sprintf(GloVars.admindb,"%s/%s",GloVars.datadir, (char *)"proxysql.db");
GloVars.statsdb_disk=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"proxysql_stats.db")+2);
sprintf(GloVars.statsdb_disk,"%s/%s",GloVars.datadir, (char *)"proxysql_stats.db");
GloVars.errorlog=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"proxysql.log")+2);
sprintf(GloVars.errorlog,"%s/%s",GloVars.datadir, (char *)"proxysql.log");
@ -355,6 +361,9 @@ void ProxySQL_Main_init_Admin_module() {
GloProxyCluster = new ProxySQL_Cluster();
GloProxyCluster->init();
GloProxyCluster->print_version();
GloProxyStats = new ProxySQL_Statistics();
//GloProxyStats->init();
GloProxyStats->print_version();
GloAdmin = new ProxySQL_Admin();
GloAdmin->init();
GloAdmin->print_version();

Loading…
Cancel
Save