diff --git a/libs/main/application/pilog.cpp b/libs/main/application/pilog.cpp
new file mode 100644
index 00000000..7a47a462
--- /dev/null
+++ b/libs/main/application/pilog.cpp
@@ -0,0 +1,128 @@
+/*
+ PIP - Platform Independent Primitives
+ High-level log
+ Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#include "pilog.h"
+
+#include "pidir.h"
+#include "piliterals_time.h"
+#include "pitime.h"
+
+
+//! \class PILog pilog.h
+//! \details
+//! \~english \section PILog_sec0 Synopsis
+//! \~russian \section PILog_sec0 Краткий обзор
+//! \~english
+//! This class provide handy parsing of command-line arguments. First you should add
+//! arguments to %PICLI with function \a addArgument(). Then you can check if there
+//! is some argument in application command-line with function \a hasArgument(),
+//! or obtain argument value by \a argumentValue().
+//!
+//! \~russian
+//! Этот класс предоставляет удобный механизм для разбора аргументов командной строки.
+//! Сперва необходимо добавить аргументы в %PICLI с помощью методов \a addArgument().
+//! Далее можно проверять аргументы на наличие в командной строке методом \a hasArgument(),
+//! а также получать их значения при помощи \a argumentValue().
+//!
+//! \~english \section PICLI_sec1 Example
+//! \~russian \section PICLI_sec1 Пример
+//! \~\code
+//! int main(int argc, char ** argv) {
+//! PICLI cli(argc, argv);
+//! cli.addArgument("console");
+//! cli.addArgument("debug");
+//! cli.addArgument("Value", "v", "value", true);
+//! if (cli.hasArgument("console"))
+//! piCout << "console active";
+//! if (cli.hasArgument("debug"))
+//! piCout << "debug active";
+//! piCout << "Value =" << cli.argumentValue("Value");
+//! return 0;
+//! }
+//! \endcode
+//!
+//! \~english These executions are similar:
+//! \~russian Эти вызовы будут идентичны:
+//!
+//! \~\code
+//! a.out -cd -v 10
+//! a.out --value 10 -dc
+//! a.out -c -v 10 -d
+//! a.out --console -d -v 10
+//! a.out --debug -c --value 10
+//! \endcode
+//!
+
+
+PILog::PILog(): PIThread(), log_ts(&log_file) {
+ split_time = 8_h;
+}
+
+
+PILog::~PILog() {
+ stopAndWait();
+}
+
+
+void PILog::setDir(const PIString & d) {
+ stopAndWait();
+ log_dir = d;
+ PIDir::make(log_dir);
+ newFile();
+ start();
+}
+
+
+void PILog::enqueue(const PIString & msg) {
+ if (log_file.isClosed()) return;
+ auto cur_dt = PIDateTime::fromSystemTime(PISystemTime::current());
+ PIMutexLocker ml(log_mutex);
+ queue.enqueue(cur_dt.toString("hh:mm:ss.zzz") + " - " + msg);
+}
+
+
+void PILog::newFile() {
+ log_file.open(log_dir + "/" + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss__p" + PIString::fromNumber(++part_number) + ".txt"),
+ PIIODevice::ReadWrite);
+}
+
+
+void PILog::run() {
+ if (split_tm.elapsed() >= split_time) {
+ split_tm.reset();
+ newFile();
+ }
+ log_mutex.lock();
+ if (queue.isEmpty()) {
+ log_mutex.unlock();
+ piMSleep(20);
+ return;
+ }
+ log_mutex.unlock();
+ while (true) {
+ log_mutex.lock();
+ if (queue.isEmpty()) {
+ log_mutex.unlock();
+ return;
+ }
+ auto qi = queue.dequeue();
+ log_mutex.unlock();
+ log_ts << qi << "\n";
+ }
+}
diff --git a/libs/main/application/pilog.h b/libs/main/application/pilog.h
new file mode 100644
index 00000000..14445ef3
--- /dev/null
+++ b/libs/main/application/pilog.h
@@ -0,0 +1,66 @@
+/*! \file pilog.h
+ * \ingroup Application
+ * \~\brief
+ * \~english High-level log
+ * \~russian Высокоуровневый лог
+ */
+/*
+ PIP - Platform Independent Primitives
+ High-level log
+ Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef PIlog_H
+#define PIlog_H
+
+#include "pifile.h"
+#include "piiostream.h"
+#include "pithread.h"
+
+//! \ingroup Application
+//! \~\brief
+//! \~english High-level log
+//! \~russian Высокоуровневый лог
+class PIP_EXPORT PILog: public PIThread {
+ PIOBJECT_SUBCLASS(PILog, PIThread)
+
+public:
+ PILog();
+ ~PILog();
+
+ PIString dir() const { return log_dir; }
+ void setDir(const PIString & d);
+
+ PISystemTime splitTime() const { return split_time; }
+ void setSplitTime(PISystemTime st) { split_time = st; }
+
+ void enqueue(const PIString & msg);
+
+private:
+ void newFile();
+ void run() override;
+
+ PIMutex log_mutex;
+ PIFile log_file;
+ PIIOTextStream log_ts;
+ PITimeMeasurer split_tm;
+ PISystemTime split_time;
+ PIString log_dir;
+ PIQueue queue;
+ int part_number = -1;
+};
+
+#endif
diff --git a/libs/main/pip.h b/libs/main/pip.h
index a5018103..297f31d6 100644
--- a/libs/main/pip.h
+++ b/libs/main/pip.h
@@ -20,6 +20,7 @@
#ifndef PIP_H
#define PIP_H
+#include "piapplicationmodule.h"
#include "picloudmodule.h"
#include "piconsolemodule.h"
#include "picontainersmodule.h"
diff --git a/libs/main/types/pisystemtime.cpp b/libs/main/types/pisystemtime.cpp
index abf8c258..eaa7f8fc 100644
--- a/libs/main/types/pisystemtime.cpp
+++ b/libs/main/types/pisystemtime.cpp
@@ -117,6 +117,11 @@ void PISystemTime::toTimespec(void * ts) {
}
+PISystemTime::Frequency PISystemTime::toFrequency() {
+ return PISystemTime::Frequency::fromSystemTime(*this);
+}
+
+
PIString PISystemTime::toString() const {
static const PISystemTime is_abs_thr = 3650._d; // 10 years
if ((*this) >= is_abs_thr) return PIDateTime::fromSystemTime((*this)).toString("yyyy-MM-dd hh:mm:ss.zzz");
diff --git a/libs/main/types/pisystemtime.h b/libs/main/types/pisystemtime.h
index 0fc0d7d2..e089b4b5 100644
--- a/libs/main/types/pisystemtime.h
+++ b/libs/main/types/pisystemtime.h
@@ -260,6 +260,10 @@ public:
//! \~russian На *nix системах присваивает время к timespec структуре
void toTimespec(void * ts);
+ //! \~english Returns \a Frequency that corresponds this time interval
+ //! \~russian Возвращает \a Frequency соответствующую этому временному интервалу
+ PISystemTime::Frequency toFrequency();
+
//! \~english Returns "yyyy-MM-dd hh:mm:ss.zzz" for absolute time and " ..." for relative
//! \~russian Возвращает "yyyy-MM-dd hh:mm:ss.zzz" для абсолютного времени и " ..." для относительного
PIString toString() const;