MXS-2050 Use global counter to detect log rotation request
Modules need to check the number regularly to detect a new log rotation.
This commit is contained in:
parent
98a081f65b
commit
90e5b80b71
@ -51,9 +51,24 @@ typedef MXB_LOG_THROTTLING MXS_LOG_THROTTLING;
|
||||
*/
|
||||
bool mxs_log_init(const char* ident, const char* logdir, mxs_log_target_t target);
|
||||
|
||||
/**
|
||||
* Close and reopen MaxScale log files. Also increments a global rotation counter which modules
|
||||
* can read to see if they should rotate their own logs.
|
||||
*
|
||||
* @return True if MaxScale internal logs were rotated. If false is returned, the rotation counter is not
|
||||
* incremented.
|
||||
*/
|
||||
bool mxs_log_rotate();
|
||||
|
||||
/**
|
||||
* Get the value of the log rotation counter. The counter is incremented when user requests a log rotation.
|
||||
*
|
||||
* @return Counter value
|
||||
*/
|
||||
int mxs_get_log_rotation_count();
|
||||
|
||||
#define mxs_log_finish mxb_log_finish
|
||||
#define mxs_log_message mxb_log_message
|
||||
#define mxs_log_rotate mxb_log_rotate
|
||||
|
||||
#define mxs_log_get_throttling mxb_log_get_throttling
|
||||
#define mxs_log_is_priority_enabled mxb_log_is_priority_enabled
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cinttypes>
|
||||
|
||||
#include <maxbase/log.hh>
|
||||
@ -28,6 +29,12 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
struct ThisUnit
|
||||
{
|
||||
std::atomic<int> rotation_count {0};
|
||||
};
|
||||
ThisUnit this_unit;
|
||||
|
||||
const char* LOGFILE_NAME = "maxscale.log";
|
||||
|
||||
size_t mxs_get_context(char* buffer, size_t len)
|
||||
@ -129,3 +136,18 @@ json_t* mxs_logs_to_json(const char* host)
|
||||
|
||||
return mxs_json_resource(host, MXS_JSON_API_LOGS, data);
|
||||
}
|
||||
|
||||
bool mxs_log_rotate()
|
||||
{
|
||||
bool rotated = mxb_log_rotate();
|
||||
if (rotated)
|
||||
{
|
||||
this_unit.rotation_count.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
int mxs_get_log_rotation_count()
|
||||
{
|
||||
return this_unit.rotation_count.load(std::memory_order_relaxed);
|
||||
}
|
@ -99,14 +99,6 @@ const MXS_ENUM_VALUE log_data_values[] =
|
||||
void print_string_replace_newlines(const char* sql_string, size_t sql_str_len,
|
||||
const char* rep_newline, std::stringstream* output);
|
||||
|
||||
/**
|
||||
* Open a file if it doesn't exist.
|
||||
*
|
||||
* @param filename Filename
|
||||
* @param ppFile Double pointer to old file. The file can be null.
|
||||
* @return True if new file was opened successfully. False, if file already existed or if new file
|
||||
* could not be opened. If false is returned, the caller should check that the file object exists.
|
||||
*/
|
||||
bool check_replace_file(const string& filename, FILE** ppFile);
|
||||
|
||||
}
|
||||
@ -115,6 +107,7 @@ QlaInstance::QlaInstance(const string& name, MXS_CONFIG_PARAMETER* params)
|
||||
: m_settings(params)
|
||||
, m_name(name)
|
||||
, m_session_data_flags(m_settings.log_file_data_flags & ~LOG_DATA_SESSION)
|
||||
, m_rotation_count(mxs_get_log_rotation_count())
|
||||
{
|
||||
}
|
||||
|
||||
@ -151,6 +144,7 @@ QlaFilterSession::QlaFilterSession(QlaInstance& instance, MXS_SESSION* session)
|
||||
, m_remote(session_get_remote(session))
|
||||
, m_service(session->service->name())
|
||||
, m_ses_id(session->ses_id)
|
||||
, m_rotation_count(mxs_get_log_rotation_count())
|
||||
{
|
||||
}
|
||||
|
||||
@ -374,22 +368,29 @@ json_t* QlaInstance::diagnostics_json() const
|
||||
return rval;
|
||||
}
|
||||
|
||||
void QlaFilterSession::check_session_log_rotation()
|
||||
void QlaInstance::check_reopen_file(const string& filename, uint64_t data_flags, FILE** ppFile) const
|
||||
{
|
||||
if (check_replace_file(m_filename, &m_logfile))
|
||||
if (check_replace_file(filename, ppFile))
|
||||
{
|
||||
auto fp = *ppFile;
|
||||
// New file created, print the log header.
|
||||
string header = m_instance.generate_log_header(m_instance.m_session_data_flags);
|
||||
if (!m_instance.write_to_logfile(m_logfile, header))
|
||||
string header = generate_log_header(data_flags);
|
||||
if (!write_to_logfile(fp, header))
|
||||
{
|
||||
MXS_ERROR(HEADER_ERROR, m_filename.c_str(), errno, mxs_strerror(errno));
|
||||
fclose(m_logfile);
|
||||
m_logfile = nullptr;
|
||||
MXS_ERROR(HEADER_ERROR, filename.c_str(), errno, mxs_strerror(errno));
|
||||
fclose(fp);
|
||||
fp = nullptr;
|
||||
*ppFile = fp;
|
||||
}
|
||||
}
|
||||
// Either the old file existed or file creation failed.
|
||||
}
|
||||
|
||||
void QlaInstance::check_reopen_session_file(const std::string& filename, FILE** ppFile) const
|
||||
{
|
||||
check_reopen_file(filename, m_session_data_flags, ppFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write QLA log entry/entries to disk
|
||||
*
|
||||
@ -397,13 +398,13 @@ void QlaFilterSession::check_session_log_rotation()
|
||||
*/
|
||||
void QlaFilterSession::write_log_entries(const LogEventElems& elems)
|
||||
{
|
||||
const int check_interval = 60; // Check log rotation once per minute.
|
||||
if (m_instance.m_settings.write_session_log)
|
||||
{
|
||||
if (m_file_check_timer.split().secs() > check_interval)
|
||||
int global_rot_count = mxs_get_log_rotation_count();
|
||||
if (global_rot_count > m_rotation_count)
|
||||
{
|
||||
check_session_log_rotation();
|
||||
m_file_check_timer.restart();
|
||||
m_rotation_count = global_rot_count;
|
||||
m_instance.check_reopen_session_file(m_filename, &m_logfile);
|
||||
}
|
||||
|
||||
if (m_logfile)
|
||||
@ -703,7 +704,13 @@ void QlaFilterSession::write_session_log_entry(const string& entry)
|
||||
void QlaInstance::write_unified_log_entry(const string& entry)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_file_lock);
|
||||
// TODO: Handle log rotation here.
|
||||
int global_rot_count = mxs_get_log_rotation_count();
|
||||
if (global_rot_count > m_rotation_count)
|
||||
{
|
||||
m_rotation_count = global_rot_count;
|
||||
check_reopen_file(m_unified_filename, m_settings.log_file_data_flags, &m_unified_fp);
|
||||
}
|
||||
|
||||
if (m_unified_fp)
|
||||
{
|
||||
if (!write_to_logfile(m_unified_fp, entry))
|
||||
@ -773,6 +780,14 @@ void print_string_replace_newlines(const char* sql_string,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a file if it doesn't exist.
|
||||
*
|
||||
* @param filename Filename
|
||||
* @param ppFile Double pointer to old file. The file can be null.
|
||||
* @return True if new file was opened successfully. False, if file already existed or if new file
|
||||
* could not be opened. If false is returned, the caller should check that the file object exists.
|
||||
*/
|
||||
bool check_replace_file(const string& filename, FILE** ppFile)
|
||||
{
|
||||
auto zfilename = filename.c_str();
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
std::string generate_log_header(uint64_t data_flags) const;
|
||||
|
||||
FILE* open_session_log_file(const std::string& filename) const;
|
||||
void check_reopen_session_file(const std::string& filename, FILE** ppFile) const;
|
||||
void write_unified_log_entry(const std::string& contents);
|
||||
bool write_to_logfile(FILE* fp, const std::string& contents) const;
|
||||
|
||||
@ -121,10 +122,12 @@ public:
|
||||
private:
|
||||
bool open_unified_logfile();
|
||||
FILE* open_log_file(uint64_t data_flags, const std::string& filename) const;
|
||||
void check_reopen_file(const std::string& filename, uint64_t data_flags, FILE** ppFile) const;
|
||||
|
||||
std::mutex m_file_lock; /* Protects access to the unified log file */
|
||||
std::string m_unified_filename; /* Filename of the unified log file */
|
||||
FILE* m_unified_fp {nullptr}; /* Unified log file. */
|
||||
int m_rotation_count {0}; /* Log rotation counter */
|
||||
bool m_write_error_logged {false}; /* Avoid repeatedly printing some errors/warnings. */
|
||||
|
||||
};
|
||||
@ -183,7 +186,7 @@ private:
|
||||
pcre2_match_data* m_mdata {nullptr}; /* Regex match data */
|
||||
|
||||
FILE* m_logfile {nullptr}; /* The session-specific log file */
|
||||
mxb::StopWatch m_file_check_timer; /* When was file checked for rotation */
|
||||
int m_rotation_count {0}; /* Log rotation counter */
|
||||
bool m_write_error_logged {false}; /* Has write error been logged */
|
||||
|
||||
/**
|
||||
@ -223,7 +226,6 @@ private:
|
||||
|
||||
LogEventData m_event_data; /* Information about the latest event, used if logging execution time. */
|
||||
|
||||
void check_session_log_rotation();
|
||||
void write_log_entries(const LogEventElems& elems);
|
||||
void write_session_log_entry(const std::string& entry);
|
||||
std::string generate_log_entry(uint64_t data_flags, const LogEventElems& elems) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user