MXS-2592 Add configuration for session specific in-memory log
When enabled each session will write log messages in the in-memory log. If session ends in error this log is written to the actual log in disk.
This commit is contained in:
@ -160,6 +160,7 @@ const char CN_SERVER[] = "server";
|
||||
const char CN_SERVICES[] = "services";
|
||||
const char CN_SERVICE[] = "service";
|
||||
const char CN_SESSIONS[] = "sessions";
|
||||
const char CN_SESSION_TRACE[] = "session_trace";
|
||||
const char CN_SESSION_TRACK_TRX_STATE[] = "session_track_trx_state";
|
||||
const char CN_SKIP_PERMISSION_CHECKS[] = "skip_permission_checks";
|
||||
const char CN_SOCKET[] = "socket";
|
||||
@ -317,6 +318,7 @@ const MXS_MODULE_PARAM config_service_params[] =
|
||||
{CN_RETRY_ON_FAILURE, MXS_MODULE_PARAM_BOOL, "true"},
|
||||
{CN_SESSION_TRACK_TRX_STATE, MXS_MODULE_PARAM_BOOL, "false"},
|
||||
{CN_RETAIN_LAST_STATEMENTS, MXS_MODULE_PARAM_INT, "-1"},
|
||||
{CN_SESSION_TRACE, MXS_MODULE_PARAM_INT, "0"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@ -2602,6 +2604,21 @@ static int handle_global_item(const char* name, const char* value)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(name, CN_SESSION_TRACE) == 0)
|
||||
{
|
||||
char* endptr;
|
||||
int intval = strtol(value, &endptr, 0);
|
||||
if (*endptr == '\0' && intval >= 0)
|
||||
{
|
||||
session_set_session_trace(intval);
|
||||
mxb_log_set_session_trace(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Invalid value for '%s': %s", CN_SESSION_TRACE, value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(name, CN_LOAD_PERSISTED_CONFIGS) == 0)
|
||||
{
|
||||
int b = config_truth_value(value);
|
||||
|
||||
@ -432,6 +432,7 @@ static void sigfatal_handler(int i)
|
||||
if (dcb->session)
|
||||
{
|
||||
session_dump_statements(dcb->session);
|
||||
session_dump_log(dcb->session);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ public:
|
||||
};
|
||||
|
||||
typedef std::deque<QueryInfo> QueryInfos;
|
||||
|
||||
using Log = std::deque<std::string>;
|
||||
using FilterList = std::vector<SessionFilter>;
|
||||
|
||||
Session(SERVICE* service);
|
||||
@ -121,8 +121,11 @@ public:
|
||||
void book_server_response(SERVER* pServer, bool final_response);
|
||||
void book_last_as_complete();
|
||||
void reset_server_bookkeeping();
|
||||
void append_session_log(std::string);
|
||||
void dump_session_log();
|
||||
|
||||
json_t* queries_as_json() const;
|
||||
json_t* log_as_json() const;
|
||||
|
||||
void link_backend_dcb(DCB* dcb)
|
||||
{
|
||||
@ -148,6 +151,7 @@ private:
|
||||
int m_current_query = -1; /*< The index of the current query */
|
||||
DCBSet m_dcb_set; /*< Set of associated backend DCBs */
|
||||
uint32_t m_retain_last_statements; /*< How many statements be retained */
|
||||
Log m_log; /*< Session specific in-memory log */
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -47,13 +47,22 @@ size_t mxs_get_context(char* buffer, size_t len)
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void mxs_log_in_memory(const char* msg, size_t len)
|
||||
{
|
||||
MXS_SESSION* session = session_get_current();
|
||||
if (session)
|
||||
{
|
||||
session_append_log(session, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool mxs_log_init(const char* ident, const char* logdir, mxs_log_target_t target)
|
||||
{
|
||||
mxb::Logger::set_ident("MariaDB MaxScale");
|
||||
|
||||
return mxb_log_init(ident, logdir, LOGFILE_NAME, target, mxs_get_context);
|
||||
return mxb_log_init(ident, logdir, LOGFILE_NAME, target, mxs_get_context, mxs_log_in_memory);
|
||||
}
|
||||
|
||||
namespace
|
||||
|
||||
@ -62,11 +62,13 @@ struct
|
||||
uint64_t next_session_id;
|
||||
uint32_t retain_last_statements;
|
||||
session_dump_statements_t dump_statements;
|
||||
uint32_t session_trace;
|
||||
} this_unit =
|
||||
{
|
||||
1,
|
||||
0,
|
||||
SESSION_DUMP_STATEMENTS_NEVER
|
||||
SESSION_DUMP_STATEMENTS_NEVER,
|
||||
0
|
||||
};
|
||||
|
||||
static struct session dummy_session()
|
||||
@ -909,6 +911,9 @@ json_t* session_json_data(const Session* session, const char* host)
|
||||
json_t* queries = session->queries_as_json();
|
||||
json_object_set_new(attr, "queries", queries);
|
||||
|
||||
json_t* log = session->log_as_json();
|
||||
json_object_set_new(attr, "log", log);
|
||||
|
||||
json_object_set_new(data, CN_ATTRIBUTES, attr);
|
||||
json_object_set_new(data, CN_LINKS, mxs_json_self_link(host, CN_SESSIONS, ss.str().c_str()));
|
||||
|
||||
@ -1111,6 +1116,32 @@ void session_dump_statements(MXS_SESSION* session)
|
||||
pSession->dump_statements();
|
||||
}
|
||||
|
||||
void session_set_session_trace(uint32_t value)
|
||||
{
|
||||
this_unit.session_trace = value;
|
||||
}
|
||||
|
||||
uint32_t session_get_session_trace()
|
||||
{
|
||||
return this_unit.session_trace;
|
||||
}
|
||||
|
||||
void session_append_log(MXS_SESSION* pSession, const char* log)
|
||||
{
|
||||
// Ignore dummy and listener sessions
|
||||
if (pSession->state != SESSION_STATE_DUMMY
|
||||
&& pSession->state != SESSION_STATE_LISTENER
|
||||
&& pSession->state != SESSION_STATE_LISTENER_STOPPED)
|
||||
{
|
||||
static_cast<Session*>(pSession)->append_session_log(std::string(log));
|
||||
}
|
||||
}
|
||||
|
||||
void session_dump_log(MXS_SESSION* pSession)
|
||||
{
|
||||
static_cast<Session*>(pSession)->dump_session_log();
|
||||
}
|
||||
|
||||
class DelayedRoutingTask
|
||||
{
|
||||
DelayedRoutingTask(const DelayedRoutingTask&) = delete;
|
||||
@ -1365,6 +1396,18 @@ json_t* Session::queries_as_json() const
|
||||
return pQueries;
|
||||
}
|
||||
|
||||
json_t* Session::log_as_json() const
|
||||
{
|
||||
json_t* pLog = json_array();
|
||||
|
||||
for (const auto& i : m_log)
|
||||
{
|
||||
json_array_append_new(pLog, json_string(i.c_str()));
|
||||
}
|
||||
|
||||
return pLog;
|
||||
}
|
||||
|
||||
bool Session::setup_filters(Service* service)
|
||||
{
|
||||
for (const auto& a : service->get_filters())
|
||||
@ -1724,3 +1767,28 @@ void Session::QueryInfo::reset_server_bookkeeping()
|
||||
m_completed.tv_nsec = 0;
|
||||
m_complete = false;
|
||||
}
|
||||
|
||||
void Session::append_session_log(std::string log)
|
||||
{
|
||||
m_log.push_front(log);
|
||||
|
||||
if (m_log.size() >= this_unit.session_trace)
|
||||
{
|
||||
m_log.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void Session::dump_session_log()
|
||||
{
|
||||
if (!(m_log.empty()))
|
||||
{
|
||||
std::string log;
|
||||
|
||||
for (const auto& s : m_log)
|
||||
{
|
||||
log += s;
|
||||
}
|
||||
|
||||
MXS_NOTICE("Session log for session (%" PRIu64"): \n%s ", ses_id, log.c_str());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user