Prepared for logging using Boost.Log v2
This commit is contained in:
parent
7a1f446ca3
commit
7efea6f56b
|
@ -28,13 +28,16 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
|||
add_compile_options(/MT$<$<CONFIG:Debug>:d>)
|
||||
endif()
|
||||
|
||||
# Define flags variables for later use
|
||||
# Set global flags and define flags variables for later use
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(enableWarningsFlags "-Wall;-Wextra")
|
||||
set(disableWarningsFlags "-w")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(enableWarningsFlags "/W4")
|
||||
set(disableWarningsFlags "/W0")
|
||||
|
||||
# Boost.Log causes this warning
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4714")
|
||||
endif()
|
||||
|
||||
# Enable project folders
|
||||
|
@ -46,7 +49,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
|||
set(Boost_USE_STATIC_LIBS ON) # Use static libs
|
||||
set(Boost_USE_MULTITHREADED ON) # Enable multithreading support
|
||||
set(Boost_USE_STATIC_RUNTIME ON) # Use static C++ runtime
|
||||
find_package(Boost REQUIRED COMPONENTS filesystem locale system)
|
||||
find_package(Boost REQUIRED COMPONENTS filesystem locale system log date_time thread chrono)
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||
|
||||
# ... C++ Format
|
||||
|
@ -105,6 +108,7 @@ set(SOURCE_FILES
|
|||
src/NiceCmdLineOutput.cpp
|
||||
src/TablePrinter.cpp
|
||||
src/ProgressBar.cpp
|
||||
src/logging.cpp
|
||||
)
|
||||
add_executable(rhubarb ${SOURCE_FILES})
|
||||
target_link_libraries(rhubarb ${Boost_LIBRARIES} cppFormat sphinxbase pocketSphinx)
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
#include "logging.h"
|
||||
#include <array>
|
||||
#include <boost/log/sinks/unlocked_frontend.hpp>
|
||||
#include <boost/log/expressions.hpp>
|
||||
|
||||
using std::string;
|
||||
using std::lock_guard;
|
||||
using boost::log::sinks::text_ostream_backend;
|
||||
using boost::log::record_view;
|
||||
using boost::log::sinks::unlocked_sink;
|
||||
|
||||
namespace expr = boost::log::expressions;
|
||||
|
||||
string toString(LogLevel level) {
|
||||
constexpr size_t levelCount = static_cast<size_t>(LogLevel::EndSentinel);
|
||||
static const std::array<const string, levelCount> strings = {
|
||||
"Trace", "Debug", "Info", "Warning", "Error", "Fatal"
|
||||
};
|
||||
return strings.at(static_cast<size_t>(level));
|
||||
}
|
||||
|
||||
PausableBackendAdapter::PausableBackendAdapter(boost::shared_ptr<text_ostream_backend> backend) :
|
||||
backend(backend) {}
|
||||
|
||||
void PausableBackendAdapter::consume(const record_view& recordView, const string message) {
|
||||
lock_guard<std::mutex> lock(mutex);
|
||||
if (isPaused) {
|
||||
buffer.push_back(std::make_tuple(recordView, message));
|
||||
} else {
|
||||
backend->consume(recordView, message);
|
||||
}
|
||||
}
|
||||
|
||||
void PausableBackendAdapter::pause() {
|
||||
lock_guard<std::mutex> lock(mutex);
|
||||
isPaused = true;
|
||||
}
|
||||
|
||||
void PausableBackendAdapter::resume() {
|
||||
lock_guard<std::mutex> lock(mutex);
|
||||
isPaused = false;
|
||||
for (const auto& tuple : buffer) {
|
||||
backend->consume(std::get<record_view>(tuple), std::get<string>(tuple));
|
||||
}
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
boost::shared_ptr<PausableBackendAdapter> initLogging() {
|
||||
// Create logging backend that logs to stderr
|
||||
auto streamBackend = boost::make_shared<text_ostream_backend>();
|
||||
streamBackend->add_stream(boost::shared_ptr<std::ostream>(&std::cerr, [](std::ostream*) {}));
|
||||
streamBackend->auto_flush(true);
|
||||
|
||||
// Create an adapter that allows us to pause, buffer, and resume log output
|
||||
auto pausableAdapter = boost::make_shared<PausableBackendAdapter>(streamBackend);
|
||||
|
||||
// Create a sink that feeds into the adapter
|
||||
auto sink = boost::make_shared<unlocked_sink<PausableBackendAdapter>>(pausableAdapter);
|
||||
|
||||
// Set output formatting
|
||||
sink->set_formatter(expr::stream << "[" << expr::attr<LogLevel>("Severity") << "] " << expr::smessage);
|
||||
|
||||
boost::log::core::get()->add_sink(sink);
|
||||
return pausableAdapter;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
|
||||
#include <boost/log/common.hpp>
|
||||
#include <boost/log/sinks/basic_sink_backend.hpp>
|
||||
#include <boost/log/sinks/frontend_requirements.hpp>
|
||||
#include <boost/log/sinks/text_ostream_backend.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <tuple>
|
||||
|
||||
enum class LogLevel {
|
||||
Trace,
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal,
|
||||
EndSentinel
|
||||
};
|
||||
|
||||
std::string toString(LogLevel level);
|
||||
|
||||
template<typename CharT, typename TraitsT>
|
||||
std::basic_ostream<CharT, TraitsT>& operator<< (std::basic_ostream<CharT, TraitsT>& stream, LogLevel level) {
|
||||
return stream << toString(level);
|
||||
}
|
||||
|
||||
using LoggerType = boost::log::sources::severity_logger_mt<LogLevel>;
|
||||
|
||||
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(globalLogger, LoggerType)
|
||||
|
||||
#define LOG(level) \
|
||||
BOOST_LOG_STREAM_WITH_PARAMS(globalLogger::get(), (::boost::log::keywords::severity = level))
|
||||
|
||||
#define LOG_TRACE LOG(LogLevel::Trace)
|
||||
#define LOG_DEBUG LOG(LogLevel::Debug)
|
||||
#define LOG_INFO LOG(LogLevel::Info)
|
||||
#define LOG_WARNING LOG(LogLevel::Warning)
|
||||
#define LOG_ERROR LOG(LogLevel::Error)
|
||||
#define LOG_FATAL LOG(LogLevel::Fatal)
|
||||
|
||||
class PausableBackendAdapter :
|
||||
public boost::log::sinks::basic_formatted_sink_backend<char, boost::log::sinks::concurrent_feeding>
|
||||
{
|
||||
public:
|
||||
PausableBackendAdapter(boost::shared_ptr<boost::log::sinks::text_ostream_backend> backend);
|
||||
void consume(const boost::log::record_view& recordView, const std::string message);
|
||||
void pause();
|
||||
void resume();
|
||||
private:
|
||||
boost::shared_ptr<boost::log::sinks::text_ostream_backend> backend;
|
||||
std::vector<std::tuple<boost::log::record_view, std::string>> buffer;
|
||||
std::mutex mutex;
|
||||
bool isPaused = false;
|
||||
};
|
||||
|
||||
boost::shared_ptr<PausableBackendAdapter> initLogging();
|
15
src/main.cpp
15
src/main.cpp
|
@ -10,6 +10,8 @@
|
|||
#include "appInfo.h"
|
||||
#include "NiceCmdLineOutput.h"
|
||||
#include "ProgressBar.h"
|
||||
#include "logging.h"
|
||||
#include <gsl_util.h>
|
||||
|
||||
using std::exception;
|
||||
using std::string;
|
||||
|
@ -79,6 +81,9 @@ namespace TCLAP {
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
auto logOutputController = initLogging();
|
||||
logOutputController->pause();
|
||||
|
||||
// Define command-line parameters
|
||||
const char argumentValueSeparator = ' ';
|
||||
TCLAP::CmdLine cmd(appName, argumentValueSeparator, appVersion);
|
||||
|
@ -88,6 +93,12 @@ int main(int argc, char *argv[]) {
|
|||
TCLAP::ValueArg<boost::optional<string>> dialog("d", "dialog", "The text of the dialog.", false, boost::optional<string>(), "string", cmd);
|
||||
|
||||
try {
|
||||
auto resumeLogging = gsl::finally([&]() {
|
||||
std::cerr << std::endl << std::endl;
|
||||
logOutputController->resume();
|
||||
std::cerr << std::endl;
|
||||
});
|
||||
|
||||
// Parse command line
|
||||
cmd.parse(argc, argv);
|
||||
|
||||
|
@ -120,13 +131,15 @@ int main(int argc, char *argv[]) {
|
|||
} catch (TCLAP::ArgException& e) {
|
||||
// Error parsing command-line args.
|
||||
cmd.getOutput()->failure(cmd, e);
|
||||
std::cerr << std::endl;
|
||||
return 1;
|
||||
} catch (TCLAP::ExitException&) {
|
||||
// A built-in TCLAP command (like --help) has finished. Exit application.
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
} catch (const exception& e) {
|
||||
// Generic error
|
||||
std::cerr << "An error occurred. " << getMessage(e);
|
||||
std::cerr << "An error occurred. " << getMessage(e) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue