diff --git a/include/MySQL_Logger.hpp b/include/MySQL_Logger.hpp index b50a1fe9a..9431f71cc 100644 --- a/include/MySQL_Logger.hpp +++ b/include/MySQL_Logger.hpp @@ -44,7 +44,8 @@ private: uint64_t last_insert_id; ///< Last insert ID. uint64_t rows_sent; ///< Number of rows sent. uint32_t client_stmt_id; ///< Client statement ID. - const char* gtid; ///< GTID. + char * gtid; ///< GTID. + char *errmsg; ///< Error message, if generated by ProxySQL (not if generated by the backend) public: /** @@ -178,6 +179,12 @@ public: */ void set_gtid(MySQL_Session* sess); + /** + * @brief Sets the error message for the event + * @param _errmsg A pointer to the error + */ + void set_errmsg(const char * _errmsg); + /** * @brief Declares MySQL_Logger as a friend class, granting it access to private members of MySQL_Event. */ diff --git a/include/ProxySQL_Statistics.hpp b/include/ProxySQL_Statistics.hpp index 30ae1673e..ec2daad94 100644 --- a/include/ProxySQL_Statistics.hpp +++ b/include/ProxySQL_Statistics.hpp @@ -79,7 +79,7 @@ #define STATSDB_SQLITE_TABLE_HISTORY_MYSQL_QUERY_DIGEST "CREATE TABLE history_mysql_query_digest (dump_time INT , hostgroup INT , schemaname VARCHAR NOT NULL , username VARCHAR NOT NULL , client_address VARCHAR NOT NULL , digest VARCHAR NOT NULL , digest_text VARCHAR NOT NULL , count_star INTEGER NOT NULL , first_seen INTEGER NOT NULL , last_seen INTEGER NOT NULL , sum_time INTEGER NOT NULL , min_time INTEGER NOT NULL , max_time INTEGER NOT NULL , sum_rows_affected INTEGER NOT NULL , sum_rows_sent INTEGER NOT NULL)" -#define STATSDB_SQLITE_TABLE_HISTORY_MYSQL_QUERY_EVENTS "CREATE TABLE history_mysql_query_events (id INTEGER PRIMARY KEY AUTOINCREMENT , thread_id INTEGER , username TEXT , schemaname TEXT , start_time INTEGER , end_time INTEGER , query_digest TEXT , query TEXT , server TEXT , client TEXT , event_type INTEGER , hid INTEGER , extra_info TEXT , affected_rows INTEGER , last_insert_id INTEGER , rows_sent INTEGER , client_stmt_id INTEGER , gtid TEXT)" +#define STATSDB_SQLITE_TABLE_HISTORY_MYSQL_QUERY_EVENTS "CREATE TABLE history_mysql_query_events (id INTEGER PRIMARY KEY AUTOINCREMENT , thread_id INTEGER , username TEXT , schemaname TEXT , start_time INTEGER , end_time INTEGER , query_digest TEXT , query TEXT , server TEXT , client TEXT , event_type INTEGER , hid INTEGER , extra_info TEXT , affected_rows INTEGER , last_insert_id INTEGER , rows_sent INTEGER , client_stmt_id INTEGER , gtid TEXT , error TEXT)" class ProxySQL_Statistics { SQLite3DB *statsdb_mem; // internal statistics DB std::vector *tables_defs_statsdb_mem; diff --git a/lib/MySQL_Logger.cpp b/lib/MySQL_Logger.cpp index dab147cca..f413c6b13 100644 --- a/lib/MySQL_Logger.cpp +++ b/lib/MySQL_Logger.cpp @@ -63,6 +63,7 @@ MySQL_Event::MySQL_Event (log_event_type _et, uint32_t _thread_id, char * _usern rows_sent=0; client_stmt_id=0; gtid = NULL; + errmsg = nullptr; free_on_delete = false; // by default, this is false. This because pointers do not belong to this object } @@ -102,6 +103,12 @@ MySQL_Event::MySQL_Event(const MySQL_Event &other) { if (other.extra_info != nullptr) { extra_info = strdup(other.extra_info); } + if (other.gtid != nullptr) { + gtid = strdup(other.gtid); + } + if (other.errmsg != nullptr) { + errmsg = strdup(other.errmsg); + } free_on_delete = true; // pointers belong to this object } @@ -125,6 +132,12 @@ MySQL_Event::~MySQL_Event() { if (extra_info != nullptr) { free(extra_info); extra_info = nullptr; } + if (gtid != nullptr) { + free(gtid); gtid = nullptr; + } + if (errmsg != nullptr) { + free(errmsg); errmsg = nullptr; + } } } @@ -154,6 +167,10 @@ void MySQL_Event::set_gtid(MySQL_Session *sess) { } } +void MySQL_Event::set_errmsg(const char * _errmsg) { + errmsg = strdup(_errmsg); +} + void MySQL_Event::set_extra_info(char *_err) { extra_info = _err; } @@ -488,6 +505,9 @@ uint64_t MySQL_Event::write_query_format_2_json(std::fstream *f) { if (have_gtid == true) { j["last_gtid"] = gtid; } + if (errmsg != nullptr) { + j["error"] = errmsg; + } j["query"] = string(query_ptr,query_len); j["starttime_timestamp_us"] = start_time; { @@ -836,6 +856,9 @@ void MySQL_Logger::log_request(MySQL_Session *sess, MySQL_Data_Stream *myds, con } me.set_rows_sent(sess->CurrentQuery.rows_sent); me.set_gtid(sess); + if (errmsg != nullptr) { + me.set_errmsg(errmsg); + } int sl=0; char *sa=(char *)""; // default @@ -1199,13 +1222,13 @@ void MySQL_Logger::insertMysqlEventsIntoDb(SQLite3DB * db, const std::string& ta sqlite3_stmt *statement32=NULL; char *query1=NULL; char *query32=NULL; - const int numcols = 17; + const int numcols = 18; std::string query1s = ""; std::string query32s = ""; - std::string coldefs = "(thread_id, username, schemaname, start_time, end_time, query_digest, query, server, client, event_type, hid, extra_info, affected_rows, last_insert_id, rows_sent, client_stmt_id, gtid)"; + std::string coldefs = "(thread_id, username, schemaname, start_time, end_time, query_digest, query, server, client, event_type, hid, extra_info, affected_rows, last_insert_id, rows_sent, client_stmt_id, gtid, error)"; - query1s = "INSERT INTO " + tableName + coldefs + " VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17)"; + query1s = "INSERT INTO " + tableName + coldefs + " VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18)"; query32s = "INSERT INTO " + tableName + coldefs + " VALUES " + generate_multi_rows_query(32, numcols); query1 = (char *)query1s.c_str(); query32 = (char *)query32s.c_str(); @@ -1245,6 +1268,7 @@ void MySQL_Logger::insertMysqlEventsIntoDb(SQLite3DB * db, const std::string& ta rc = (*proxy_sqlite3_bind_int64)(statement32, (idx*numcols)+15, event->rows_sent); ASSERT_SQLITE_OK(rc, db); rc = (*proxy_sqlite3_bind_int)(statement32, (idx*numcols)+16, event->client_stmt_id); ASSERT_SQLITE_OK(rc, db); rc = (*proxy_sqlite3_bind_text)(statement32, (idx*numcols)+17, event->gtid, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, db); + rc = (*proxy_sqlite3_bind_text)(statement32, (idx*numcols)+18, event->errmsg, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, db); if (idx==31) { SAFE_SQLITE3_STEP2(statement32); rc=(*proxy_sqlite3_clear_bindings)(statement32); ASSERT_SQLITE_OK(rc, db); @@ -1270,6 +1294,7 @@ void MySQL_Logger::insertMysqlEventsIntoDb(SQLite3DB * db, const std::string& ta rc = (*proxy_sqlite3_bind_int64)(statement1, 15, event->rows_sent); ASSERT_SQLITE_OK(rc, db); rc = (*proxy_sqlite3_bind_int)(statement1, 16, event->client_stmt_id); ASSERT_SQLITE_OK(rc, db); rc = (*proxy_sqlite3_bind_text)(statement1, 17, event->gtid, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, db); + rc = (*proxy_sqlite3_bind_text)(statement1, 18, event->errmsg, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, db); SAFE_SQLITE3_STEP2(statement1); rc=(*proxy_sqlite3_clear_bindings)(statement1); ASSERT_SQLITE_OK(rc, db); rc=(*proxy_sqlite3_reset)(statement1); ASSERT_SQLITE_OK(rc, db); diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index dbd56721a..0d788e5c7 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -603,7 +603,7 @@ MHD_Result http_handler(void *cls, struct MHD_Connection *connection, const char #define ADMIN_SQLITE_TABLE_STATS_MYSQL_PREPARED_STATEMENTS_INFO "CREATE TABLE stats_mysql_prepared_statements_info (global_stmt_id INT NOT NULL , schemaname VARCHAR NOT NULL , username VARCHAR NOT NULL , digest VARCHAR NOT NULL , ref_count_client INT NOT NULL , ref_count_server INT NOT NULL , num_columns INT NOT NULL, num_params INT NOT NULL, query VARCHAR NOT NULL)" -#define ADMIN_SQLITE_TABLE_STATS_MYSQL_QUERY_EVENTS "CREATE TABLE stats_mysql_query_events (id INTEGER PRIMARY KEY AUTOINCREMENT , thread_id INTEGER , username TEXT , schemaname TEXT , start_time INTEGER , end_time INTEGER , query_digest TEXT , query TEXT , server TEXT , client TEXT , event_type INTEGER , hid INTEGER , extra_info TEXT , affected_rows INTEGER , last_insert_id INTEGER , rows_sent INTEGER , client_stmt_id INTEGER , gtid TEXT)" +#define ADMIN_SQLITE_TABLE_STATS_MYSQL_QUERY_EVENTS "CREATE TABLE stats_mysql_query_events (id INTEGER PRIMARY KEY AUTOINCREMENT , thread_id INTEGER , username TEXT , schemaname TEXT , start_time INTEGER , end_time INTEGER , query_digest TEXT , query TEXT , server TEXT , client TEXT , event_type INTEGER , hid INTEGER , extra_info TEXT , affected_rows INTEGER , last_insert_id INTEGER , rows_sent INTEGER , client_stmt_id INTEGER , gtid TEXT , error TEXT)" static char * admin_variables_names[]= {