Replaced Boost.Log with small custom logger
Boost.Log is a complex monstrosity and I can't get it to build on OS X.
This commit is contained in:
parent
4941bff739
commit
7ce79f9c08
|
@ -36,10 +36,6 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
set(enableWarningsFlags "/W4")
|
set(enableWarningsFlags "/W4")
|
||||||
set(disableWarningsFlags "/W0")
|
set(disableWarningsFlags "/W0")
|
||||||
|
|
||||||
# Disable warning C4714: function '...' marked as __forceinline not inlined
|
|
||||||
# This is caused by Boost.Log
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4714")
|
|
||||||
|
|
||||||
# Disable warning C4456: declaration of '...' hides previous local declaration
|
# Disable warning C4456: declaration of '...' hides previous local declaration
|
||||||
# I'm doing that on purpose.
|
# I'm doing that on purpose.
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4458")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4458")
|
||||||
|
@ -54,7 +50,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
set(Boost_USE_STATIC_LIBS ON) # Use static libs
|
set(Boost_USE_STATIC_LIBS ON) # Use static libs
|
||||||
set(Boost_USE_MULTITHREADED ON) # Enable multithreading support
|
set(Boost_USE_MULTITHREADED ON) # Enable multithreading support
|
||||||
set(Boost_USE_STATIC_RUNTIME ON) # Use static C++ runtime
|
set(Boost_USE_STATIC_RUNTIME ON) # Use static C++ runtime
|
||||||
find_package(Boost REQUIRED COMPONENTS filesystem locale system log date_time thread chrono)
|
find_package(Boost REQUIRED COMPONENTS filesystem locale system)
|
||||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
# ... C++ Format
|
# ... C++ Format
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/property_tree/ptree.hpp>
|
#include <boost/property_tree/ptree.hpp>
|
||||||
#include <boost/property_tree/xml_parser.hpp>
|
#include <boost/property_tree/xml_parser.hpp>
|
||||||
|
#include <tools.h>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using boost::property_tree::ptree;
|
using boost::property_tree::ptree;
|
||||||
|
|
|
@ -48,7 +48,7 @@ Timeline<bool> detectVoiceActivity(std::unique_ptr<AudioStream> audioStream) {
|
||||||
|
|
||||||
// Log
|
// Log
|
||||||
for (const auto& element : activity) {
|
for (const auto& element : activity) {
|
||||||
logTimedEvent("utterance", static_cast<TimeRange>(element), std::string());
|
logging::logTimedEvent("utterance", static_cast<TimeRange>(element), std::string());
|
||||||
}
|
}
|
||||||
|
|
||||||
return activity;
|
return activity;
|
||||||
|
|
168
src/logging.cpp
168
src/logging.cpp
|
@ -1,123 +1,131 @@
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include <boost/log/sinks/unlocked_frontend.hpp>
|
#include <tools.h>
|
||||||
#include <boost/log/sinks/text_file_backend.hpp>
|
#include <iostream>
|
||||||
#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 <Timed.h>
|
|
||||||
|
|
||||||
|
using namespace logging;
|
||||||
using std::string;
|
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;
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::tuple;
|
using std::tuple;
|
||||||
using std::make_tuple;
|
using std::make_tuple;
|
||||||
|
using std::shared_ptr;
|
||||||
namespace expr = boost::log::expressions;
|
using std::lock_guard;
|
||||||
namespace keywords = boost::log::keywords;
|
|
||||||
namespace sinks = boost::log::sinks;
|
|
||||||
namespace attr = boost::log::attributes;
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const string& getEnumTypeName<LogLevel>() {
|
const string& getEnumTypeName<Level>() {
|
||||||
static const string name = "LogLevel";
|
static const string name = "LogLevel";
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const vector<tuple<LogLevel, string>>& getEnumMembers<LogLevel>() {
|
const vector<tuple<Level, string>>& getEnumMembers<Level>() {
|
||||||
static const vector<tuple<LogLevel, string>> values = {
|
static const vector<tuple<Level, string>> values = {
|
||||||
make_tuple(LogLevel::Trace, "Trace"),
|
make_tuple(Level::Trace, "Trace"),
|
||||||
make_tuple(LogLevel::Debug, "Debug"),
|
make_tuple(Level::Debug, "Debug"),
|
||||||
make_tuple(LogLevel::Info, "Info"),
|
make_tuple(Level::Info, "Info"),
|
||||||
make_tuple(LogLevel::Warning, "Warning"),
|
make_tuple(Level::Warn, "Warn"),
|
||||||
make_tuple(LogLevel::Error, "Error"),
|
make_tuple(Level::Error, "Error"),
|
||||||
make_tuple(LogLevel::Fatal, "Fatal")
|
make_tuple(Level::Fatal, "Fatal")
|
||||||
};
|
};
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, LogLevel value) {
|
std::ostream& operator<<(std::ostream& stream, Level value) {
|
||||||
return stream << enumToString(value);
|
return stream << enumToString(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::istream& operator>>(std::istream& stream, LogLevel& value) {
|
std::istream& operator>>(std::istream& stream, Level& value) {
|
||||||
string name;
|
string name;
|
||||||
stream >> name;
|
stream >> name;
|
||||||
value = parseEnum<LogLevel>(name);
|
value = parseEnum<Level>(name);
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
PausableBackendAdapter::PausableBackendAdapter(boost::shared_ptr<text_ostream_backend> backend) :
|
Entry::Entry(Level level, const string& message) :
|
||||||
backend(backend) {}
|
level(level),
|
||||||
|
message(message)
|
||||||
PausableBackendAdapter::~PausableBackendAdapter() {
|
{
|
||||||
resume();
|
time(×tamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PausableBackendAdapter::consume(const record_view& recordView, const string message) {
|
string SimpleConsoleFormatter::format(const Entry& entry) {
|
||||||
lock_guard<std::mutex> lock(mutex);
|
return fmt::format("[{0}] {1}", entry.level, entry.message);
|
||||||
if (isPaused) {
|
}
|
||||||
buffer.push_back(std::make_tuple(recordView, message));
|
|
||||||
} else {
|
string SimpleFileFormatter::format(const Entry& entry) {
|
||||||
backend->consume(recordView, message);
|
return fmt::format("[{0}] {1}", formatTime(entry.timestamp, "%F %H:%M:%S"), consoleFormatter.format(entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelFilter::LevelFilter(shared_ptr<Sink> innerSink, Level minLevel) :
|
||||||
|
innerSink(innerSink),
|
||||||
|
minLevel(minLevel)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void LevelFilter::receive(const Entry& entry) {
|
||||||
|
if (entry.level >= minLevel) {
|
||||||
|
innerSink->receive(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PausableBackendAdapter::pause() {
|
StreamSink::StreamSink(shared_ptr<std::ostream> stream, shared_ptr<Formatter> formatter) :
|
||||||
lock_guard<std::mutex> lock(mutex);
|
stream(stream),
|
||||||
isPaused = true;
|
formatter(formatter)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void StreamSink::receive(const Entry& entry) {
|
||||||
|
string line = formatter->format(entry);
|
||||||
|
*stream << line << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PausableBackendAdapter::resume() {
|
StdErrSink::StdErrSink(shared_ptr<Formatter> formatter) :
|
||||||
|
StreamSink(std::shared_ptr<std::ostream>(&std::cerr, [](void*){}), formatter)
|
||||||
|
{}
|
||||||
|
|
||||||
|
PausableSink::PausableSink(shared_ptr<Sink> innerSink) :
|
||||||
|
innerSink(innerSink)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void PausableSink::receive(const Entry& entry) {
|
||||||
|
lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (isPaused) {
|
||||||
|
buffer.push_back(entry);
|
||||||
|
} else {
|
||||||
|
innerSink->receive(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PausableSink::pause() {
|
||||||
|
lock_guard<std::mutex> lock(mutex);
|
||||||
|
isPaused = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PausableSink::resume() {
|
||||||
lock_guard<std::mutex> lock(mutex);
|
lock_guard<std::mutex> lock(mutex);
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
for (const auto& tuple : buffer) {
|
for (const Entry& entry : buffer) {
|
||||||
backend->consume(std::get<record_view>(tuple), std::get<string>(tuple));
|
innerSink->receive(entry);
|
||||||
}
|
}
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_GLOBAL_LOGGER_INIT(globalLogger, LoggerType) {
|
std::mutex& getLogMutex() {
|
||||||
LoggerType logger;
|
static std::mutex mutex;
|
||||||
|
return mutex;
|
||||||
logger.add_attribute("TimeStamp", attr::local_clock());
|
|
||||||
|
|
||||||
return logger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", LogLevel)
|
vector<shared_ptr<Sink>>& getSinks() {
|
||||||
|
static vector<shared_ptr<Sink>> sinks;
|
||||||
boost::shared_ptr<PausableBackendAdapter> addPausableStderrSink(LogLevel minLogLevel) {
|
return sinks;
|
||||||
// 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);
|
|
||||||
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) {
|
void logging::addSink(shared_ptr<Sink> sink) {
|
||||||
auto textFileBackend = boost::make_shared<sinks::text_file_backend>(
|
lock_guard<std::mutex> lock(getLogMutex());
|
||||||
keywords::file_name = logFilePath.string());
|
getSinks().push_back(sink);
|
||||||
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")
|
void logging::log(Level level, const string& message) {
|
||||||
<< "] [" << severity << "] " << expr::smessage);
|
lock_guard<std::mutex> lock(getLogMutex());
|
||||||
sink->set_filter(severity >= minLogLevel);
|
for (auto& sink : getSinks()) {
|
||||||
boost::log::core::get()->add_sink(sink);
|
sink->receive(Entry(level, message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
155
src/logging.h
155
src/logging.h
|
@ -1,86 +1,145 @@
|
||||||
#pragma once
|
#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 <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include "centiseconds.h"
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include "tools.h"
|
|
||||||
#include "enumTools.h"
|
#include "enumTools.h"
|
||||||
|
#include "tools.h"
|
||||||
#include "Timed.h"
|
#include "Timed.h"
|
||||||
|
|
||||||
enum class LogLevel {
|
namespace logging {
|
||||||
|
|
||||||
|
enum class Level {
|
||||||
Trace,
|
Trace,
|
||||||
Debug,
|
Debug,
|
||||||
Info,
|
Info,
|
||||||
Warning,
|
Warn,
|
||||||
Error,
|
Error,
|
||||||
Fatal,
|
Fatal,
|
||||||
EndSentinel
|
EndSentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
const std::string& getEnumTypeName<LogLevel>();
|
const std::string& getEnumTypeName<logging::Level>();
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
const std::vector<std::tuple<LogLevel, std::string>>& getEnumMembers<LogLevel>();
|
const std::vector<std::tuple<logging::Level, std::string>>& getEnumMembers<logging::Level>();
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, LogLevel value);
|
std::ostream& operator<<(std::ostream& stream, logging::Level value);
|
||||||
|
|
||||||
std::istream& operator>>(std::istream& stream, LogLevel& value);
|
std::istream& operator>>(std::istream& stream, logging::Level& value);
|
||||||
|
|
||||||
using LoggerType = boost::log::sources::severity_logger_mt<LogLevel>;
|
namespace logging {
|
||||||
|
|
||||||
BOOST_LOG_GLOBAL_LOGGER(globalLogger, LoggerType)
|
struct Entry {
|
||||||
|
Entry(Level level, const std::string& message);
|
||||||
|
|
||||||
#define LOG(level) \
|
time_t timestamp;
|
||||||
BOOST_LOG_STREAM_WITH_PARAMS(globalLogger::get(), (::boost::log::keywords::severity = level))
|
Level level;
|
||||||
|
std::string message;
|
||||||
|
};
|
||||||
|
|
||||||
#define LOG_TRACE LOG(LogLevel::Trace)
|
class Formatter {
|
||||||
#define LOG_DEBUG LOG(LogLevel::Debug)
|
public:
|
||||||
#define LOG_INFO LOG(LogLevel::Info)
|
virtual ~Formatter() = default;
|
||||||
#define LOG_WARNING LOG(LogLevel::Warning)
|
virtual std::string format(const Entry& entry) = 0;
|
||||||
#define LOG_ERROR LOG(LogLevel::Error)
|
};
|
||||||
#define LOG_FATAL LOG(LogLevel::Fatal)
|
|
||||||
|
|
||||||
class PausableBackendAdapter :
|
class SimpleConsoleFormatter : public Formatter {
|
||||||
public boost::log::sinks::basic_formatted_sink_backend<char, boost::log::sinks::concurrent_feeding>
|
public:
|
||||||
{
|
std::string format(const Entry& entry) override;
|
||||||
public:
|
};
|
||||||
PausableBackendAdapter(boost::shared_ptr<boost::log::sinks::text_ostream_backend> backend);
|
|
||||||
~PausableBackendAdapter();
|
class SimpleFileFormatter : public Formatter {
|
||||||
void consume(const boost::log::record_view& recordView, const std::string message);
|
public:
|
||||||
|
std::string format(const Entry& entry) override;
|
||||||
|
private:
|
||||||
|
SimpleConsoleFormatter consoleFormatter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Sink {
|
||||||
|
public:
|
||||||
|
virtual ~Sink() = default;
|
||||||
|
virtual void receive(const Entry& entry) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LevelFilter : public Sink {
|
||||||
|
public:
|
||||||
|
LevelFilter(std::shared_ptr<Sink> innerSink, Level minLevel);
|
||||||
|
void receive(const Entry& entry) override;
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Sink> innerSink;
|
||||||
|
Level minLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StreamSink : public Sink {
|
||||||
|
public:
|
||||||
|
StreamSink(std::shared_ptr<std::ostream> stream, std::shared_ptr<Formatter> formatter);
|
||||||
|
void receive(const Entry& entry) override;
|
||||||
|
private:
|
||||||
|
std::shared_ptr<std::ostream> stream;
|
||||||
|
std::shared_ptr<Formatter> formatter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StdErrSink : public StreamSink {
|
||||||
|
public:
|
||||||
|
explicit StdErrSink(std::shared_ptr<Formatter> formatter);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PausableSink : public Sink {
|
||||||
|
public:
|
||||||
|
explicit PausableSink(std::shared_ptr<Sink> innerSink);
|
||||||
|
void receive(const Entry& entry) override;
|
||||||
void pause();
|
void pause();
|
||||||
void resume();
|
void resume();
|
||||||
private:
|
private:
|
||||||
boost::shared_ptr<boost::log::sinks::text_ostream_backend> backend;
|
std::shared_ptr<Sink> innerSink;
|
||||||
std::vector<std::tuple<boost::log::record_view, std::string>> buffer;
|
std::vector<Entry> buffer;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
bool isPaused = false;
|
bool isPaused = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::shared_ptr<PausableBackendAdapter> addPausableStderrSink(LogLevel minLogLevel);
|
void addSink(std::shared_ptr<Sink> sink);
|
||||||
|
|
||||||
void addFileSink(const boost::filesystem::path& logFilePath, LogLevel minLogLevel);
|
void log(Level level, const std::string& message);
|
||||||
|
|
||||||
template<typename TValue>
|
template <typename... Args>
|
||||||
void logTimedEvent(const std::string& eventName, const Timed<TValue> timedValue) {
|
void logFormat(Level level, fmt::CStringRef format, const Args&... args) {
|
||||||
LOG_DEBUG
|
log(level, fmt::format(format, args...));
|
||||||
<< "##" << eventName << "[" << formatDuration(timedValue.getStart()) << "-" << formatDuration(timedValue.getEnd()) << "]: "
|
}
|
||||||
<< timedValue.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TValue>
|
#define LOG_WITH_LEVEL(levelName, levelEnum) \
|
||||||
void logTimedEvent(const std::string& eventName, const TimeRange& timeRange, const TValue& value) {
|
inline void levelName(const std::string& message) { \
|
||||||
|
log(Level::levelEnum, message); \
|
||||||
|
} \
|
||||||
|
template <typename... Args> \
|
||||||
|
void levelName ## Format(fmt::CStringRef format, const Args&... args) { \
|
||||||
|
logFormat(Level::levelEnum, format, args...); \
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_WITH_LEVEL(trace, Trace)
|
||||||
|
LOG_WITH_LEVEL(debug, Debug)
|
||||||
|
LOG_WITH_LEVEL(info, Info)
|
||||||
|
LOG_WITH_LEVEL(warn, Warn)
|
||||||
|
LOG_WITH_LEVEL(error, Error)
|
||||||
|
LOG_WITH_LEVEL(fatal, Fatal)
|
||||||
|
|
||||||
|
template<typename TValue>
|
||||||
|
void logTimedEvent(const std::string& eventName, const Timed<TValue> timedValue) {
|
||||||
|
debugFormat("##{0} [{1}-{2}]: {3}",
|
||||||
|
eventName, formatDuration(timedValue.getStart()), formatDuration(timedValue.getEnd()), timedValue.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TValue>
|
||||||
|
void logTimedEvent(const std::string& eventName, const TimeRange& timeRange, const TValue& value) {
|
||||||
logTimedEvent(eventName, Timed<TValue>(timeRange, value));
|
logTimedEvent(eventName, Timed<TValue>(timeRange, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
void logTimedEvent(const std::string& eventName, centiseconds start, centiseconds end, const TValue& value) {
|
void logTimedEvent(const std::string& eventName, centiseconds start, centiseconds end, const TValue& value) {
|
||||||
logTimedEvent(eventName, Timed<TValue>(start, end, value));
|
logTimedEvent(eventName, Timed<TValue>(start, end, value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
29
src/main.cpp
29
src/main.cpp
|
@ -18,6 +18,8 @@ using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
|
using std::shared_ptr;
|
||||||
|
using std::make_shared;
|
||||||
using std::map;
|
using std::map;
|
||||||
using std::chrono::duration;
|
using std::chrono::duration;
|
||||||
using std::chrono::duration_cast;
|
using std::chrono::duration_cast;
|
||||||
|
@ -47,7 +49,7 @@ unique_ptr<AudioStream> createAudioStream(path filePath) {
|
||||||
// Tell TCLAP how to handle our types
|
// Tell TCLAP how to handle our types
|
||||||
namespace TCLAP {
|
namespace TCLAP {
|
||||||
template<>
|
template<>
|
||||||
struct ArgTraits<LogLevel> {
|
struct ArgTraits<logging::Level> {
|
||||||
typedef ValueLike ValueCategory;
|
typedef ValueLike ValueCategory;
|
||||||
};
|
};
|
||||||
template<>
|
template<>
|
||||||
|
@ -56,8 +58,25 @@ namespace TCLAP {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<logging::PausableSink> addPausableStdErrSink(logging::Level minLevel) {
|
||||||
|
auto stdErrSink = make_shared<logging::StdErrSink>(make_shared<logging::SimpleConsoleFormatter>());
|
||||||
|
auto pausableSink = make_shared<logging::PausableSink>(stdErrSink);
|
||||||
|
auto levelFilter = make_shared<logging::LevelFilter>(pausableSink, minLevel);
|
||||||
|
logging::addSink(levelFilter);
|
||||||
|
return pausableSink;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addFileSink(path path, logging::Level minLevel) {
|
||||||
|
auto file = make_shared<boost::filesystem::ofstream>();
|
||||||
|
file->exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||||
|
file->open(path);
|
||||||
|
auto FileSink = make_shared<logging::StreamSink>(file, make_shared<logging::SimpleFileFormatter>());
|
||||||
|
auto levelFilter = make_shared<logging::LevelFilter>(FileSink, minLevel);
|
||||||
|
logging::addSink(levelFilter);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
auto pausableStderrSink = addPausableStderrSink(LogLevel::Warning);
|
auto pausableStderrSink = addPausableStdErrSink(logging::Level::Warn);
|
||||||
pausableStderrSink->pause();
|
pausableStderrSink->pause();
|
||||||
|
|
||||||
// Define command-line parameters
|
// Define command-line parameters
|
||||||
|
@ -65,9 +84,9 @@ int main(int argc, char *argv[]) {
|
||||||
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());
|
||||||
auto logLevels = vector<LogLevel>(getEnumValues<LogLevel>());
|
auto logLevels = vector<logging::Level>(getEnumValues<logging::Level>());
|
||||||
tclap::ValuesConstraint<LogLevel> logLevelConstraint(logLevels);
|
tclap::ValuesConstraint<logging::Level> logLevelConstraint(logLevels);
|
||||||
tclap::ValueArg<LogLevel> logLevel("", "logLevel", "The minimum log level to log", false, LogLevel::Debug, &logLevelConstraint, cmd);
|
tclap::ValueArg<logging::Level> logLevel("", "logLevel", "The minimum log level to log", false, logging::Level::Debug, &logLevelConstraint, cmd);
|
||||||
tclap::ValueArg<string> logFileName("", "logFile", "The log file path.", false, string(), "string", 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::ValueArg<string> dialog("d", "dialog", "The text of the dialog.", false, string(), "string", cmd);
|
||||||
auto exportFormats = vector<ExportFormat>(getEnumValues<ExportFormat>());
|
auto exportFormats = vector<ExportFormat>(getEnumValues<ExportFormat>());
|
||||||
|
|
|
@ -72,7 +72,7 @@ Timeline<Shape> animate(const Timeline<Phone> &phones) {
|
||||||
for (auto& timedPhone : phones) {
|
for (auto& timedPhone : phones) {
|
||||||
Timed<Shape> timedShape(static_cast<TimeRange>(timedPhone), getShape(timedPhone.getValue()));
|
Timed<Shape> timedShape(static_cast<TimeRange>(timedPhone), getShape(timedPhone.getValue()));
|
||||||
shapes.set(timedShape);
|
shapes.set(timedShape);
|
||||||
logTimedEvent("shape", timedShape);
|
logging::logTimedEvent("shape", timedShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
return shapes;
|
return shapes;
|
||||||
|
|
|
@ -98,18 +98,18 @@ void processAudioStream(AudioStream& audioStream16kHz, function<void(const vecto
|
||||||
} while (buffer.size());
|
} while (buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
LogLevel ConvertSphinxErrorLevel(err_lvl_t errorLevel) {
|
logging::Level ConvertSphinxErrorLevel(err_lvl_t errorLevel) {
|
||||||
switch (errorLevel) {
|
switch (errorLevel) {
|
||||||
case ERR_DEBUG:
|
case ERR_DEBUG:
|
||||||
case ERR_INFO:
|
case ERR_INFO:
|
||||||
case ERR_INFOCONT:
|
case ERR_INFOCONT:
|
||||||
return LogLevel::Trace;
|
return logging::Level::Trace;
|
||||||
case ERR_WARN:
|
case ERR_WARN:
|
||||||
return LogLevel::Warning;
|
return logging::Level::Warn;
|
||||||
case ERR_ERROR:
|
case ERR_ERROR:
|
||||||
return LogLevel::Error;
|
return logging::Level::Error;
|
||||||
case ERR_FATAL:
|
case ERR_FATAL:
|
||||||
return LogLevel::Fatal;
|
return logging::Level::Fatal;
|
||||||
default:
|
default:
|
||||||
throw invalid_argument("Unknown log level.");
|
throw invalid_argument("Unknown log level.");
|
||||||
}
|
}
|
||||||
|
@ -137,8 +137,8 @@ void sphinxLogCallback(void* user_data, err_lvl_t errorLevel, const char* format
|
||||||
string message(chars.data());
|
string message(chars.data());
|
||||||
boost::algorithm::trim(message);
|
boost::algorithm::trim(message);
|
||||||
|
|
||||||
LogLevel logLevel = ConvertSphinxErrorLevel(errorLevel);
|
logging::Level logLevel = ConvertSphinxErrorLevel(errorLevel);
|
||||||
LOG(logLevel) << message;
|
logging::log(logLevel, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> recognizeWords(unique_ptr<AudioStream> audioStream, ps_decoder_t& recognizer, ProgressSink& progressSink) {
|
vector<string> recognizeWords(unique_ptr<AudioStream> audioStream, ps_decoder_t& recognizer, ProgressSink& progressSink) {
|
||||||
|
@ -169,7 +169,7 @@ vector<string> recognizeWords(unique_ptr<AudioStream> audioStream, ps_decoder_t&
|
||||||
|
|
||||||
int firstFrame, lastFrame;
|
int firstFrame, lastFrame;
|
||||||
ps_seg_frames(it, &firstFrame, &lastFrame);
|
ps_seg_frames(it, &firstFrame, &lastFrame);
|
||||||
logTimedEvent("word", centiseconds(firstFrame), centiseconds(lastFrame + 1), word);
|
logging::logTimedEvent("word", centiseconds(firstFrame), centiseconds(lastFrame + 1), word);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -278,7 +278,7 @@ Timeline<Phone> getPhoneAlignment(const vector<s3wid_t>& wordIds, unique_ptr<Aud
|
||||||
Timed<Phone> timedPhone(start, start + duration, parseEnum<Phone>(phoneName));
|
Timed<Phone> timedPhone(start, start + duration, parseEnum<Phone>(phoneName));
|
||||||
result.set(timedPhone);
|
result.set(timedPhone);
|
||||||
|
|
||||||
logTimedEvent("phone", timedPhone);
|
logging::logTimedEvent("phone", timedPhone);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::chrono::duration;
|
using std::chrono::duration;
|
||||||
|
@ -8,3 +9,14 @@ using std::chrono::duration;
|
||||||
string formatDuration(duration<double> seconds) {
|
string formatDuration(duration<double> seconds) {
|
||||||
return fmt::format("{0:.2f}", seconds.count());
|
return fmt::format("{0:.2f}", seconds.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string formatTime(time_t time, const string& format) {
|
||||||
|
tm* timeInfo = localtime(&time);
|
||||||
|
std::vector<char> buffer(20);
|
||||||
|
bool success = false;
|
||||||
|
while (!success) {
|
||||||
|
success = strftime(buffer.data(), buffer.size(), format.c_str(), timeInfo) != 0;
|
||||||
|
if (!success) buffer.resize(buffer.size() * 2);
|
||||||
|
}
|
||||||
|
return string(buffer.data());
|
||||||
|
}
|
||||||
|
|
|
@ -10,3 +10,5 @@ template<typename T>
|
||||||
using lambda_unique_ptr = std::unique_ptr<T, std::function<void(T*)>>;
|
using lambda_unique_ptr = std::unique_ptr<T, std::function<void(T*)>>;
|
||||||
|
|
||||||
std::string formatDuration(std::chrono::duration<double> seconds);
|
std::string formatDuration(std::chrono::duration<double> seconds);
|
||||||
|
|
||||||
|
std::string formatTime(time_t time, const std::string& format);
|
Loading…
Reference in New Issue