mirror of
https://github.com/KjellKod/g3log.git
synced 2025-01-31 14:39:54 +01:00
Removing g2logmessage pimpl
This commit is contained in:
parent
43806018aa
commit
11235acbc9
@ -5,7 +5,6 @@
|
|||||||
* ============================================================================*/
|
* ============================================================================*/
|
||||||
|
|
||||||
#include "crashhandler.hpp"
|
#include "crashhandler.hpp"
|
||||||
#include "g2log.hpp"
|
|
||||||
#include "g2logmessage.hpp"
|
#include "g2logmessage.hpp"
|
||||||
#include "g2LogMessageBuilder.hpp"
|
#include "g2LogMessageBuilder.hpp"
|
||||||
|
|
||||||
@ -21,6 +20,7 @@
|
|||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Dump of stack,. then exit through g2log background worker
|
// Dump of stack,. then exit through g2log background worker
|
||||||
@ -32,15 +32,13 @@ namespace {
|
|||||||
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "Received fatal signal: " << g2::internal::signalName(signal_number);
|
oss << "Received fatal signal: " << g2::internal::signalName(signal_number);
|
||||||
oss << "(" << signal_number << ")" << std::endl;
|
oss << "(" << signal_number << ")\tPID: " << getpid() << std::endl;
|
||||||
oss << "\tPID: " << getpid() << std::endl;
|
|
||||||
oss << stackdump();
|
oss << stackdump();
|
||||||
|
|
||||||
{ // Local scope, trigger send
|
{ // Local scope, trigger send
|
||||||
std::ostringstream fatal_stream;
|
std::ostringstream fatal_stream;
|
||||||
fatal_stream << oss.str() << std::endl;
|
fatal_stream << oss.str() << std::endl;
|
||||||
fatal_stream << "\n***** SIGNAL " << signalName(signal_number) << "(" << signal_number << ")" << std::endl;
|
fatal_stream << "\n***** SIGNAL " << signalName(signal_number) << "(" << signal_number << ")" << std::endl;
|
||||||
|
|
||||||
g2::FatalMessageBuilder trigger(fatal_stream.str(), signal_number);
|
g2::FatalMessageBuilder trigger(fatal_stream.str(), signal_number);
|
||||||
} // message sent to g2LogWorker by FatalMessageBuilder
|
} // message sent to g2LogWorker by FatalMessageBuilder
|
||||||
// wait to die -- will be inside the FatalMessageBuilder
|
// wait to die -- will be inside the FatalMessageBuilder
|
||||||
@ -68,12 +66,13 @@ namespace g2 {
|
|||||||
// http://stackoverflow.com/questions/6878546/why-doesnt-parent-process-return-to-the-exact-location-after-handling-signal_number
|
// http://stackoverflow.com/questions/6878546/why-doesnt-parent-process-return-to-the-exact-location-after-handling-signal_number
|
||||||
namespace internal {
|
namespace internal {
|
||||||
std::string stackdump() {
|
std::string stackdump() {
|
||||||
std::ostringstream oss;
|
|
||||||
const size_t max_dump_size = 50;
|
const size_t max_dump_size = 50;
|
||||||
void* dump[max_dump_size];
|
void* dump[max_dump_size];
|
||||||
size_t size = backtrace(dump, max_dump_size);
|
size_t size = backtrace(dump, max_dump_size);
|
||||||
char** messages = backtrace_symbols(dump, size); // overwrite sigaction with caller's address
|
char** messages = backtrace_symbols(dump, size); // overwrite sigaction with caller's address
|
||||||
|
|
||||||
// dump stack: skip first frame, since that is here
|
// dump stack: skip first frame, since that is here
|
||||||
|
std::ostringstream oss;
|
||||||
for (size_t idx = 1; idx < size && messages != nullptr; ++idx) {
|
for (size_t idx = 1; idx < size && messages != nullptr; ++idx) {
|
||||||
char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
|
char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
|
||||||
// find parantheses and +address offset surrounding mangled name
|
// find parantheses and +address offset surrounding mangled name
|
||||||
@ -99,7 +98,7 @@ namespace g2 {
|
|||||||
char * real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
|
char * real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
|
||||||
// if demangling is successful, output the demangled function name
|
// if demangling is successful, output the demangled function name
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
oss << "\tstack dump [" << idx << "] " << messages[idx] << " : " << real_name << "+";
|
oss << "\n\tstack dump [" << idx << "] " << messages[idx] << " : " << real_name << "+";
|
||||||
oss << offset_begin << offset_end << std::endl;
|
oss << offset_begin << offset_end << std::endl;
|
||||||
}// otherwise, output the mangled function name
|
}// otherwise, output the mangled function name
|
||||||
else {
|
else {
|
||||||
|
@ -7,10 +7,9 @@
|
|||||||
|
|
||||||
//#include "g2log.hpp"
|
//#include "g2log.hpp"
|
||||||
#include "g2LogMessageBuilder.hpp"
|
#include "g2LogMessageBuilder.hpp"
|
||||||
#include "g2logmessageimpl.hpp"
|
|
||||||
#include "g2logmessage.hpp"
|
#include "g2logmessage.hpp"
|
||||||
|
#include "g2log.hpp"
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const int kMaxMessageSize = 2048;
|
const int kMaxMessageSize = 2048;
|
||||||
const std::string kTruncatedWarningText = "[...truncated...]";
|
const std::string kTruncatedWarningText = "[...truncated...]";
|
||||||
@ -20,26 +19,25 @@ namespace g2 {
|
|||||||
|
|
||||||
LogMessageBuilder::LogMessageBuilder(const std::string& file, const int line,
|
LogMessageBuilder::LogMessageBuilder(const std::string& file, const int line,
|
||||||
const std::string& function, const LEVELS& level)
|
const std::string& function, const LEVELS& level)
|
||||||
: _message(std::make_shared<LogMessageImpl>(file, line, function, level)) {
|
: _message(file, line, function, level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LogMessageBuilder::~LogMessageBuilder() {
|
LogMessageBuilder::~LogMessageBuilder() {
|
||||||
if (internal::wasFatal(_message->_level)) {
|
if (_message.wasFatal()) {
|
||||||
FatalMessageBuilder trigger({_message, SIGABRT});
|
FatalMessageBuilder trigger(_message, SIGABRT);
|
||||||
return; // FatalMessageBuilder will send to worker at scope exit
|
return; // FatalMessageBuilder will send to worker at scope exit
|
||||||
}
|
}
|
||||||
|
|
||||||
LogMessage log_entry(_message);
|
saveMessage(_message); // message saved to g2LogWorker
|
||||||
saveMessage(log_entry); // message saved to g2LogWorker
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LogMessageBuilder& LogMessageBuilder::setExpression(const std::string& boolean_expression) {
|
LogMessageBuilder& LogMessageBuilder::setExpression(const std::string& boolean_expression) {
|
||||||
_message->_expression = boolean_expression;
|
_message.setExpression(boolean_expression);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream& LogMessageBuilder::stream() {
|
std::ostringstream& LogMessageBuilder::stream() {
|
||||||
return _message->_stream;
|
return _message.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogMessageBuilder::messageSave(const char *printf_like_message, ...) {
|
void LogMessageBuilder::messageSave(const char *printf_like_message, ...) {
|
||||||
@ -65,11 +63,11 @@ namespace g2 {
|
|||||||
/// FatalMessageBuilder
|
/// FatalMessageBuilder
|
||||||
|
|
||||||
FatalMessageBuilder::FatalMessageBuilder(const std::string& exit_message, int signal_id)
|
FatalMessageBuilder::FatalMessageBuilder(const std::string& exit_message, int signal_id)
|
||||||
: _fatal_message(std::make_shared<LogMessageImpl>(exit_message)), _fatal_signal(signal_id)
|
: _fatal_message{exit_message}, _fatal_signal{signal_id}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
FatalMessageBuilder:: FatalMessageBuilder(const std::shared_ptr<LogMessageImpl>& details, int signal_id)
|
FatalMessageBuilder:: FatalMessageBuilder(const LogMessage& details, int signal_id)
|
||||||
: _fatal_message(details), _fatal_signal(signal_id)
|
: _fatal_message(details), _fatal_signal(signal_id)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -79,6 +77,7 @@ namespace g2 {
|
|||||||
// either we will stay here until the background worker has received the fatal
|
// either we will stay here until the background worker has received the fatal
|
||||||
// message, flushed the crash message to the sinks and exits with the same fatal signal
|
// message, flushed the crash message to the sinks and exits with the same fatal signal
|
||||||
//..... OR it's in unit-test mode then we throw a std::runtime_error (and never hit sleep)
|
//..... OR it's in unit-test mode then we throw a std::runtime_error (and never hit sleep)
|
||||||
|
|
||||||
FatalMessage msg(_fatal_message, _fatal_signal);
|
FatalMessage msg(_fatal_message, _fatal_signal);
|
||||||
fatalCall(msg);
|
fatalCall(msg);
|
||||||
|
|
||||||
|
@ -8,23 +8,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <memory>
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include "g2loglevels.hpp"
|
|
||||||
|
|
||||||
|
#include "g2loglevels.hpp"
|
||||||
|
#include "g2logmessage.hpp"
|
||||||
|
|
||||||
namespace g2 {
|
namespace g2 {
|
||||||
|
|
||||||
struct LogMessageImpl;
|
|
||||||
|
|
||||||
// At RAII scope end this struct will trigger a FatalMessage sending
|
// At RAII scope end this struct will trigger a FatalMessage sending
|
||||||
struct FatalMessageBuilder {
|
struct FatalMessageBuilder {
|
||||||
//explicit FatalMessageBuilder(const FatalMessage& exit_message);
|
//explicit FatalMessageBuilder(const FatalMessage& exit_message);
|
||||||
FatalMessageBuilder(const std::string& exit_message, int fatal_signal);
|
FatalMessageBuilder(const std::string& exit_message, int fatal_signal);
|
||||||
FatalMessageBuilder(const std::shared_ptr<LogMessageImpl>& details, int signal_id);
|
FatalMessageBuilder(const LogMessage& details, int signal_id);
|
||||||
virtual ~FatalMessageBuilder();
|
virtual ~FatalMessageBuilder();
|
||||||
|
|
||||||
std::shared_ptr<LogMessageImpl> _fatal_message;
|
LogMessage _fatal_message;
|
||||||
int _fatal_signal;
|
int _fatal_signal;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,6 +43,6 @@ namespace g2 {
|
|||||||
__attribute__((format(printf, 2, 3))); // ref: http://www.codemaestro.com/reviews/18
|
__attribute__((format(printf, 2, 3))); // ref: http://www.codemaestro.com/reviews/18
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<LogMessageImpl> _message;
|
LogMessage _message;
|
||||||
};
|
};
|
||||||
} // g2
|
} // g2
|
@ -35,7 +35,7 @@ FileSink::FileSink(const std::string& log_prefix, const std::string& log_directo
|
|||||||
addLogFileHeader();
|
addLogFileHeader();
|
||||||
}
|
}
|
||||||
FileSink::~FileSink() {
|
FileSink::~FileSink() {
|
||||||
std::string exit_msg{"\n\t\tg2log g2FileSink shutdown at: "};
|
std::string exit_msg{"\ng2log g2FileSink shutdown at: "};
|
||||||
exit_msg.append(localtime_formatted(systemtime_now(), internal::time_formatted));
|
exit_msg.append(localtime_formatted(systemtime_now(), internal::time_formatted));
|
||||||
filestream() << exit_msg << std::flush;
|
filestream() << exit_msg << std::flush;
|
||||||
|
|
||||||
|
@ -36,14 +36,25 @@ namespace g2 {
|
|||||||
template<typename Moveable>
|
template<typename Moveable>
|
||||||
struct PretendToBeCopyable
|
struct PretendToBeCopyable
|
||||||
{
|
{
|
||||||
explicit PretendToBeCopyable(Moveable&& m) : move_only_(std::move(m)) {}
|
explicit PretendToBeCopyable(Moveable&& m) : _move_only(std::move(m)) {}
|
||||||
|
|
||||||
template<typename T> // universal copy constructor
|
PretendToBeCopyable(PretendToBeCopyable const& t): _move_only(std::move(t._move_only)){}
|
||||||
PretendToBeCopyable(T&& t): move_only_(std::move(t.move_only_)){}
|
PretendToBeCopyable(PretendToBeCopyable&& t): _move_only(std::move(t._move_only)){}
|
||||||
|
|
||||||
void operator()() { move_only_(); } // execute
|
PretendToBeCopyable& operator=(PretendToBeCopyable const& other) {
|
||||||
|
_move_only=std::move(other._move_only);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PretendToBeCopyable& operator=(PretendToBeCopyable&& other) {
|
||||||
|
_move_only=std::move(other._move_only);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void operator()() { _move_only(); } // execute
|
||||||
private:
|
private:
|
||||||
mutable Moveable move_only_;
|
mutable Moveable _move_only;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,19 +21,20 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "std2_make_unique.hpp"
|
||||||
#include "g2logworker.hpp"
|
#include "g2logworker.hpp"
|
||||||
#include "crashhandler.hpp"
|
#include "crashhandler.hpp"
|
||||||
#include "g2loglevels.hpp"
|
#include "g2loglevels.hpp"
|
||||||
#include "g2logmessageimpl.hpp"
|
#include "g2logmessage.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::once_flag g_initialize_flag;
|
std::once_flag g_initialize_flag;
|
||||||
g2LogWorker* g_logger_instance = nullptr; // instantiated and OWNED somewhere else (main)
|
g2LogWorker* g_logger_instance = nullptr; // instantiated and OWNED somewhere else (main)
|
||||||
std::mutex g_logging_init_mutex;
|
std::mutex g_logging_init_mutex;
|
||||||
|
|
||||||
std::shared_ptr<g2::LogMessageImpl> g_first_unintialized_msg = {nullptr};
|
std::unique_ptr<g2::LogMessage> g_first_unintialized_msg = {nullptr};
|
||||||
bool g_uninitialized_call = false;
|
|
||||||
std::once_flag g_set_first_uninitialized_flag;
|
std::once_flag g_set_first_uninitialized_flag;
|
||||||
std::once_flag g_save_first_unintialized_flag;
|
std::once_flag g_save_first_unintialized_flag;
|
||||||
|
|
||||||
@ -92,13 +93,13 @@ namespace g2 {
|
|||||||
* The first initialized log entry will also save the first uninitialized log message, if any
|
* The first initialized log entry will also save the first uninitialized log message, if any
|
||||||
* @param log_entry to save to logger
|
* @param log_entry to save to logger
|
||||||
*/
|
*/
|
||||||
void saveMessage(const g2::LogMessage& log_entry) {
|
void saveMessage(const g2::LogMessage& incoming) {
|
||||||
// Uninitialized messages are ignored but does not CHECK/crash the logger
|
// Uninitialized messages are ignored but does not CHECK/crash the logger
|
||||||
if (!internal::isLoggingInitialized()) {
|
if (!internal::isLoggingInitialized()) {
|
||||||
|
LogMessage log_entry{incoming};
|
||||||
std::call_once(g_set_first_uninitialized_flag, [&] {
|
std::call_once(g_set_first_uninitialized_flag, [&] {
|
||||||
g_first_unintialized_msg = log_entry._pimpl;
|
g_first_unintialized_msg = std2::make_unique<LogMessage>(log_entry);
|
||||||
g_uninitialized_call = true;
|
//g_uninitialized_call = true;
|
||||||
std::string err = {"LOGGER NOT INITIALIZED:\n\t\t"};
|
std::string err = {"LOGGER NOT INITIALIZED:\n\t\t"};
|
||||||
err.append(log_entry.message());
|
err.append(log_entry.message());
|
||||||
auto& stream = log_entry.stream();
|
auto& stream = log_entry.stream();
|
||||||
@ -112,14 +113,14 @@ namespace g2 {
|
|||||||
// logger is initialized
|
// logger is initialized
|
||||||
// Save the first uninitialized message, if any
|
// Save the first uninitialized message, if any
|
||||||
std::call_once(g_save_first_unintialized_flag, [] {
|
std::call_once(g_save_first_unintialized_flag, [] {
|
||||||
if (g_uninitialized_call) {
|
if (g_first_unintialized_msg) {
|
||||||
LogMessage error_msg{g_first_unintialized_msg};
|
LogMessage error_msg{*(g_first_unintialized_msg.get())};
|
||||||
g_logger_instance->save(error_msg);
|
g_logger_instance->save(error_msg);
|
||||||
g_first_unintialized_msg.reset();
|
g_first_unintialized_msg.reset();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
g_logger_instance->save(log_entry);
|
g_logger_instance->save(incoming);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -128,14 +129,14 @@ namespace g2 {
|
|||||||
* will sleep forever (i.e. until the background thread catches up, saves the fatal
|
* will sleep forever (i.e. until the background thread catches up, saves the fatal
|
||||||
* message and kills the software with the fatal signal.
|
* message and kills the software with the fatal signal.
|
||||||
*/
|
*/
|
||||||
void fatalCallToLogger(const FatalMessage& message) {
|
void fatalCallToLogger(const FatalMessage& message) {
|
||||||
if (!isLoggingInitialized()) {
|
if (!isLoggingInitialized()) {
|
||||||
std::ostringstream error;
|
std::ostringstream error;
|
||||||
error << "FATAL CALL but logger is NOT initialized\n"
|
error << "FATAL CALL but logger is NOT initialized\n"
|
||||||
<< "SIGNAL: " << g2::internal::signalName(message.signal_id_)
|
<< "SIGNAL: " << g2::internal::signalName(message._signal_id)
|
||||||
<< "\nMessage: \n" << message.toString() << std::flush;
|
<< "\nMessage: \n" << message.toString() << std::flush;
|
||||||
std::cerr << error << std::flush;
|
std::cerr << error << std::flush;
|
||||||
internal::exitWithDefaultSignalHandler(message.signal_id_);
|
internal::exitWithDefaultSignalHandler(message._signal_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_logger_instance->fatal(message);
|
g_logger_instance->fatal(message);
|
||||||
|
@ -21,10 +21,12 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "g2loglevels.hpp"
|
#include "g2loglevels.hpp"
|
||||||
#include "g2LogMessageBuilder.hpp"
|
#include "g2LogMessageBuilder.hpp"
|
||||||
|
|
||||||
|
|
||||||
class g2LogWorker;
|
class g2LogWorker;
|
||||||
#if !(defined(__PRETTY_FUNCTION__))
|
#if !(defined(__PRETTY_FUNCTION__))
|
||||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||||
|
@ -10,60 +10,67 @@
|
|||||||
* ********************************************* */
|
* ********************************************* */
|
||||||
|
|
||||||
#include "g2logmessage.hpp"
|
#include "g2logmessage.hpp"
|
||||||
#include "g2logmessageimpl.hpp"
|
|
||||||
#include "g2time.hpp"
|
|
||||||
#include "crashhandler.hpp"
|
#include "crashhandler.hpp"
|
||||||
#include <stdexcept> // exceptions
|
#include "g2time.hpp"
|
||||||
#include "g2log.hpp"
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::once_flag g_start_time_flag;
|
||||||
|
g2::steady_time_point g_start_time;
|
||||||
|
|
||||||
|
long microsecondsCounter() {
|
||||||
|
std::call_once(g_start_time_flag, []() { g_start_time = std::chrono::steady_clock::now(); });
|
||||||
|
g2::steady_time_point now = std::chrono::steady_clock::now();
|
||||||
|
return std::chrono::duration_cast<std::chrono::microseconds>(now - g_start_time).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string splitFileName(const std::string& str) {
|
||||||
|
size_t found;
|
||||||
|
found = str.find_last_of("(/\\");
|
||||||
|
return str.substr(found + 1);
|
||||||
|
}
|
||||||
|
} // anonymous
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace g2 {
|
namespace g2 {
|
||||||
|
|
||||||
|
|
||||||
std::string LogMessage::line() const {
|
std::string LogMessage::line() const {
|
||||||
return std::to_string(_pimpl->_line);
|
return std::to_string(_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string LogMessage::file() const {
|
std::string LogMessage::file() const {
|
||||||
return _pimpl->_file;
|
return _file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string LogMessage::function() const {
|
std::string LogMessage::function() const {
|
||||||
return _pimpl->_function;
|
return _function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string LogMessage::level() const {
|
std::string LogMessage::level() const {
|
||||||
return _pimpl->_level.text;
|
return _level.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string LogMessage::timestamp(const std::string & time_look) const {
|
std::string LogMessage::timestamp(const std::string & time_look) const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << localtime_formatted(_pimpl->_timestamp, time_look);
|
oss << localtime_formatted(_timestamp, time_look);
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string LogMessage::microseconds() const {
|
std::string LogMessage::microseconds() const {
|
||||||
return std::to_string(_pimpl->_microseconds);
|
return std::to_string(_microseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string LogMessage::message() const {
|
std::string LogMessage::message() const {
|
||||||
return _pimpl->_stream.str();
|
return _stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string LogMessage::expression() const {
|
std::string LogMessage::expression() const {
|
||||||
return _pimpl->_expression;
|
return _expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LogMessage::wasFatal() const {
|
bool LogMessage::wasFatal() const {
|
||||||
return internal::wasFatal(_pimpl->_level);
|
return internal::wasFatal(_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LogMessage::toString() const {
|
std::string LogMessage::toString() const {
|
||||||
@ -80,7 +87,7 @@ namespace g2 {
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (internal::FATAL_SIGNAL.value == _pimpl->_level.value) {
|
if (internal::FATAL_SIGNAL.value == _level.value) {
|
||||||
oss.str(""); // clear any previous text and formatting
|
oss.str(""); // clear any previous text and formatting
|
||||||
oss << "\n" << timestamp() << "." << microseconds();
|
oss << "\n" << timestamp() << "." << microseconds();
|
||||||
oss << "\n\n***** FATAL SIGNAL RECEIVED ******* " << std::endl;
|
oss << "\n\n***** FATAL SIGNAL RECEIVED ******* " << std::endl;
|
||||||
@ -90,15 +97,15 @@ namespace g2 {
|
|||||||
|
|
||||||
|
|
||||||
// Not crash scenario but LOG or CONTRACT
|
// Not crash scenario but LOG or CONTRACT
|
||||||
auto level_value = _pimpl->_level.value;
|
auto level_value = _level.value;
|
||||||
if (FATAL.value == level_value) {
|
if (FATAL.value == level_value) {
|
||||||
oss << "\n\t*******\tEXIT trigger caused by LOG(FATAL) entry: \n\t";
|
oss << "\n\t*******\tEXIT trigger caused by LOG(FATAL) entry: \n\t";
|
||||||
oss << '"' << message() << '"';
|
oss << '"' << message() << '"';
|
||||||
oss << "\n*******\tSTACKDUMP *******\n" << internal::stackdump();
|
oss << "\n*******\tSTACKDUMP *******\n" << internal::stackdump();
|
||||||
} else if (internal::CONTRACT.value == level_value) {
|
} else if (internal::CONTRACT.value == level_value) {
|
||||||
oss << "\n\t *******\tEXIT trigger caused by broken Contract: CHECK(" << _pimpl->_expression << ")\n\t";
|
oss << "\n\t *******\tEXIT trigger caused by broken Contract: CHECK(" << _expression << ")\n\t";
|
||||||
oss << '"' << message() << '"';
|
oss << '"' << message() << '"';
|
||||||
oss << "\n*******\tSTACKDUMP *******\n" << internal::stackdump()<< '"';
|
oss << "\n*******\tSTACKDUMP *******\n" << internal::stackdump() << '"';
|
||||||
} else {
|
} else {
|
||||||
oss << "\n\t*******\tUNKNOWN Log Message Type\n" << '"' << message() << '"';
|
oss << "\n\t*******\tUNKNOWN Log Message Type\n" << '"' << message() << '"';
|
||||||
}
|
}
|
||||||
@ -108,21 +115,69 @@ namespace g2 {
|
|||||||
|
|
||||||
|
|
||||||
// is strictly not speaking const
|
// is strictly not speaking const
|
||||||
std::ostringstream& LogMessage::stream() const{
|
void LogMessage::setExpression(const std::string expression) {
|
||||||
return _pimpl->_stream;
|
_expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream& LogMessage::stream(){
|
||||||
|
return _stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogMessage::LogMessage(const std::string &file, const int line,
|
||||||
LogMessage::LogMessage(const std::shared_ptr<LogMessageImpl>& details)
|
const std::string& function, const LEVELS& level)
|
||||||
: _pimpl(details) { }
|
: _timestamp(g2::systemtime_now())
|
||||||
|
, _microseconds(microsecondsCounter())
|
||||||
|
, _file(splitFileName(file)), _line(line), _function(function), _level(level) { }
|
||||||
|
|
||||||
|
|
||||||
FatalMessage::FatalMessage(const std::shared_ptr<LogMessageImpl>& details, int signal_id)
|
LogMessage::LogMessage(const std::string& fatalOsSignalCrashMessage)
|
||||||
: LogMessage(details), signal_id_(signal_id) { }
|
: LogMessage({""}, 0, {""}, internal::FATAL_SIGNAL) {
|
||||||
|
_stream << fatalOsSignalCrashMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogMessage::LogMessage(const LogMessage& other)
|
||||||
|
: _timestamp(other._timestamp)
|
||||||
|
, _microseconds(other._microseconds)
|
||||||
|
, _file(other._file)
|
||||||
|
, _line(other._line)
|
||||||
|
, _function(other._function)
|
||||||
|
, _level(other._level)
|
||||||
|
, _expression(other._expression)
|
||||||
|
{
|
||||||
|
_stream << other._stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogMessage::LogMessage(LogMessage&& msg)
|
||||||
|
// : _timestamp(other._timestamp)
|
||||||
|
// , _microseconds(other._microseconds)
|
||||||
|
// , _file(std::move(other._file))
|
||||||
|
// , _line(other._line)
|
||||||
|
// , _function(std::move(other._function))
|
||||||
|
// , _level(other._level)
|
||||||
|
// , _expression(other._expression)
|
||||||
|
// , _stream(std::move(other._stream))
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FatalMessage::FatalMessage(const LogMessage& details, int signal_id)
|
||||||
|
: LogMessage(details), _signal_id(signal_id) { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FatalMessage::FatalMessage(const FatalMessage& other)
|
||||||
|
: LogMessage(other), _signal_id(other._signal_id) {}
|
||||||
|
|
||||||
|
|
||||||
LogMessage FatalMessage::copyToLogMessage() const {
|
LogMessage FatalMessage::copyToLogMessage() const {
|
||||||
return LogMessage(_pimpl);
|
return LogMessage(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FatalMessage::signal() const{
|
||||||
|
return internal::signalName(_signal_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // g2
|
} // g2
|
||||||
|
@ -14,20 +14,14 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <chrono>
|
||||||
#include <cstdarg>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "g2log.hpp"
|
|
||||||
#include "g2loglevels.hpp"
|
#include "g2loglevels.hpp"
|
||||||
#include "g2time.hpp"
|
#include "g2time.hpp"
|
||||||
//#include "g2logmessageimpl.hpp"
|
|
||||||
|
|
||||||
namespace g2 {
|
namespace g2 {
|
||||||
struct LogMessageImpl;
|
|
||||||
|
|
||||||
struct LogMessage {
|
struct LogMessage {
|
||||||
mutable std::shared_ptr<LogMessageImpl> _pimpl;
|
|
||||||
std::string file() const;
|
std::string file() const;
|
||||||
std::string line() const;
|
std::string line() const;
|
||||||
std::string function() const;
|
std::string function() const;
|
||||||
@ -44,20 +38,43 @@ namespace g2 {
|
|||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
|
|
||||||
std::ostringstream& stream() const;
|
std::ostringstream& stream();
|
||||||
explicit LogMessage(const std::shared_ptr<LogMessageImpl>& details);
|
void setExpression(const std::string expression);
|
||||||
|
|
||||||
|
LogMessage(const std::string &file, const int line, const std::string& function, const LEVELS& level);
|
||||||
|
explicit LogMessage(const std::string& fatalOsSignalCrashMessage);
|
||||||
|
|
||||||
|
LogMessage(const LogMessage&);
|
||||||
|
//LogMessage(LogMessage&&);
|
||||||
|
|
||||||
~LogMessage() = default;
|
~LogMessage() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const std::time_t _timestamp;
|
||||||
|
const long _microseconds;
|
||||||
|
const std::string _file;
|
||||||
|
const int _line;
|
||||||
|
const std::string _function;
|
||||||
|
const LEVELS _level;
|
||||||
|
|
||||||
|
std::string _expression; // only with content for CHECK(...) calls
|
||||||
|
mutable std::ostringstream _stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Trigger for flushing the message queue and exiting the application
|
/** Trigger for flushing the message queue and exiting the application
|
||||||
* A thread that causes a FatalMessage will sleep forever until the
|
* A thread that causes a FatalMessage will sleep forever until the
|
||||||
* application has exited (after message flush) */
|
* application has exited (after message flush) */
|
||||||
struct FatalMessage : public LogMessage {
|
struct FatalMessage : public LogMessage {
|
||||||
FatalMessage(const std::shared_ptr<LogMessageImpl>& details, int signal_id);
|
FatalMessage(const LogMessage& details, int signal_id);
|
||||||
|
FatalMessage(const FatalMessage&);
|
||||||
~FatalMessage() = default;
|
~FatalMessage() = default;
|
||||||
LogMessage copyToLogMessage() const;
|
|
||||||
|
|
||||||
int signal_id_;
|
LogMessage copyToLogMessage() const;
|
||||||
|
std::string signal() const;
|
||||||
|
|
||||||
|
const int _signal_id;
|
||||||
};
|
};
|
||||||
} // g2
|
} // g2
|
||||||
|
@ -1,39 +1,39 @@
|
|||||||
|
//
|
||||||
|
//
|
||||||
#include <g2logmessageimpl.hpp>
|
//#include <g2logmessageimpl.hpp>
|
||||||
#include <g2time.hpp>
|
//#include <g2time.hpp>
|
||||||
#include <mutex>
|
//#include <mutex>
|
||||||
|
//
|
||||||
namespace {
|
//namespace {
|
||||||
std::once_flag g_start_time_flag;
|
// std::once_flag g_start_time_flag;
|
||||||
g2::steady_time_point g_start_time;
|
// g2::steady_time_point g_start_time;
|
||||||
|
//
|
||||||
long microsecondsCounter() {
|
// long microsecondsCounter() {
|
||||||
std::call_once(g_start_time_flag, []() { g_start_time = std::chrono::steady_clock::now(); });
|
// std::call_once(g_start_time_flag, []() { g_start_time = std::chrono::steady_clock::now(); });
|
||||||
g2::steady_time_point now = std::chrono::steady_clock::now();
|
// g2::steady_time_point now = std::chrono::steady_clock::now();
|
||||||
return std::chrono::duration_cast<std::chrono::microseconds>(now - g_start_time).count();
|
// return std::chrono::duration_cast<std::chrono::microseconds>(now - g_start_time).count();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
std::string splitFileName(const std::string& str) {
|
// std::string splitFileName(const std::string& str) {
|
||||||
size_t found;
|
// size_t found;
|
||||||
found = str.find_last_of("(/\\");
|
// found = str.find_last_of("(/\\");
|
||||||
return str.substr(found + 1);
|
// return str.substr(found + 1);
|
||||||
}
|
// }
|
||||||
} // anonymous
|
//} // anonymous
|
||||||
|
//
|
||||||
|
//
|
||||||
namespace g2 {
|
//namespace g2 {
|
||||||
LogMessageImpl::LogMessageImpl(const std::string &file, const int line,
|
// LogMessageImpl::LogMessageImpl(const std::string &file, const int line,
|
||||||
const std::string& function, const LEVELS& level)
|
// const std::string& function, const LEVELS& level)
|
||||||
: _timestamp(g2::systemtime_now())
|
// : _timestamp(g2::systemtime_now())
|
||||||
, _microseconds(microsecondsCounter())
|
// , _microseconds(microsecondsCounter())
|
||||||
, _file(splitFileName(file)), _line(line), _function(function), _level(level) { }
|
// , _file(splitFileName(file)), _line(line), _function(function), _level(level) { }
|
||||||
|
//
|
||||||
|
//
|
||||||
LogMessageImpl::LogMessageImpl(const std::string& fatalOsSignalCrashMessage)
|
// LogMessageImpl::LogMessageImpl(const std::string& fatalOsSignalCrashMessage)
|
||||||
: LogMessageImpl({""}, 0, {""}, internal::FATAL_SIGNAL) {
|
// : LogMessageImpl({""}, 0, {""}, internal::FATAL_SIGNAL) {
|
||||||
_stream << fatalOsSignalCrashMessage;
|
// _stream << fatalOsSignalCrashMessage;
|
||||||
}
|
// }
|
||||||
} // g2
|
//} // g2
|
||||||
|
//
|
||||||
|
//
|
||||||
|
@ -1,40 +1,40 @@
|
|||||||
// -*- C++ -*-
|
//// -*- C++ -*-
|
||||||
/*
|
///*
|
||||||
* File: g2logmessageimpl.hpp
|
// * File: g2logmessageimpl.hpp
|
||||||
* Author: kjell
|
// * Author: kjell
|
||||||
*
|
// *
|
||||||
* Created on October 27, 2013, 9:14 PM
|
// * Created on October 27, 2013, 9:14 PM
|
||||||
*/
|
// */
|
||||||
|
//
|
||||||
#pragma once
|
//#pragma once
|
||||||
|
//
|
||||||
|
//
|
||||||
#include <string>
|
//#include <string>
|
||||||
#include "g2loglevels.hpp"
|
//#include "g2loglevels.hpp"
|
||||||
#include <ctime>
|
//#include <ctime>
|
||||||
#include <sstream>
|
//#include <sstream>
|
||||||
|
//
|
||||||
namespace g2 {
|
//namespace g2 {
|
||||||
struct LogMessageImpl {
|
//struct LogMessageImpl {
|
||||||
|
//
|
||||||
// LOG message constructor
|
// // LOG message constructor
|
||||||
LogMessageImpl(const std::string &file, const int line,
|
// LogMessageImpl(const std::string &file, const int line,
|
||||||
const std::string& function, const LEVELS& level);
|
// const std::string& function, const LEVELS& level);
|
||||||
|
//
|
||||||
// Fatal OS-Signal constructor
|
// // Fatal OS-Signal constructor
|
||||||
explicit LogMessageImpl(const std::string& fatalOsSignalCrashMessage);
|
// explicit LogMessageImpl(const std::string& fatalOsSignalCrashMessage);
|
||||||
|
//
|
||||||
LogMessageImpl(const LogMessageImpl& copy) = default;
|
// LogMessageImpl(const LogMessageImpl& copy) = default;
|
||||||
~LogMessageImpl() = default;
|
// ~LogMessageImpl() = default;
|
||||||
|
//
|
||||||
const std::time_t _timestamp;
|
// const std::time_t _timestamp;
|
||||||
const long _microseconds;
|
// const long _microseconds;
|
||||||
const std::string _file;
|
// const std::string _file;
|
||||||
const int _line;
|
// const int _line;
|
||||||
const std::string _function;
|
// const std::string _function;
|
||||||
const LEVELS _level;
|
// const LEVELS _level;
|
||||||
|
//
|
||||||
std::string _expression; // only with content for CHECK(...) calls
|
// std::string _expression; // only with content for CHECK(...) calls
|
||||||
std::ostringstream _stream;
|
// std::ostringstream _stream;
|
||||||
};
|
//};
|
||||||
}
|
//}
|
||||||
|
@ -47,12 +47,17 @@ struct g2LogWorkerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void bgFatal(const FatalMessage& msg) {
|
void bgFatal(const FatalMessage& msg) {
|
||||||
auto fatal_message = msg;
|
FatalMessage fatal_message{msg};
|
||||||
fatal_message.stream() << "\nExiting after fatal event. Log flushed sucessfully to disk.\n";
|
fatal_message.stream() << "\nExiting after fatal event (" << fatal_message.level()
|
||||||
bgSave(fatal_message.copyToLogMessage());
|
<<"). Exiting with signal: " << fatal_message.signal()
|
||||||
|
<< "\nLog flushed sucessfully to disk\n\n";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::cerr << fatal_message.message() << std::flush;
|
||||||
_sinks.clear(); // flush all queues
|
_sinks.clear(); // flush all queues
|
||||||
exitWithDefaultSignalHandler(fatal_message.signal_id_);
|
|
||||||
|
exitWithDefaultSignalHandler(fatal_message._signal_id);
|
||||||
// should never reach this point
|
// should never reach this point
|
||||||
perror("g2log exited after receiving FATAL trigger. Flush message status: ");
|
perror("g2log exited after receiving FATAL trigger. Flush message status: ");
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "g2log.hpp"
|
#include "g2log.hpp"
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <iostream>
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "g2sinkwrapper.h"
|
#include "g2sinkwrapper.h"
|
||||||
#include "g2sinkhandle.h"
|
#include "g2sinkhandle.h"
|
||||||
#include "g2logmessage.hpp"
|
#include "g2logmessage.hpp"
|
||||||
#include "g2logmessageimpl.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -51,7 +50,7 @@ namespace g2 {
|
|||||||
|
|
||||||
void bgSave(LogEntry msg) {
|
void bgSave(LogEntry msg) {
|
||||||
for (auto& sink : _container) {
|
for (auto& sink : _container) {
|
||||||
g2::LogMessage message(std::make_shared<g2::LogMessageImpl>("test", 0, "test", DEBUG));
|
g2::LogMessage message("test", 0, "test", DEBUG);
|
||||||
message.stream() << msg;
|
message.stream() << msg;
|
||||||
sink->send(message);
|
sink->send(message);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#include "testing_helpers.h"
|
#include "testing_helpers.h"
|
||||||
#include "g2logmessageimpl.hpp"
|
|
||||||
#include "g2logmessage.hpp"
|
#include "g2logmessage.hpp"
|
||||||
#include "g2logworker.hpp"
|
#include "g2logworker.hpp"
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ TEST(Sink, OneSink) {
|
|||||||
EXPECT_FALSE(flag->load());
|
EXPECT_FALSE(flag->load());
|
||||||
EXPECT_TRUE(0 == count->load());
|
EXPECT_TRUE(0 == count->load());
|
||||||
//worker->save("this message should trigger an atomic increment at the sink");
|
//worker->save("this message should trigger an atomic increment at the sink");
|
||||||
g2::LogMessage message(std::make_shared<g2::LogMessageImpl>("test", 0, "test", DEBUG));
|
g2::LogMessage message("test", 0, "test", DEBUG);
|
||||||
message.stream() << "this message should trigger an atomic increment at the sink";
|
message.stream() << "this message should trigger an atomic increment at the sink";
|
||||||
worker->save(message);
|
worker->save(message);
|
||||||
}
|
}
|
||||||
@ -59,7 +58,7 @@ TEST(ConceptSink, OneHundredSinks) {
|
|||||||
worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
|
worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
|
||||||
}
|
}
|
||||||
LOG(DEBUG) << "start message";
|
LOG(DEBUG) << "start message";
|
||||||
g2::LogMessage message(std::make_shared<g2::LogMessageImpl>("test", 0, "test", DEBUG));
|
g2::LogMessage message("test", 0, "test", DEBUG);
|
||||||
auto& stream = message.stream();
|
auto& stream = message.stream();
|
||||||
stream << "Hello to 100 receivers :)";
|
stream << "Hello to 100 receivers :)";
|
||||||
worker->save(message);
|
worker->save(message);
|
||||||
|
@ -34,7 +34,7 @@ namespace testing_helpers {
|
|||||||
|
|
||||||
void mockFatalCall(const g2::FatalMessage& fatal_message) {
|
void mockFatalCall(const g2::FatalMessage& fatal_message) {
|
||||||
g_mockFatal_message = fatal_message.toString();
|
g_mockFatal_message = fatal_message.toString();
|
||||||
g_mockFatal_signal = fatal_message.signal_id_;
|
g_mockFatal_signal = fatal_message._signal_id;
|
||||||
g_mockFatalWasCalled = true;
|
g_mockFatalWasCalled = true;
|
||||||
g2::internal::saveMessage(fatal_message.copyToLogMessage());
|
g2::internal::saveMessage(fatal_message.copyToLogMessage());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user