Breaking change but a good change: Cleared up the API for Creating log worker and Adding sinks

This commit is contained in:
Kjell Hedstrom 2015-08-19 10:08:41 -06:00
parent bc4459d779
commit 1803498e89
13 changed files with 108 additions and 63 deletions

View File

@ -89,7 +89,7 @@ Example usage where a custom sink is added. A function is called though the sink
int main(int argc, char**argv) {
using namespace g3;
std::unique_ptr<LogWorker> logworker{ LogWorker::createWithNoSink() };
std::unique_ptr<LogWorker> logworker{ LogWorker::createLogWorker() };
auto sinkHandle = logworker->addSink(std2::make_unique<CustomSink>(),
&CustomSink::ReceiveLogMessage);
@ -135,7 +135,8 @@ Example usage where a the default file logger is used **and** a custom sink is a
int main(int argc, char**argv) {
using namespace g3;
auto defaultHandler = LogWorker::createWithDefaultLogger(argv[0],
auto worker = LogWorker::createLogWorker();
auto defaultHandler = worker->addDefaultLogger(argv[0],
path_to_log_file);
// logger is initialized
@ -143,7 +144,7 @@ int main(int argc, char**argv) {
LOG(DEBUG) << "Make log call, then add another sink";
defaultHandler.worker->addSink(std2::make_unique<CustomSink>(),
worker->addSink(std2::make_unique<CustomSink>(),
&CustomSink::ReceiveLogMessage);
...

View File

@ -35,9 +35,10 @@ int main(int argc, char **argv)
double pi_d = 3.1415926535897932384626433832795;
float pi_f = 3.1415926535897932384626433832795f;
auto logger_n_handle = g3::LogWorker::createWithDefaultLogger(argv[0], path_to_log_file);
g3::initializeLogging(logger_n_handle.worker.get());
std::future<std::string> log_file_name = logger_n_handle.sink->call(&g3::FileSink::fileName);
auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger(argv[0], path_to_log_file);
g3::initializeLogging(worker.get());
std::future<std::string> log_file_name = handle->call(&g3::FileSink::fileName);
std::cout << "* This is an example of g3log. It WILL exit by a failed CHECK(...)" << std::endl;
std::cout << "* that acts as a FATAL trigger. Please see the generated log and " << std::endl;
std::cout << "* compare to the code at:\n* \t g3log/test_example/main_contract.cpp" << std::endl;

View File

@ -235,6 +235,10 @@ namespace
} // namespace
void breakHere() {
std::ostringstream oss;
oss << __FUNCTION__ << " was reached" << std::endl;
std::cout << oss.str() << std::endl;
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
__debugbreak();
#endif
@ -242,11 +246,11 @@ void breakHere() {
int main(int argc, char **argv)
{
auto logger_n_handle = g3::LogWorker::createWithDefaultLogger(argv[0], path_to_log_file);
g3::initializeLogging(logger_n_handle.worker.get());
g3::setFatalPreLoggingHook(&breakHere);
std::future<std::string> log_file_name = logger_n_handle.sink->call(&g3::FileSink::fileName);
auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger(argv[0], path_to_log_file);
g3::initializeLogging(worker.get());
std::future<std::string> log_file_name = handle->call(&g3::FileSink::fileName);
std::cout << "**** G3LOG FATAL EXAMPLE ***\n\n"
<< "Choose your type of fatal exit, then "
<< " read the generated log and backtrace.\n"

View File

@ -55,7 +55,8 @@ int main(int argc, char **argv)
using namespace g3;
std::unique_ptr<LogWorker> logworker {LogWorker::createWithNoSink()};
std::unique_ptr<LogWorker> logworker {LogWorker::createLogWorker()};
auto sinkHandle = logworker->addSink(std2::make_unique<FileSink>(argv[0], path_to_log_file),
&FileSink::fileWrite);

View File

@ -27,14 +27,9 @@
namespace g3 {
class LogWorker;
struct LogWorkerImpl;
using FileSinkHandle = g3::SinkHandle<g3::FileSink>;
struct DefaultFileLogger {
DefaultFileLogger(const std::string &log_prefix, const std::string &log_directory);
std::unique_ptr<LogWorker> worker;
std::unique_ptr<g3::SinkHandle<g3::FileSink>> sink;
};
/// Background side of the LogWorker. Internal use only
struct LogWorkerImpl final {
typedef std::shared_ptr<g3::internal::SinkWrapper> SinkWrapperPtr;
std::vector<SinkWrapperPtr> _sinks;
@ -46,33 +41,60 @@ namespace g3 {
void bgSave(g3::LogMessagePtr msgPtr);
void bgFatal(FatalMessagePtr msgPtr);
LogWorkerImpl(const LogWorkerImpl &) = delete;
LogWorkerImpl &operator=(const LogWorkerImpl &) = delete;
LogWorkerImpl(const LogWorkerImpl&) = delete;
LogWorkerImpl& operator=(const LogWorkerImpl&) = delete;
};
/// Front end of the LogWorker. API that is usefule is
/// addSink( sink, default_call ) which returns a handle to the sink. See below and REAME for usage example
/// save( msg ) : internal use
/// fatal ( fatal_msg ) : internal use
class LogWorker final {
LogWorker() = default;
void addWrappedSink(std::shared_ptr<g3::internal::SinkWrapper> wrapper);
LogWorkerImpl _impl;
LogWorker(const LogWorker &) = delete;
LogWorker &operator=(const LogWorker &) = delete;
LogWorker(const LogWorker&) = delete;
LogWorker& operator=(const LogWorker&) = delete;
public:
public:
~LogWorker();
static g3::DefaultFileLogger createWithDefaultLogger(const std::string &log_prefix, const std::string &log_directory);
static std::unique_ptr<LogWorker> createWithNoSink();
/// Creates the LogWorker with no sinks. See exampel below on @ref addSink for how to use it
/// if you want to use the default file logger then see below for @ref addDefaultLogger
static std::unique_ptr<LogWorker> createLogWorker();
/**
A convenience function to add the default g3::FileSink to the log worker
@param the worker (no, don't put in nullptr here!)
@param log_prefix that you want
@param log_directory where the log is to be stored.
@return a handle for API access to the sink. See the README for example usage
@verbatim
Example:
using namespace g3;
std::unique_ptr<LogWorker> logworker {LogWorker::createLogWorker()};
auto handle = addDefaultLogger("my_test_log", "/tmp");
initializeLogging(logworker.get()); // ref. g3log.hpp
std::future<std::string> log_file_name = sinkHandle->call(&FileSink::fileName);
std::cout << "The filename is: " << log_file_name.get() << std::endl;
// something like: /tmp/
*/
std::unique_ptr<FileSinkHandle> addDefaultLogger(const std::string& log_prefix, const std::string& log_directory);
/// pushes in background thread (asynchronously) input messages to log file
void save(LogMessagePtr entry);
/// Will push a fatal message on the queue, this is the last message to be processed
/// this way it's ensured that all existing entries were flushed before 'fatal'
/// Will abort the application!
void fatal(FatalMessagePtr fatal_message);
/// Adds a sink and returns the handle for access to the sink
/// @param real_sink unique_ptr ownership is passed to the log worker
/// @param call the default call that should receive either a std::string or a LogMessageMover message
/// @return handle to the sink for API access. See usage example below at @ref addDefaultLogger
template<typename T, typename DefaultLogCall>
std::unique_ptr<g3::SinkHandle<T>> addSink(std::unique_ptr<T> real_sink, DefaultLogCall call) {
using namespace g3;
@ -81,5 +103,19 @@ namespace g3 {
addWrappedSink(sink);
return std2::make_unique<SinkHandle<T>> (sink);
}
/// internal:
/// pushes in background thread (asynchronously) input messages to log file
void save(LogMessagePtr entry);
/// internal:
// pushes a fatal message on the queue, this is the last message to be processed
/// this way it's ensured that all existing entries were flushed before 'fatal'
/// Will abort the application!
void fatal(FatalMessagePtr fatal_message);
};
} // g3

View File

@ -2,7 +2,7 @@
* 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
* with no warranties. This code is yours to share, use and modify with no
* strings attached and no restrictions or obligations.
*
*
* For more information see g3log/LICENSE or refer refer to http://unlicense.org
* ============================================================================*/
@ -26,7 +26,7 @@ namespace g3 {
void LogWorkerImpl::bgSave(g3::LogMessagePtr msgPtr) {
std::unique_ptr<LogMessage> uniqueMsg(std::move(msgPtr.get()));
for (auto &sink : _sinks) {
for (auto& sink : _sinks) {
LogMessage msg(*(uniqueMsg));
sink->send(LogMessageMover(std::move(msg)));
}
@ -59,7 +59,7 @@ namespace g3 {
.append("\nLog content flushed flushed sucessfully to sink\n\n");
std::cerr << uniqueMsg->message() << std::flush;
for (auto &sink : _sinks) {
for (auto& sink : _sinks) {
LogMessage msg(*(uniqueMsg));
sink->send(LogMessageMover(std::move(msg)));
}
@ -120,17 +120,15 @@ namespace g3 {
token_done.wait();
}
g3::DefaultFileLogger LogWorker::createWithDefaultLogger(const std::string &log_prefix, const std::string &log_directory) {
return g3::DefaultFileLogger(log_prefix, log_directory);
}
std::unique_ptr<LogWorker> LogWorker::createWithNoSink() {
std::unique_ptr<LogWorker> LogWorker::createLogWorker() {
return std::unique_ptr<LogWorker>(new LogWorker);
}
DefaultFileLogger::DefaultFileLogger(const std::string &log_prefix, const std::string &log_directory)
: worker(LogWorker::createWithNoSink())
, sink(worker->addSink(std2::make_unique<g3::FileSink>(log_prefix, log_directory), &FileSink::fileWrite)) { }
std::unique_ptr<FileSinkHandle>LogWorker::addDefaultLogger(const std::string& log_prefix, const std::string& log_directory) {
return addSink(std2::make_unique<g3::FileSink>(log_prefix, log_directory), &FileSink::fileWrite);
}
} // g3

View File

@ -60,8 +60,10 @@ int main(int argc, char **argv)
oss.str(""); // clear the stream
#if defined(G3LOG_PERFORMANCE)
auto logger_n_handle = g3::LogWorker::createWithDefaultLogger(g_prefix_log_name, g_path);
g3::initializeLogging(logger_n_handle.worker.get());
auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger(g_prefix_log_name, g_path);
g3::initializeLogging(worker.get());
#elif defined(GOOGLE_GLOG_PERFORMANCE)
google::InitGoogleLogging(argv[0]);
@ -87,7 +89,7 @@ int main(int argc, char **argv)
delete [] threads;
#if defined(G3LOG_PERFORMANCE)
logger_n_handle.worker.reset(); // will flush anything in the queue to file
worker.reset(); // will flush anything in the queue to file
#elif defined(GOOGLE_GLOG_PERFORMANCE)
google::ShutdownGoogleLogging();
#endif

View File

@ -84,8 +84,9 @@ int main(int argc, char** argv)
oss.str(""); // clear the stream
#if defined(G3LOG_PERFORMANCE)
auto logger_n_handle = g3::LogWorker::createWithDefaultLogger(g_prefix_log_name, g_path);
g3::initializeLogging(logger_n_handle.worker.get());
auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger(g_prefix_log_name, g_path);
g3::initializeLogging(worker.get());
#elif defined(GOOGLE_GLOG_PERFORMANCE)
google::InitGoogleLogging(argv[0]);
@ -120,7 +121,7 @@ int main(int argc, char** argv)
#if defined(G3LOG_PERFORMANCE)
logger_n_handle.worker.reset(); // will flush anything in the queue to file
worker.reset(); // will flush anything in the queue to file
#elif defined(GOOGLE_GLOG_PERFORMANCE)
google::ShutdownGoogleLogging();
#endif

View File

@ -111,9 +111,10 @@ int main(int argc, char *argv[]) {
testing_helpers::ScopedOut scopedCerr(std::cerr, &cerrDump);
auto logger = g3::LogWorker::createWithDefaultLogger("ReplaceLogFile", name_path_1);
g_logger_ptr = logger.worker.get();
g_filesink_handler = logger.sink.get();
auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger("ReplaceLogFile", name_path_1);
g_logger_ptr = worker.get();
g_filesink_handler = handle.get();
last_log_file = g_filesink_handler->call(&g3::FileSink::fileName).get();
cleaner.addLogToClean(last_log_file);

View File

@ -198,7 +198,7 @@ TEST(Basics, DoNotShutdownActiveLogger) {
{
RestoreFileLogger logger(log_directory);
LOG(INFO) << "Not yet shutdown. This message should make it";
std::unique_ptr<g3::LogWorker> duplicateLogWorker{g3::LogWorker::createWithNoSink()};
std::unique_ptr<g3::LogWorker> duplicateLogWorker{g3::LogWorker::createLogWorker()};
EXPECT_FALSE(g3::internal::shutDownLoggingForActiveOnly(duplicateLogWorker.get()));
LOG(INFO) << "Logger is (NOT) shutdown,. this message WILL make it";
file_content = logger.resetAndRetrieveContent();

View File

@ -33,7 +33,7 @@ TEST(DynamicLoadOfLibrary, JustLoadAndExit) {
std::vector<std::string> receiver;
{ // scope to flush logs at logworker exit
auto worker = g3::LogWorker::createWithNoSink();
auto worker = g3::LogWorker::createLogWorker();
auto handle = worker->addSink(std2::make_unique<LogMessageCounter>(std::ref(receiver)), &LogMessageCounter::countMessages);
// add another sink just for more throughput of data

View File

@ -28,7 +28,7 @@ using namespace g3;
AtomicBoolPtr flag = make_shared < atomic<bool >> (false);
AtomicIntPtr count = make_shared < atomic<int >> (0);
{
auto worker = g3::LogWorker::createWithNoSink();
auto worker = g3::LogWorker::createLogWorker();
auto handle = worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
EXPECT_FALSE(flag->load());
EXPECT_TRUE(0 == count->load());
@ -61,7 +61,7 @@ TEST(ConceptSink, OneHundredSinks) {
{
RestoreFileLogger logger{"./"};
g3::LogWorker* worker = logger._scope->get(); //g3LogWorker::createWithNoSink();
g3::LogWorker* worker = logger._scope->get(); //g3LogWorker::createLogWorker();
size_t index = 0;
for (auto& flag : flags) {
auto& count = counts[index++];
@ -107,7 +107,7 @@ struct VoidReceiver {
TEST(ConceptSink, VoidCall__NoCall_ExpectingNoAdd) {
std::atomic<int> counter{0};
{
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createWithNoSink()};
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createLogWorker()};
auto handle = worker->addSink(std2::make_unique<VoidReceiver>(&counter), &VoidReceiver::receiveMsg);
}
EXPECT_EQ(counter, 0);
@ -116,7 +116,7 @@ TEST(ConceptSink, VoidCall__NoCall_ExpectingNoAdd) {
TEST(ConceptSink, VoidCall__OneCall_ExpectingOneAdd) {
std::atomic<int> counter{0};
{
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createWithNoSink()};
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createLogWorker()};
auto handle = worker->addSink(std2::make_unique<VoidReceiver>(&counter), &VoidReceiver::receiveMsg);
std::future<void> ignored = handle->call(&VoidReceiver::incrementAtomic);
}
@ -126,7 +126,7 @@ TEST(ConceptSink, VoidCall__OneCall_ExpectingOneAdd) {
TEST(ConceptSink, VoidCall__TwoCalls_ExpectingTwoAdd) {
std::atomic<int> counter{0};
{
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createWithNoSink()};
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createLogWorker()};
auto handle = worker->addSink(std2::make_unique<VoidReceiver>(&counter), &VoidReceiver::receiveMsg);
auto voidFuture1 = handle->call(&VoidReceiver::incrementAtomic);
auto voidFuture2 = handle->call(&VoidReceiver::incrementAtomic);
@ -153,7 +153,7 @@ struct IntReceiver {
TEST(ConceptSink, IntCall__TwoCalls_ExpectingTwoAdd) {
std::atomic<int> counter{0};
{
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createWithNoSink()};
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createLogWorker()};
auto handle = worker->addSink(std2::make_unique<IntReceiver>(&counter), &IntReceiver::receiveMsgDoNothing);
std::future<int> intFuture1 = handle->call(&IntReceiver::incrementAtomic);
EXPECT_EQ(intFuture1.get(), 1);
@ -210,7 +210,7 @@ TEST(ConceptSink, AggressiveThreadCallsDuringShutdown) {
for (size_t create = 0; create < numberOfCycles; ++create) {
std::cout << create << " ";
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createWithNoSink()};
std::unique_ptr<g3::LogWorker> worker{g3::LogWorker::createLogWorker()};
auto handle = worker->addSink(std2::make_unique<IntReceiver>(&atomicCounter), &IntReceiver::receiveMsgIncrementAtomic);
g3::initializeLogging(worker.get());

View File

@ -102,7 +102,7 @@ namespace testing_helpers {
}
}
ScopedLogger::ScopedLogger() : _currentWorker(g3::LogWorker::createWithNoSink()) {}
ScopedLogger::ScopedLogger() : _currentWorker(g3::LogWorker::createLogWorker()) {}
ScopedLogger::~ScopedLogger() {}
g3::LogWorker* ScopedLogger::get() {