PICout improvement:
* renamed private members for more clear code * registerExternalBufferID() method to obtain unique ID for withExternalBuffer() * PICoutManipulators::PICoutStdStream enum for select stream (stdout or stderr) * Constructors now accept optional stream * piCerr and piCerrObj macros PIDir::temporary() moved to "mkdtemp" PILog: * now 4 levels * you can set max level * Error writes to piCerr
This commit is contained in:
@@ -76,6 +76,10 @@ PILog::PILog(): PIThread(), log_ts(&log_file) {
|
||||
split_time = 8_h;
|
||||
timestamp_format = "yyyy-MM-dd hh:mm:ss.zzz";
|
||||
setLineFormat("t - c: m");
|
||||
id_by_cat[Level::Info] = PICout::registerExternalBufferID();
|
||||
id_by_cat[Level::Debug] = PICout::registerExternalBufferID();
|
||||
id_by_cat[Level::Warning] = PICout::registerExternalBufferID();
|
||||
id_by_cat[Level::Error] = PICout::registerExternalBufferID();
|
||||
CONNECTU(PICout::Notifier::object(), finished, this, coutDone);
|
||||
}
|
||||
|
||||
@@ -101,18 +105,28 @@ void PILog::setLineFormat(const PIString & f) {
|
||||
}
|
||||
|
||||
|
||||
PICout PILog::debug(PIObject * context) {
|
||||
return makePICout(context, Category::Debug);
|
||||
}
|
||||
|
||||
|
||||
PICout PILog::warning(PIObject * context) {
|
||||
return makePICout(context, Category::Warning);
|
||||
void PILog::setLevel(Level l) {
|
||||
max_level = l;
|
||||
}
|
||||
|
||||
|
||||
PICout PILog::error(PIObject * context) {
|
||||
return makePICout(context, Category::Error);
|
||||
return makePICout(context, Level::Error);
|
||||
}
|
||||
|
||||
|
||||
PICout PILog::warning(PIObject * context) {
|
||||
return makePICout(context, Level::Warning);
|
||||
}
|
||||
|
||||
|
||||
PICout PILog::info(PIObject * context) {
|
||||
return makePICout(context, Level::Info);
|
||||
}
|
||||
|
||||
|
||||
PICout PILog::debug(PIObject * context) {
|
||||
return makePICout(context, Level::Debug);
|
||||
}
|
||||
|
||||
|
||||
@@ -129,35 +143,27 @@ void PILog::stop() {
|
||||
|
||||
|
||||
void PILog::coutDone(int id, PIString * buffer) {
|
||||
cout_mutex.lock();
|
||||
if (!cout_cat_by_id.contains(id)) {
|
||||
cout_mutex.unlock();
|
||||
return;
|
||||
}
|
||||
auto cat = cout_cat_by_id.take(id, PILog::Category::Debug);
|
||||
cout_mutex.unlock();
|
||||
if (!buffer) return;
|
||||
if (!id_by_cat.containsValue(id)) return;
|
||||
auto cat = id_by_cat.key(id, PILog::Level::Debug);
|
||||
if (cat > max_level) return;
|
||||
enqueue(*buffer, cat);
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
|
||||
PICout PILog::makePICout(PIObject * context, Category cat) {
|
||||
cout_mutex.lock();
|
||||
int id = ++cout_id;
|
||||
auto buffer = new PIString();
|
||||
cout_cat_by_id[id] = cat;
|
||||
cout_mutex.unlock();
|
||||
PICout PILog::makePICout(PIObject * context, Level cat) {
|
||||
auto buffer = new PIString();
|
||||
if (context) {
|
||||
*buffer = "["_a + context->className();
|
||||
if (context->name().isNotEmpty()) *buffer += " \"" + context->name() + "\"";
|
||||
*buffer += "] ";
|
||||
}
|
||||
return PICout::withExternalBuffer(buffer, id, PICoutManipulators::AddSpaces);
|
||||
return PICout::withExternalBuffer(buffer, id_by_cat.value(cat), PICoutManipulators::AddSpaces);
|
||||
}
|
||||
|
||||
|
||||
void PILog::enqueue(const PIString & msg, Category cat) {
|
||||
void PILog::enqueue(const PIString & msg, Level cat) {
|
||||
if (log_file.isClosed()) return;
|
||||
auto t = PIDateTime::fromSystemTime(PISystemTime::current());
|
||||
PIMutexLocker ml(log_mutex);
|
||||
@@ -166,7 +172,7 @@ void PILog::enqueue(const PIString & msg, Category cat) {
|
||||
|
||||
|
||||
PIString PILog::entryToString(const Entry & e) const {
|
||||
static PIStringList categories{"debug", "warn ", "error"};
|
||||
static PIStringList categories{"error", "warn ", "info ", "debug"};
|
||||
PIString t = e.time.toString(timestamp_format);
|
||||
PIString ret = line_format_p;
|
||||
ret.replace("${t}", t).replace("${c}", categories[static_cast<int>(e.cat)]).replace("${m}", e.msg);
|
||||
@@ -175,7 +181,7 @@ PIString PILog::entryToString(const Entry & e) const {
|
||||
|
||||
|
||||
void PILog::newFile() {
|
||||
PIString aname = app_name;
|
||||
PIString aname = log_name;
|
||||
if (aname.isNotEmpty()) aname += "__";
|
||||
log_file.open(log_dir + "/" + aname + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss") + ".log." +
|
||||
PIString::fromNumber(++part_number),
|
||||
@@ -205,6 +211,9 @@ void PILog::run() {
|
||||
log_mutex.unlock();
|
||||
auto str = entryToString(qi);
|
||||
log_ts << str << "\n";
|
||||
piCout << str;
|
||||
if (qi.cat == Level::Error)
|
||||
piCerr << str;
|
||||
else
|
||||
piCout << str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,11 +41,18 @@ public:
|
||||
PILog();
|
||||
~PILog();
|
||||
|
||||
enum class Level {
|
||||
Error,
|
||||
Warning,
|
||||
Info,
|
||||
Debug,
|
||||
};
|
||||
|
||||
//! \~english Returns prefix for filename.
|
||||
PIString applicationName() const { return app_name; }
|
||||
PIString logName() const { return log_name; }
|
||||
|
||||
//! \~english Set prefix for filename. Should be set \b before \a setDir()!
|
||||
void setApplicationName(const PIString & n) { app_name = n; }
|
||||
void setLogName(const PIString & n) { log_name = n; }
|
||||
|
||||
|
||||
//! \~english Returns directory for log files.
|
||||
@@ -75,27 +82,30 @@ public:
|
||||
//! \~english Set line format. "t" is timestamp, "c" is category and "m" is message. Default is "t - c: m".
|
||||
void setLineFormat(const PIString & f);
|
||||
|
||||
PICout debug(PIObject * context = nullptr);
|
||||
PICout warning(PIObject * context = nullptr);
|
||||
|
||||
//! \~english Returns maximum level.
|
||||
Level level() const { return max_level; }
|
||||
|
||||
//! \~english Set maximum level. All levels greater than \"l\" will be ignored. Default if \a Level::Debug.
|
||||
void setLevel(Level l);
|
||||
|
||||
|
||||
PICout error(PIObject * context = nullptr);
|
||||
PICout warning(PIObject * context = nullptr);
|
||||
PICout info(PIObject * context = nullptr);
|
||||
PICout debug(PIObject * context = nullptr);
|
||||
|
||||
//! \~english Write all queued lines and stop. Also called in destructor.
|
||||
void stop();
|
||||
|
||||
private:
|
||||
enum class Category {
|
||||
Debug,
|
||||
Warning,
|
||||
Error
|
||||
};
|
||||
|
||||
EVENT_HANDLER2(void, coutDone, int, id, PIString *, buff);
|
||||
|
||||
PICout makePICout(PIObject * context, Category cat);
|
||||
void enqueue(const PIString & msg, Category cat = Category::Debug);
|
||||
PICout makePICout(PIObject * context, Level cat);
|
||||
void enqueue(const PIString & msg, Level cat = Level::Debug);
|
||||
|
||||
struct Entry {
|
||||
Category cat;
|
||||
Level cat;
|
||||
PIDateTime time;
|
||||
PIString msg;
|
||||
};
|
||||
@@ -104,14 +114,15 @@ private:
|
||||
void newFile();
|
||||
void run() override;
|
||||
|
||||
PIMutex log_mutex, cout_mutex;
|
||||
PIMutex log_mutex;
|
||||
PIFile log_file;
|
||||
PIIOTextStream log_ts;
|
||||
PITimeMeasurer split_tm;
|
||||
PISystemTime split_time;
|
||||
PIString log_dir, timestamp_format, line_format, line_format_p, app_name;
|
||||
PIString log_dir, timestamp_format, line_format, line_format_p, log_name;
|
||||
PIQueue<Entry> queue;
|
||||
PIMap<int, Category> cout_cat_by_id;
|
||||
PIMap<Level, int> id_by_cat;
|
||||
Level max_level = Level::Debug;
|
||||
int part_number = -1, cout_id = -1;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user