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