mirror of
https://github.com/codership/wsrep-lib.git
synced 2025-07-28 20:02:00 +03:00
Add report_event() method into reporter object
Report event will write json formatted event into report file. Include Boost headers as system headers to avoid generating excessive warnings. Enable extra tests for selected compilers in actions.
This commit is contained in:
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
@ -159,19 +159,27 @@ jobs:
|
|||||||
else
|
else
|
||||||
export CXX="ccache clang++-${{ matrix.config.version }}"
|
export CXX="ccache clang++-${{ matrix.config.version }}"
|
||||||
fi
|
fi
|
||||||
if [ ${{ matrix.config.version }} == "4.8" ]
|
if [ ${{ matrix.config.CC }} == "gcc" ] && [ ${{ matrix.config.version }} == "4.8" ]
|
||||||
then
|
then
|
||||||
STRICT=OFF
|
STRICT=OFF
|
||||||
DBSIM=OFF
|
DBSIM=OFF
|
||||||
|
TESTS_EXTRA=OFF
|
||||||
|
elif [ ${{ matrix.config.CC }} == "gcc" ] && [ ${{ matrix.config.version }} == "5" ]
|
||||||
|
then
|
||||||
|
STRICT=ON
|
||||||
|
DBSIM=ON
|
||||||
|
TESTS_EXTRA=OFF
|
||||||
else
|
else
|
||||||
STRICT=ON
|
STRICT=ON
|
||||||
DBSIM=ON
|
DBSIM=ON
|
||||||
|
TESTS_EXTRA=ON
|
||||||
fi
|
fi
|
||||||
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.config.type }} \
|
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.config.type }} \
|
||||||
-DWSREP_LIB_MAINTAINER_MODE:BOOL=ON \
|
-DWSREP_LIB_MAINTAINER_MODE:BOOL=ON \
|
||||||
-DWSREP_LIB_STRICT_BUILD_FLAGS:BOOL=$STRICT \
|
-DWSREP_LIB_STRICT_BUILD_FLAGS:BOOL=$STRICT \
|
||||||
-DWSREP_LIB_WITH_DBSIM:BOOL=$DBSIM \
|
-DWSREP_LIB_WITH_DBSIM:BOOL=$DBSIM \
|
||||||
-DWSREP_LIB_WITH_ASAN:BOOL=ON .
|
-DWSREP_LIB_WITH_ASAN:BOOL=ON \
|
||||||
|
-DWSREP_LIB_WITH_UNIT_TESTS_EXTRA:BOOL=$TESTS_EXTRA
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
@ -123,6 +123,7 @@ endif()
|
|||||||
set(MIN_BOOST_VERSION "1.54.0")
|
set(MIN_BOOST_VERSION "1.54.0")
|
||||||
if (WSREP_LIB_WITH_UNIT_TESTS)
|
if (WSREP_LIB_WITH_UNIT_TESTS)
|
||||||
if (WSREP_LIB_WITH_UNIT_TESTS_EXTRA)
|
if (WSREP_LIB_WITH_UNIT_TESTS_EXTRA)
|
||||||
|
message(STATUS "Compiling extra unit tests")
|
||||||
set(json_HEADER "boost/json/src.hpp")
|
set(json_HEADER "boost/json/src.hpp")
|
||||||
# Extra tests may require packages from very recent boost which may be
|
# Extra tests may require packages from very recent boost which may be
|
||||||
# unavailable on the system. In such case download private boost distro.
|
# unavailable on the system. In such case download private boost distro.
|
||||||
@ -140,17 +141,14 @@ if (WSREP_LIB_WITH_UNIT_TESTS)
|
|||||||
PATHS ${WITH_BOOST}/lib/cmake
|
PATHS ${WITH_BOOST}/lib/cmake
|
||||||
NO_DEFAULT_PATH
|
NO_DEFAULT_PATH
|
||||||
)
|
)
|
||||||
# Boost 1.76.0 comes very sloppy (and not only in JSON department)
|
# Include as system header to be more permissive about generated
|
||||||
# - need to disable some checks.
|
# warnings.
|
||||||
set(ADDITIONAL_CXX_FLAGS "-Wno-effc++ -Wno-conversion -Wno-suggest-override -Wno-overloaded-virtual")
|
set(CMAKE_REQUIRED_FLAGS "-isystem ${BOOST_INCLUDE_DIR}")
|
||||||
set(ADDITIONAL_CXX_INCLUDES ${BOOST_INCLUDE_DIR})
|
check_include_file_cxx(${json_HEADER} json_FOUND)
|
||||||
check_include_file_cxx(${json_HEADER} json_FOUND
|
|
||||||
"-I${ADDITIONAL_CXX_INCLUDES} ${ADDITIONAL_CXX_FLAGS}"
|
|
||||||
)
|
|
||||||
if (NOT json_FOUND)
|
if (NOT json_FOUND)
|
||||||
message(FATAL_ERROR "Required header 'boost/json.hpp' not found: ${json_FOUND}")
|
message(FATAL_ERROR "Required header 'boost/json.hpp' not found: ${json_FOUND}")
|
||||||
else()
|
else()
|
||||||
include_directories(SYSTEM ${ADDITIONAL_CXX_INCLUDES})
|
include_directories(SYSTEM ${BOOST_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
|
@ -57,6 +57,15 @@ namespace wsrep
|
|||||||
*/
|
*/
|
||||||
void report_progress(const std::string& json);
|
void report_progress(const std::string& json);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report provider event.
|
||||||
|
* {
|
||||||
|
* "status": "Status string",
|
||||||
|
* "message": "Message from the provider"
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
void report_event(const std::string& json);
|
||||||
|
|
||||||
enum log_level
|
enum log_level
|
||||||
{
|
{
|
||||||
error,
|
error,
|
||||||
@ -100,14 +109,17 @@ namespace wsrep
|
|||||||
|
|
||||||
std::deque<log_msg> err_msg_;
|
std::deque<log_msg> err_msg_;
|
||||||
std::deque<log_msg> warn_msg_;
|
std::deque<log_msg> warn_msg_;
|
||||||
|
std::deque<log_msg> events_;
|
||||||
size_t const max_msg_;
|
size_t const max_msg_;
|
||||||
|
|
||||||
static void write_log_msgs(std::ostream& os,
|
|
||||||
const std::string& label,
|
|
||||||
const std::deque<log_msg>& msgs);
|
|
||||||
static void write_log_msg(std::ostream& os,
|
static void write_log_msg(std::ostream& os,
|
||||||
const log_msg& msg);
|
const log_msg& msg);
|
||||||
|
static void write_event(std::ostream& os,
|
||||||
|
const log_msg& msg);
|
||||||
|
static void write_array(std::ostream& os, const std::string& label,
|
||||||
|
const std::deque<log_msg>& events,
|
||||||
|
void (*element_writer)(std::ostream& os,
|
||||||
|
const log_msg& msg));
|
||||||
substates substate_map(enum server_state::state state);
|
substates substate_map(enum server_state::state state);
|
||||||
float progress_map(float progress) const;
|
float progress_map(float progress) const;
|
||||||
void write_file(double timestamp);
|
void write_file(double timestamp);
|
||||||
|
@ -72,6 +72,7 @@ wsrep::reporter::reporter(wsrep::mutex& mutex,
|
|||||||
, initialized_(false)
|
, initialized_(false)
|
||||||
, err_msg_()
|
, err_msg_()
|
||||||
, warn_msg_()
|
, warn_msg_()
|
||||||
|
, events_()
|
||||||
, max_msg_(max_msg)
|
, max_msg_(max_msg)
|
||||||
{
|
{
|
||||||
template_[file_name_.length() + TEMP_EXTENSION.length()] = '\0';
|
template_[file_name_.length() + TEMP_EXTENSION.length()] = '\0';
|
||||||
@ -137,6 +138,37 @@ wsrep::reporter::substate_map(enum wsrep::server_state::state const state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See https://www.ietf.org/rfc/rfc4627.txt
|
||||||
|
static std::string escape_json(const std::string& str)
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
for (auto c = str.cbegin(); c != str.cend(); ++c)
|
||||||
|
{
|
||||||
|
switch (*c)
|
||||||
|
{
|
||||||
|
case '"': os << "\\\""; break;
|
||||||
|
case '\\': os << "\\\\"; break;
|
||||||
|
case '/': os << "\\/"; break;
|
||||||
|
case '\b': os << "\\b"; break;
|
||||||
|
case '\f': os << "\\f"; break;
|
||||||
|
case '\n': os << "\\n"; break;
|
||||||
|
case '\r': os << "\\r"; break;
|
||||||
|
case '\t': os << "\\t"; break;
|
||||||
|
default:
|
||||||
|
if (0x0 <= *c && *c <= 0x1f)
|
||||||
|
{
|
||||||
|
os << "\\u" << std::hex << std::setw(4) <<
|
||||||
|
std::setfill('0') << static_cast<int>(*c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << *c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wsrep::reporter::write_log_msg(std::ostream& os,
|
wsrep::reporter::write_log_msg(std::ostream& os,
|
||||||
const log_msg& msg)
|
const log_msg& msg)
|
||||||
@ -149,14 +181,27 @@ wsrep::reporter::write_log_msg(std::ostream& os,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wsrep::reporter::write_log_msgs(std::ostream& os,
|
wsrep::reporter::write_event(std::ostream& os,
|
||||||
const std::string& label,
|
const log_msg& msg)
|
||||||
const std::deque<log_msg>& msgs)
|
{
|
||||||
|
os << "\t\t{\n";
|
||||||
|
os << "\t\t\t\"timestamp\": " << std::showpoint << std::setprecision(18)
|
||||||
|
<< msg.tstamp << ",\n";
|
||||||
|
os << "\t\t\t\"event\": " << msg.msg << "\n";
|
||||||
|
os << "\t\t}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wsrep::reporter::write_array(std::ostream& os,
|
||||||
|
const std::string& label,
|
||||||
|
const std::deque<log_msg>& msgs,
|
||||||
|
void (*element_writer)(std::ostream& os,
|
||||||
|
const log_msg& msg))
|
||||||
{
|
{
|
||||||
os << "\t\"" << label << "\": [\n";
|
os << "\t\"" << label << "\": [\n";
|
||||||
for (size_t i(0); i < msgs.size(); ++i)
|
for (size_t i(0); i < msgs.size(); ++i)
|
||||||
{
|
{
|
||||||
write_log_msg(os, msgs[i]);
|
element_writer(os, msgs[i]);
|
||||||
os << (i+1 < msgs.size() ? ",\n" : "\n");
|
os << (i+1 < msgs.size() ? ",\n" : "\n");
|
||||||
}
|
}
|
||||||
os << "\t],\n";
|
os << "\t],\n";
|
||||||
@ -223,8 +268,9 @@ wsrep::reporter::write_file(double const tstamp)
|
|||||||
os << "\t\"date\": \"" << date_str << "\",\n";
|
os << "\t\"date\": \"" << date_str << "\",\n";
|
||||||
os << "\t\"timestamp\": " << std::showpoint << std::setprecision(18)
|
os << "\t\"timestamp\": " << std::showpoint << std::setprecision(18)
|
||||||
<< tstamp << ",\n";
|
<< tstamp << ",\n";
|
||||||
write_log_msgs(os, "errors", err_msg_);
|
write_array(os, "errors", err_msg_, write_log_msg);
|
||||||
write_log_msgs(os, "warnings", warn_msg_);
|
write_array(os, "warnings", warn_msg_, write_log_msg);
|
||||||
|
write_array(os, "events", events_, write_event);
|
||||||
os << "\t\"status\": {\n";
|
os << "\t\"status\": {\n";
|
||||||
os << "\t\t\"state\": \"" << strings[state_].state << "\",\n";
|
os << "\t\t\"state\": \"" << strings[state_].state << "\",\n";
|
||||||
os << "\t\t\"comment\": \"" << strings[state_].comment << "\",\n";
|
os << "\t\t\"comment\": \"" << strings[state_].comment << "\",\n";
|
||||||
@ -282,6 +328,18 @@ wsrep::reporter::report_progress(const std::string& json)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wsrep::reporter::report_event(const std::string& json)
|
||||||
|
{
|
||||||
|
wsrep::unique_lock<wsrep::mutex> lock(mutex_);
|
||||||
|
if (events_.size() == max_msg_)
|
||||||
|
{
|
||||||
|
events_.pop_front();
|
||||||
|
}
|
||||||
|
events_.push_back({timestamp(), json});
|
||||||
|
write_file(timestamp());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wsrep::reporter::report_log_msg(log_level const lvl,
|
wsrep::reporter::report_log_msg(log_level const lvl,
|
||||||
const std::string& msg,
|
const std::string& msg,
|
||||||
@ -297,7 +355,9 @@ wsrep::reporter::report_log_msg(log_level const lvl,
|
|||||||
|
|
||||||
if (tstamp <= undefined) tstamp = timestamp();
|
if (tstamp <= undefined) tstamp = timestamp();
|
||||||
|
|
||||||
log_msg entry({tstamp, msg});
|
/* Log messages are not expected to be json formatted, so we escape
|
||||||
|
the message strings here to keep the report file well formatted. */
|
||||||
|
log_msg entry({tstamp, escape_json(msg)});
|
||||||
deque.push_back(entry);
|
deque.push_back(entry);
|
||||||
write_file(tstamp);
|
write_file(tstamp);
|
||||||
}
|
}
|
||||||
|
@ -320,8 +320,9 @@ print_logs(std::ostream& os, const logs& left, const logs& right)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// print two results against each other
|
// print two results against each other
|
||||||
|
template <typename Iteration>
|
||||||
static std::string
|
static std::string
|
||||||
print(const result& left, const result& right, size_t it)
|
print(const result& left, const result& right, Iteration it)
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
|
|
||||||
@ -360,6 +361,7 @@ static struct result
|
|||||||
const RES_INIT = { LOGS_INIT, LOGS_INIT,
|
const RES_INIT = { LOGS_INIT, LOGS_INIT,
|
||||||
{ "DISCONNECTED", "Disconnected", indefinite } };
|
{ "DISCONNECTED", "Disconnected", indefinite } };
|
||||||
|
|
||||||
|
template <typename Iteration>
|
||||||
static void
|
static void
|
||||||
test_log(const char* const fname,
|
test_log(const char* const fname,
|
||||||
wsrep::reporter& rep,
|
wsrep::reporter& rep,
|
||||||
@ -367,7 +369,7 @@ test_log(const char* const fname,
|
|||||||
wsrep::reporter::log_level const lvl,
|
wsrep::reporter::log_level const lvl,
|
||||||
double const tstamp,
|
double const tstamp,
|
||||||
const std::string& msg,
|
const std::string& msg,
|
||||||
size_t const iteration)
|
Iteration const iteration)
|
||||||
{
|
{
|
||||||
// this is implementaiton detail, if it changes in the code, it needs
|
// this is implementaiton detail, if it changes in the code, it needs
|
||||||
// to be changed here
|
// to be changed here
|
||||||
@ -389,11 +391,14 @@ test_log(const char* const fname,
|
|||||||
|
|
||||||
static size_t const MAX_MSG = 4;
|
static size_t const MAX_MSG = 4;
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(log_msg_test)
|
struct reporter_fixture
|
||||||
{
|
{
|
||||||
wsrep::default_mutex m;
|
wsrep::default_mutex mutex{};
|
||||||
wsrep::reporter rep(m, REPORT, MAX_MSG);
|
wsrep::reporter rep{mutex, REPORT, MAX_MSG};
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(log_msg_test, reporter_fixture)
|
||||||
|
{
|
||||||
auto value = read_file(REPORT);
|
auto value = read_file(REPORT);
|
||||||
BOOST_REQUIRE(value != nullptr);
|
BOOST_REQUIRE(value != nullptr);
|
||||||
|
|
||||||
@ -435,12 +440,10 @@ BOOST_AUTO_TEST_CASE(log_msg_test)
|
|||||||
::unlink(REPORT);
|
::unlink(REPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(state_test)
|
BOOST_FIXTURE_TEST_CASE(state_test, reporter_fixture)
|
||||||
{
|
{
|
||||||
using wsrep::server_state;
|
using wsrep::server_state;
|
||||||
|
|
||||||
wsrep::default_mutex m;
|
|
||||||
wsrep::reporter rep(m, REPORT, MAX_MSG);
|
|
||||||
double const err_tstamp(timestamp());
|
double const err_tstamp(timestamp());
|
||||||
std::string const err_msg("Error!");
|
std::string const err_msg("Error!");
|
||||||
|
|
||||||
@ -526,7 +529,7 @@ BOOST_AUTO_TEST_CASE(state_test)
|
|||||||
::unlink(REPORT);
|
::unlink(REPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(progress_test)
|
BOOST_FIXTURE_TEST_CASE(progress_test, reporter_fixture)
|
||||||
{
|
{
|
||||||
using wsrep::server_state;
|
using wsrep::server_state;
|
||||||
|
|
||||||
@ -634,3 +637,19 @@ BOOST_AUTO_TEST_CASE(progress_test)
|
|||||||
|
|
||||||
::unlink(REPORT);
|
::unlink(REPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(event_test, reporter_fixture)
|
||||||
|
{
|
||||||
|
rep.report_event("{\"msg\": \"message\"}");
|
||||||
|
auto value = read_file(REPORT);
|
||||||
|
BOOST_REQUIRE(value.at("events").is_array());
|
||||||
|
auto event_array = value.at("events").as_array();
|
||||||
|
BOOST_REQUIRE(event_array.size() == 1);
|
||||||
|
auto event = event_array[0];
|
||||||
|
BOOST_REQUIRE(event.is_object());
|
||||||
|
BOOST_REQUIRE(event.at("timestamp").is_double());
|
||||||
|
BOOST_REQUIRE(event.at("event").is_object());
|
||||||
|
BOOST_REQUIRE(event.at("event").at("msg").is_string());
|
||||||
|
BOOST_REQUIRE(event.at("event").at("msg").as_string() == "message");
|
||||||
|
::unlink(REPORT);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user