diff --git a/include/maxscale/config.h b/include/maxscale/config.h index 99eac2881..ba6786a56 100644 --- a/include/maxscale/config.h +++ b/include/maxscale/config.h @@ -99,6 +99,7 @@ extern const char CN_AUTH_READ_TIMEOUT[]; extern const char CN_AUTH_WRITE_TIMEOUT[]; extern const char CN_AUTO[]; extern const char CN_CONNECTION_TIMEOUT[]; +extern const char CN_DUMP_LAST_STATEMENTS[]; extern const char CN_DATA[]; extern const char CN_DEFAULT[]; extern const char CN_DESCRIPTION[]; diff --git a/include/maxscale/session.h b/include/maxscale/session.h index 2b4e3ade3..4c5b71b43 100644 --- a/include/maxscale/session.h +++ b/include/maxscale/session.h @@ -83,6 +83,13 @@ typedef enum SESSION_TRX_READ_WRITE_ENDING = (SESSION_TRX_ENDING_BIT | SESSION_TRX_READ_WRITE), } mxs_session_trx_state_t; +typedef enum +{ + SESSION_DUMP_STATEMENTS_NEVER, + SESSION_DUMP_STATEMENTS_ON_CLOSE, + SESSION_DUMP_STATEMENTS_ON_ERROR, +} session_dump_statements_t; + /** * The session statistics structure */ @@ -496,7 +503,7 @@ uint64_t session_get_current_id(); * * @param n The number of statements. */ -void session_retain_last_statements(uint32_t n); +void session_set_retain_last_statements(uint32_t n); /** * @brief Retain provided statement, if configured to do so. @@ -513,4 +520,18 @@ void session_retain_statement(MXS_SESSION* session, GWBUF* buffer); */ void session_dump_statements(MXS_SESSION* pSession); +/** + * @brief Specify whether statements should be dumped or not. + * + * @param value Whether and when to dump statements. + */ +void session_set_dump_statements(session_dump_statements_t value); + +/** + * @brief Returns in what contexts statements should be dumped. + * + * @return Whether and when to dump statements. + */ +session_dump_statements_t session_get_dump_statements(); + MXS_END_DECLS diff --git a/server/core/config.cc b/server/core/config.cc index e5a92b25b..408f14342 100644 --- a/server/core/config.cc +++ b/server/core/config.cc @@ -80,6 +80,7 @@ const char CN_CONNECTION_TIMEOUT[] = "connection_timeout"; const char CN_DATA[] = "data"; const char CN_DEFAULT[] = "default"; const char CN_DESCRIPTION[] = "description"; +const char CN_DUMP_LAST_STATEMENTS[] = "dump_last_statements"; const char CN_ENABLE_ROOT_USER[] = "enable_root_user"; const char CN_FILTERS[] = "filters"; const char CN_FILTER[] = "filter"; @@ -1740,13 +1741,33 @@ handle_global_item(const char *name, const char *value) int intval = strtol(value, &endptr, 0); if (*endptr == '\0' && intval >= 0) { - session_retain_last_statements(intval); + session_set_retain_last_statements(intval); } else { MXS_ERROR("Invalid value for '%s': %s", CN_RETAIN_LAST_STATEMENTS, value); } } + else if (strcmp(name, CN_DUMP_LAST_STATEMENTS) == 0) + { + if (strcmp(value, "on_close") == 0) + { + session_set_dump_statements(SESSION_DUMP_STATEMENTS_ON_CLOSE); + } + else if (strcmp(value, "on_error") == 0) + { + session_set_dump_statements(SESSION_DUMP_STATEMENTS_ON_ERROR); + } + else if (strcmp(value, "never") == 0) + { + session_set_dump_statements(SESSION_DUMP_STATEMENTS_NEVER); + } + else + { + MXS_ERROR("%s can have the values 'never', 'on_close' or 'on_error'.", + CN_DUMP_LAST_STATEMENTS); + } + } else { for (i = 0; lognames[i].name; i++) diff --git a/server/core/gateway.cc b/server/core/gateway.cc index 321d3dbf9..8d3d0edc0 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -3221,7 +3221,7 @@ static void retain_last_statements(const char* arg) n = 0; } - session_retain_last_statements(n); + session_set_retain_last_statements(n); } static void redirect_output_to_file(const char* arg) diff --git a/server/core/session.cc b/server/core/session.cc index 2434efc2e..322e057f2 100644 --- a/server/core/session.cc +++ b/server/core/session.cc @@ -53,6 +53,7 @@ using std::stringstream; static uint64_t next_session_id = 1; static uint32_t retain_last_statements = 0; +static session_dump_statements_t dump_statements = SESSION_DUMP_STATEMENTS_NEVER; static struct session session_dummy_struct; @@ -392,6 +393,11 @@ static void session_free(MXS_SESSION *session) static void session_final_free(MXS_SESSION *session) { + if (dump_statements == SESSION_DUMP_STATEMENTS_ON_CLOSE) + { + session_dump_statements(session); + } + gwbuf_free(session->stmt.buffer); delete session->last_statements; MXS_FREE(session); @@ -1111,11 +1117,21 @@ uint64_t session_get_current_id() return session ? session->ses_id : 0; } -void session_retain_last_statements(uint32_t n) +void session_set_retain_last_statements(uint32_t n) { retain_last_statements = n; } +void session_set_dump_statements(session_dump_statements_t value) +{ + dump_statements = value; +} + +session_dump_statements_t session_get_dump_statements() +{ + return dump_statements; +} + void session_retain_statement(MXS_SESSION* pSession, GWBUF* pBuffer) { if (retain_last_statements) diff --git a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc index 048aac322..aabc618d5 100644 --- a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc +++ b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc @@ -1410,7 +1410,11 @@ static int gw_client_hangup_event(DCB *dcb) CHK_SESSION(session); if (session->state != SESSION_STATE_DUMMY && !session_valid_for_pool(session)) { - session_dump_statements(session); + if (session_get_dump_statements() == SESSION_DUMP_STATEMENTS_ON_ERROR) + { + session_dump_statements(session); + } + // The client did not send a COM_QUIT packet modutil_send_mysql_err_packet(dcb, 0, 0, 1927, "08S01", "Connection killed by MaxScale"); }