|
|
|
#ifndef LOGGER_HPP_INCLUDED
|
|
|
|
#define LOGGER_HPP_INCLUDED
|
|
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
#include <iostream>
|
|
|
|
#include <stack>
|
|
|
|
#include <map>
|
|
|
|
#include <cassert>
|
|
|
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
|
|
|
|
|
|
|
extern int verbose;
|
|
|
|
|
|
|
|
#define LogDebug(s, ...) \
|
|
|
|
if ( verbose >= 3 ) printf(s, ##__VA_ARGS__);
|
|
|
|
|
|
|
|
#define LogMoreInfo(s, ...) \
|
|
|
|
if ( verbose >= 2 ) printf(s, ##__VA_ARGS__);
|
|
|
|
|
|
|
|
#define LogInfo(s, ...) \
|
|
|
|
if ( verbose >= 1 ) printf(s, ##__VA_ARGS__);
|
|
|
|
|
|
|
|
#define LogError(s, ...) \
|
|
|
|
if ( verbose >= 0 ) { printf("%s, %s(), %d: ", __FILE__, __func__, __LINE__); printf(s, ##__VA_ARGS__); }
|
|
|
|
|
|
|
|
enum LoggingLevels {
|
|
|
|
LOG_ERROR,
|
|
|
|
LOG_INFO,
|
|
|
|
LOG_VERBOSE,
|
|
|
|
LOG_DEBUG
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Imported from Astrant:
|
|
|
|
Questions/Suggestions mail nick@astrant.net
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct LoggingBase {
|
|
|
|
protected:
|
|
|
|
LoggingBase(std::ostream & out, LoggingLevels level)
|
|
|
|
: out(out)
|
|
|
|
, level(level)
|
|
|
|
{}
|
|
|
|
|
|
|
|
bool shouldSkip(){
|
|
|
|
return verbose < level;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream & out;
|
|
|
|
LoggingLevels level;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Logger : public LoggingBase {
|
|
|
|
Logger(std::ostream& logging_stream_, LoggingLevels level, std::string prefix_ = "")
|
|
|
|
: LoggingBase(logging_stream_, level)
|
|
|
|
, prefix(prefix_)
|
|
|
|
{}
|
|
|
|
|
|
|
|
void log(std::string what){
|
|
|
|
if (shouldSkip()) return;
|
|
|
|
out << get_prefix() << "(" << what << ") took place at (" << boost::posix_time::microsec_clock::local_time() << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void start(std::string what){
|
|
|
|
if (shouldSkip()) return;
|
|
|
|
Event e;
|
|
|
|
e.start = boost::posix_time::microsec_clock::local_time();
|
|
|
|
e.name = what;
|
|
|
|
|
|
|
|
EventMap::iterator it = event_map.find(what);
|
|
|
|
if(it != event_map.end()){
|
|
|
|
out << get_prefix() << "WARNING: Overwriting event(" << e.name << "), did you forget to call stop()?";
|
|
|
|
} else {
|
|
|
|
event_name_stack.push(what);
|
|
|
|
}
|
|
|
|
|
|
|
|
event_map.insert(it, std::make_pair(what, e));
|
|
|
|
}
|
|
|
|
|
|
|
|
void stop() {
|
|
|
|
if (shouldSkip()) return;
|
|
|
|
assert(!event_name_stack.empty());
|
|
|
|
stop(event_name_stack.top());
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void stop(std::string what){
|
|
|
|
EventMap::iterator it = event_map.find(what);
|
|
|
|
if(it == event_map.end()){
|
|
|
|
out << get_prefix() << "WARNING: No such, or already stopped, event(" << what << "), did you forget to call start()?";
|
|
|
|
} else {
|
|
|
|
it->second.end = boost::posix_time::microsec_clock::local_time();
|
|
|
|
log_event(it->second);
|
|
|
|
event_map.erase(it);
|
|
|
|
}
|
|
|
|
|
|
|
|
event_name_stack.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Event {
|
|
|
|
boost::posix_time::ptime start;
|
|
|
|
boost::posix_time::ptime end;
|
|
|
|
std::string name;
|
|
|
|
};
|
|
|
|
|
|
|
|
// A map containing strings -> Event, used by start() and stop()
|
|
|
|
typedef std::map<std::string, Event> EventMap;
|
|
|
|
EventMap event_map;
|
|
|
|
|
|
|
|
// A stack used by 0-parameter stop() to stop the last start()ed event.
|
|
|
|
std::stack<std::string> event_name_stack;
|
|
|
|
|
|
|
|
std::string prefix;
|
|
|
|
|
|
|
|
void log_event(Event const& e){
|
|
|
|
out << get_prefix() << "Event(" << e.name << ") started at (" << e.start << ") ended at (" << e.end << ") duration (" << e.end - e.start << " ms) " << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string get_prefix() const {
|
|
|
|
if(prefix == std::string("")){
|
|
|
|
return prefix;
|
|
|
|
} else {
|
|
|
|
return prefix + ": ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
My progressbar class (as seen on github)
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct Progressbar : public LoggingBase {
|
|
|
|
Progressbar(std::ostream & out, LoggingLevels level, std::string prefix = "")
|
|
|
|
: LoggingBase(out, level)
|
|
|
|
, prefix(prefix)
|
|
|
|
{
|
|
|
|
if (shouldSkip()) return;
|
|
|
|
show(0, 1, ' ');
|
|
|
|
}
|
|
|
|
|
|
|
|
~Progressbar(){
|
|
|
|
if (shouldSkip()) return;
|
|
|
|
show(1, 1, '=');
|
|
|
|
out << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void show(T const & progress, T const & max, char delim = '>'){
|
|
|
|
if (shouldSkip()) return;
|
|
|
|
out << "\r";
|
|
|
|
|
|
|
|
size_t width = 79; // default terminal size :D
|
|
|
|
width -= prefix.size();
|
|
|
|
width -= 3; // [, > and ]
|
|
|
|
|
|
|
|
if (prefix != "") {
|
|
|
|
width -= 1;
|
|
|
|
out << prefix << ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
double ratio = (double) progress / (double) max;
|
|
|
|
size_t length = width * ratio;
|
|
|
|
|
|
|
|
std::string fill(length, '=');
|
|
|
|
std::string empty(width - length, ' ');
|
|
|
|
out << '[' << fill << delim << empty << ']' << std::flush;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::string prefix;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ProgressIndicator : public LoggingBase {
|
|
|
|
ProgressIndicator(std::ostream & out, LoggingLevels level, std::string prefix = "")
|
|
|
|
: LoggingBase(out, level)
|
|
|
|
, prefix(prefix)
|
|
|
|
, wave("`*-,_,-*`")
|
|
|
|
, previous_time(boost::posix_time::microsec_clock::local_time() - boost::posix_time::seconds(1.0))
|
|
|
|
, progress(0)
|
|
|
|
{
|
|
|
|
show();
|
|
|
|
}
|
|
|
|
|
|
|
|
~ProgressIndicator(){
|
|
|
|
show("=");
|
|
|
|
out << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void show(std::string const & alt_wave = ""){
|
|
|
|
if (shouldSkip()) return;
|
|
|
|
|
|
|
|
boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();
|
|
|
|
if(now - previous_time < boost::posix_time::milliseconds(50.0)) return;
|
|
|
|
|
|
|
|
out << "\r";
|
|
|
|
|
|
|
|
size_t width = 79; // default terminal size :D
|
|
|
|
width -= 2;
|
|
|
|
if(prefix != ""){
|
|
|
|
width -= prefix.size() + 1;
|
|
|
|
out << prefix << ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string const & wave_to_use = (alt_wave == "") ? wave : alt_wave;
|
|
|
|
out << '[';
|
|
|
|
for(unsigned int i = 0; i < width; ++i){
|
|
|
|
out << wave_to_use[(i + progress) % wave_to_use.size()];
|
|
|
|
}
|
|
|
|
out << ']' << std::flush;
|
|
|
|
|
|
|
|
previous_time = now;
|
|
|
|
++progress;
|
|
|
|
if(progress >= wave.size())
|
|
|
|
progress = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::string prefix;
|
|
|
|
std::string wave;
|
|
|
|
boost::posix_time::ptime previous_time;
|
|
|
|
unsigned int progress;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif // LOGGER_HPP_INCLUDED
|