Implemented logging to log file
This commit is contained in:
parent
35ec1f8a45
commit
af5a6649c1
|
@ -1,6 +1,12 @@
|
|||
#include "logging.h"
|
||||
#include <boost/log/sinks/unlocked_frontend.hpp>
|
||||
#include <boost/log/sinks/text_file_backend.hpp>
|
||||
#include <boost/log/sinks/sync_frontend.hpp>
|
||||
#include <boost/log/expressions.hpp>
|
||||
#include <boost/log/keywords/file_name.hpp>
|
||||
#include <boost/log/utility/setup/common_attributes.hpp>
|
||||
// ReSharper disable once CppUnusedIncludeDirective
|
||||
#include <boost/log/support/date_time.hpp>
|
||||
#include <centiseconds.h>
|
||||
#include "tools.h"
|
||||
|
||||
|
@ -14,6 +20,9 @@ using std::tuple;
|
|||
using std::make_tuple;
|
||||
|
||||
namespace expr = boost::log::expressions;
|
||||
namespace keywords = boost::log::keywords;
|
||||
namespace sinks = boost::log::sinks;
|
||||
namespace attr = boost::log::attributes;
|
||||
|
||||
template <>
|
||||
const string& getEnumTypeName<LogLevel>() {
|
||||
|
@ -75,7 +84,17 @@ void PausableBackendAdapter::resume() {
|
|||
buffer.clear();
|
||||
}
|
||||
|
||||
boost::shared_ptr<PausableBackendAdapter> initLogging() {
|
||||
BOOST_LOG_GLOBAL_LOGGER_INIT(globalLogger, LoggerType) {
|
||||
LoggerType logger;
|
||||
|
||||
logger.add_attribute("TimeStamp", attr::local_clock());
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", LogLevel)
|
||||
|
||||
boost::shared_ptr<PausableBackendAdapter> addPausableStderrSink(LogLevel minLogLevel) {
|
||||
// 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*) {}));
|
||||
|
@ -86,14 +105,24 @@ boost::shared_ptr<PausableBackendAdapter> initLogging() {
|
|||
|
||||
// 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);
|
||||
|
||||
sink->set_formatter(expr::stream << "[" << severity << "] " << expr::smessage);
|
||||
sink->set_filter(severity >= minLogLevel);
|
||||
boost::log::core::get()->add_sink(sink);
|
||||
|
||||
return pausableAdapter;
|
||||
}
|
||||
|
||||
void addFileSink(const boost::filesystem::path& logFilePath, LogLevel minLogLevel) {
|
||||
auto textFileBackend = boost::make_shared<sinks::text_file_backend>(
|
||||
keywords::file_name = logFilePath.string());
|
||||
auto sink = boost::make_shared<sinks::synchronous_sink<sinks::text_file_backend>>(textFileBackend);
|
||||
sink->set_formatter(expr::stream
|
||||
<< "[" << expr::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S")
|
||||
<< "] [" << severity << "] " << expr::smessage);
|
||||
sink->set_filter(severity >= minLogLevel);
|
||||
boost::log::core::get()->add_sink(sink);
|
||||
}
|
||||
|
||||
void logTimedEvent(const string& eventName, centiseconds start, centiseconds end, const string& value) {
|
||||
LOG_DEBUG << "##" << eventName << "[" << formatDuration(start) << "-" << formatDuration(end) << "]: " << value;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <mutex>
|
||||
#include <tuple>
|
||||
#include "centiseconds.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "enumTools.h"
|
||||
|
||||
enum class LogLevel {
|
||||
|
@ -33,7 +34,7 @@ std::istream& operator>>(std::istream& stream, LogLevel& value);
|
|||
|
||||
using LoggerType = boost::log::sources::severity_logger_mt<LogLevel>;
|
||||
|
||||
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(globalLogger, LoggerType)
|
||||
BOOST_LOG_GLOBAL_LOGGER(globalLogger, LoggerType)
|
||||
|
||||
#define LOG(level) \
|
||||
BOOST_LOG_STREAM_WITH_PARAMS(globalLogger::get(), (::boost::log::keywords::severity = level))
|
||||
|
@ -61,6 +62,8 @@ private:
|
|||
bool isPaused = false;
|
||||
};
|
||||
|
||||
boost::shared_ptr<PausableBackendAdapter> initLogging();
|
||||
boost::shared_ptr<PausableBackendAdapter> addPausableStderrSink(LogLevel minLogLevel);
|
||||
|
||||
void addFileSink(const boost::filesystem::path& logFilePath, LogLevel minLogLevel);
|
||||
|
||||
void logTimedEvent(const std::string& eventName, centiseconds start, centiseconds end, const std::string& value);
|
||||
|
|
36
src/main.cpp
36
src/main.cpp
|
@ -16,6 +16,7 @@
|
|||
|
||||
using std::exception;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::unique_ptr;
|
||||
using std::map;
|
||||
using std::chrono::duration;
|
||||
|
@ -23,6 +24,8 @@ using std::chrono::duration_cast;
|
|||
using boost::filesystem::path;
|
||||
using boost::property_tree::ptree;
|
||||
|
||||
namespace tclap = TCLAP;
|
||||
|
||||
string getMessage(const exception& e) {
|
||||
string result(e.what());
|
||||
try {
|
||||
|
@ -69,36 +72,45 @@ ptree createXmlTree(const path& filePath, const map<centiseconds, Phone>& phones
|
|||
return tree;
|
||||
}
|
||||
|
||||
// Tell TCLAP how to handle boost::optional
|
||||
// Tell TCLAP how to handle our types
|
||||
namespace TCLAP {
|
||||
template<>
|
||||
struct ArgTraits<boost::optional<string>> {
|
||||
typedef TCLAP::StringLike ValueCategory;
|
||||
struct ArgTraits<LogLevel> {
|
||||
typedef ValueLike ValueCategory;
|
||||
};
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
auto logOutputController = initLogging();
|
||||
logOutputController->pause();
|
||||
auto pausableStderrSink = addPausableStderrSink(LogLevel::Warning);
|
||||
pausableStderrSink->pause();
|
||||
|
||||
// Define command-line parameters
|
||||
const char argumentValueSeparator = ' ';
|
||||
TCLAP::CmdLine cmd(appName, argumentValueSeparator, appVersion);
|
||||
tclap::CmdLine cmd(appName, argumentValueSeparator, appVersion);
|
||||
cmd.setExceptionHandling(false);
|
||||
cmd.setOutput(new NiceCmdLineOutput());
|
||||
TCLAP::UnlabeledValueArg<string> inputFileName("inputFile", "The input file. Must be a sound file in WAVE format.", true, "", "string", cmd);
|
||||
TCLAP::ValueArg<boost::optional<string>> dialog("d", "dialog", "The text of the dialog.", false, boost::optional<string>(), "string", cmd);
|
||||
auto logLevels = vector<LogLevel>(getEnumValues<LogLevel>());
|
||||
tclap::ValuesConstraint<LogLevel> logLevelConstraint(logLevels);
|
||||
tclap::ValueArg<LogLevel> logLevel("", "logLevel", "The minimum log level to log", false, LogLevel::Debug, &logLevelConstraint, cmd);
|
||||
tclap::ValueArg<string> logFileName("", "logFile", "The log file path.", false, string(), "string", cmd);
|
||||
tclap::ValueArg<string> dialog("d", "dialog", "The text of the dialog.", false, string(), "string", cmd);
|
||||
tclap::UnlabeledValueArg<string> inputFileName("inputFile", "The input file. Must be a sound file in WAVE format.", true, "", "string", cmd);
|
||||
|
||||
try {
|
||||
auto resumeLogging = gsl::finally([&]() {
|
||||
std::cerr << std::endl << std::endl;
|
||||
logOutputController->resume();
|
||||
pausableStderrSink->resume();
|
||||
std::cerr << std::endl;
|
||||
});
|
||||
|
||||
// Parse command line
|
||||
cmd.parse(argc, argv);
|
||||
|
||||
// Set up log file
|
||||
if (logFileName.isSet()) {
|
||||
addFileSink(path(logFileName.getValue()), logLevel.getValue());
|
||||
}
|
||||
|
||||
// Detect phones
|
||||
const int columnWidth = 30;
|
||||
std::cerr << std::left;
|
||||
|
@ -108,7 +120,7 @@ int main(int argc, char *argv[]) {
|
|||
ProgressBar progressBar;
|
||||
phones = detectPhones(
|
||||
createAudioStream(inputFileName.getValue()),
|
||||
dialog.getValue(),
|
||||
dialog.isSet() ? dialog.getValue() : boost::optional<string>(),
|
||||
progressBar);
|
||||
}
|
||||
std::cerr << "Done" << std::endl;
|
||||
|
@ -125,12 +137,12 @@ int main(int argc, char *argv[]) {
|
|||
boost::property_tree::write_xml(std::cout, xmlTree, boost::property_tree::xml_writer_settings<string>(' ', 2));
|
||||
|
||||
return 0;
|
||||
} catch (TCLAP::ArgException& e) {
|
||||
} catch (tclap::ArgException& e) {
|
||||
// Error parsing command-line args.
|
||||
cmd.getOutput()->failure(cmd, e);
|
||||
std::cerr << std::endl;
|
||||
return 1;
|
||||
} catch (TCLAP::ExitException&) {
|
||||
} catch (tclap::ExitException&) {
|
||||
// A built-in TCLAP command (like --help) has finished. Exit application.
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue