Removing g2logmessage pimpl

This commit is contained in:
KjellKod 2013-11-11 23:07:34 -07:00
parent 43806018aa
commit 11235acbc9
16 changed files with 268 additions and 183 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;
}; };

View File

@ -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);

View File

@ -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__

View File

@ -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

View File

@ -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

View File

@ -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
//
//

View File

@ -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;
}; //};
} //}

View File

@ -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: ");
} }

View File

@ -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__))

View File

@ -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);
} }

View File

@ -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);

View File

@ -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());
} }