feat(app): add interactive logger configuration and ownership transfer
This commit is contained in:
@@ -13,6 +13,9 @@ namespace app {
|
|||||||
* LoggerWorker получает сообщения из MessageQueue и передаёт их
|
* LoggerWorker получает сообщения из MessageQueue и передаёт их
|
||||||
* в библиотеку Logger для записи в файл.
|
* в библиотеку Logger для записи в файл.
|
||||||
*
|
*
|
||||||
|
* Logger передаётся в worker по значению и перемещается внутрь объекта.
|
||||||
|
* LoggerWorker становится владельцем логгера.
|
||||||
|
*
|
||||||
* Объект Logger используется только внутри рабочего потока,
|
* Объект Logger используется только внутри рабочего потока,
|
||||||
* поэтому потокобезопасность Logger не требуется.
|
* поэтому потокобезопасность Logger не требуется.
|
||||||
*/
|
*/
|
||||||
@@ -21,10 +24,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Создаёт worker для записи сообщений.
|
* @brief Создаёт worker для записи сообщений.
|
||||||
*
|
*
|
||||||
|
* Переданный Logger перемещается внутрь объекта LoggerWorker.
|
||||||
|
*
|
||||||
* @param logger Логгер, используемый для записи.
|
* @param logger Логгер, используемый для записи.
|
||||||
* @param queue Очередь сообщений.
|
* @param queue Очередь сообщений.
|
||||||
*/
|
*/
|
||||||
LoggerWorker(logger::Logger &logger, MessageQueue &queue);
|
LoggerWorker(logger::Logger logger, MessageQueue &queue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Останавливает поток записи.
|
* @brief Останавливает поток записи.
|
||||||
@@ -44,11 +49,45 @@ public:
|
|||||||
*/
|
*/
|
||||||
LoggerWorker &operator=(const LoggerWorker &) = delete;
|
LoggerWorker &operator=(const LoggerWorker &) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Разрешает перемещение worker.
|
||||||
|
*
|
||||||
|
* Передаёт владение потоком записи и состоянием объекта.
|
||||||
|
*/
|
||||||
|
LoggerWorker(LoggerWorker &&) noexcept = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Разрешает перемещающее присваивание worker.
|
||||||
|
*/
|
||||||
|
LoggerWorker &operator=(LoggerWorker &&) noexcept = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Запускает поток записи сообщений.
|
* @brief Запускает поток записи сообщений.
|
||||||
*/
|
*/
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Возвращает используемый логгер.
|
||||||
|
*
|
||||||
|
* Позволяет получить текущую конфигурацию логгера,
|
||||||
|
* например имя файла журнала или уровень логирования
|
||||||
|
* по умолчанию.
|
||||||
|
*
|
||||||
|
* @return Константная ссылка на логгер.
|
||||||
|
*/
|
||||||
|
[[nodiscard]]
|
||||||
|
const logger::Logger &getLogger() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Устанавливает новый логгер.
|
||||||
|
*
|
||||||
|
* Новый Logger заменяет текущий.
|
||||||
|
* Переданный объект перемещается внутрь worker.
|
||||||
|
*
|
||||||
|
* @param logger Новый логгер.
|
||||||
|
*/
|
||||||
|
void setLogger(logger::Logger logger);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Останавливает обработку сообщений.
|
* @brief Останавливает обработку сообщений.
|
||||||
*
|
*
|
||||||
@@ -70,7 +109,7 @@ private:
|
|||||||
*
|
*
|
||||||
* Используется только рабочим потоком.
|
* Используется только рабочим потоком.
|
||||||
*/
|
*/
|
||||||
logger::Logger &logger_;
|
logger::Logger logger_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Очередь входящих сообщений.
|
* @brief Очередь входящих сообщений.
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#include "logger_worker.hpp"
|
#include "logger_worker.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
||||||
LoggerWorker::LoggerWorker(logger::Logger &logger, MessageQueue &queue)
|
LoggerWorker::LoggerWorker(logger::Logger logger, MessageQueue &queue)
|
||||||
: logger_(logger), queue_(queue) {}
|
: logger_(std::move(logger)), queue_(queue) {}
|
||||||
|
|
||||||
LoggerWorker::~LoggerWorker() { stop(); }
|
LoggerWorker::~LoggerWorker() { stop(); }
|
||||||
|
|
||||||
@@ -21,6 +22,12 @@ void LoggerWorker::stop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const logger::Logger &LoggerWorker::getLogger() const { return logger_; }
|
||||||
|
|
||||||
|
void LoggerWorker::setLogger(logger::Logger logger) {
|
||||||
|
logger_ = std::move(logger);
|
||||||
|
}
|
||||||
|
|
||||||
void LoggerWorker::process() {
|
void LoggerWorker::process() {
|
||||||
while (auto message = queue_.pop()) {
|
while (auto message = queue_.pop()) {
|
||||||
auto status = logger_.writeMessage(message->level, message->message);
|
auto status = logger_.writeMessage(message->level, message->message);
|
||||||
|
|||||||
+192
-5
@@ -5,22 +5,209 @@
|
|||||||
#include "logger_worker.hpp"
|
#include "logger_worker.hpp"
|
||||||
#include "message_queue.hpp"
|
#include "message_queue.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void printMainMenu() {
|
||||||
|
std::cout << "\n*** Logger ***\n"
|
||||||
|
<< " 1: [w]rite message\n"
|
||||||
|
<< " 2: [c]onfigure\n"
|
||||||
|
<< " 3: [q]uit\n"
|
||||||
|
<< "What now> ";
|
||||||
|
}
|
||||||
|
|
||||||
|
void printConfigureMenu() {
|
||||||
|
std::cout << "\n*** Configure ***\n"
|
||||||
|
<< " 1: change [d]efault level\n"
|
||||||
|
<< " 2: change [c]urrent level\n"
|
||||||
|
<< " 3: [b]ack\n"
|
||||||
|
<< "What now> ";
|
||||||
|
}
|
||||||
|
|
||||||
|
void printWriteMenu() {
|
||||||
|
std::cout << "\n*** Write Message ***\n"
|
||||||
|
<< " 1: use [d]efault level\n"
|
||||||
|
<< " 2: use [c]urrent level\n"
|
||||||
|
<< " 3: [b]ack\n"
|
||||||
|
<< "What now> ";
|
||||||
|
}
|
||||||
|
|
||||||
|
void printLogLevelMenu(const std::string &title,
|
||||||
|
logger::LogLevel currentLevel) {
|
||||||
|
std::cout << "\n*** " << title << " ***\n"
|
||||||
|
<< "\nCurrent: " << currentLevel.toString() << "\n\n"
|
||||||
|
<< " 1: [d]ebug\n"
|
||||||
|
<< " 2: [i]nfo\n"
|
||||||
|
<< " 3: [e]rror\n"
|
||||||
|
<< " 4: [b]ack\n"
|
||||||
|
<< "Select level> ";
|
||||||
|
}
|
||||||
|
|
||||||
|
char readCommand() {
|
||||||
|
std::string command;
|
||||||
|
std::getline(std::cin, command);
|
||||||
|
|
||||||
|
return command.empty() ? '\0' : command.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
logger::Logger logger("app.log", logger::LogLevel::info());
|
logger::Logger logger("app.log", logger::LogLevel::info());
|
||||||
|
|
||||||
app::MessageQueue queue;
|
app::MessageQueue queue;
|
||||||
app::LoggerWorker worker(logger, queue);
|
app::LoggerWorker worker(std::move(logger), queue);
|
||||||
|
|
||||||
worker.start();
|
worker.start();
|
||||||
|
|
||||||
std::string message;
|
logger::LogLevel currentLevel = logger::LogLevel::info();
|
||||||
|
|
||||||
|
bool running = true;
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
printMainMenu();
|
||||||
|
|
||||||
|
switch (readCommand()) {
|
||||||
|
case 'w': {
|
||||||
|
bool writing = true;
|
||||||
|
|
||||||
|
while (writing) {
|
||||||
|
printWriteMenu();
|
||||||
|
|
||||||
|
std::optional<logger::LogLevel> level;
|
||||||
|
|
||||||
|
switch (readCommand()) {
|
||||||
|
case 'd':
|
||||||
|
level = worker.getLogger().getLogLevel();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
level = currentLevel;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
writing = false;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "Unknown command.\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Message> ";
|
||||||
|
|
||||||
|
std::string message;
|
||||||
|
std::getline(std::cin, message);
|
||||||
|
|
||||||
|
queue.push({*level, message});
|
||||||
|
|
||||||
|
writing = false;
|
||||||
|
}
|
||||||
|
|
||||||
while (std::getline(std::cin, message)) {
|
|
||||||
if (message == "exit") {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
queue.push({logger::LogLevel::info(), message});
|
case 'c': {
|
||||||
|
bool configuring = true;
|
||||||
|
|
||||||
|
while (configuring) {
|
||||||
|
printConfigureMenu();
|
||||||
|
|
||||||
|
switch (readCommand()) {
|
||||||
|
case 'd': {
|
||||||
|
bool selecting = true;
|
||||||
|
|
||||||
|
while (selecting) {
|
||||||
|
printLogLevelMenu("Default Log Level",
|
||||||
|
worker.getLogger().getLogLevel());
|
||||||
|
|
||||||
|
switch (readCommand()) {
|
||||||
|
case 'd':
|
||||||
|
worker.setLogger(
|
||||||
|
worker.getLogger().withLogLevel(logger::LogLevel::debug()));
|
||||||
|
selecting = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
worker.setLogger(
|
||||||
|
worker.getLogger().withLogLevel(logger::LogLevel::info()));
|
||||||
|
selecting = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
worker.setLogger(
|
||||||
|
worker.getLogger().withLogLevel(logger::LogLevel::error()));
|
||||||
|
selecting = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
selecting = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "Unknown command.\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'c': {
|
||||||
|
bool selecting = true;
|
||||||
|
|
||||||
|
while (selecting) {
|
||||||
|
printLogLevelMenu("Current Log Level", currentLevel);
|
||||||
|
|
||||||
|
switch (readCommand()) {
|
||||||
|
case 'd':
|
||||||
|
currentLevel = logger::LogLevel::debug();
|
||||||
|
selecting = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
currentLevel = logger::LogLevel::info();
|
||||||
|
selecting = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
currentLevel = logger::LogLevel::error();
|
||||||
|
selecting = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
selecting = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "Unknown command.\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
configuring = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "Unknown command.\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "Unknown command.\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
worker.stop();
|
worker.stop();
|
||||||
|
|||||||
@@ -49,14 +49,18 @@ public:
|
|||||||
Logger &operator=(const Logger &) = delete;
|
Logger &operator=(const Logger &) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Запрещает перемещение Logger.
|
* @brief Разрешает перемещение Logger.
|
||||||
|
*
|
||||||
|
* Передаёт владение ресурсами новому объекту.
|
||||||
*/
|
*/
|
||||||
Logger(Logger &&) = delete;
|
Logger(Logger &&) noexcept = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Запрещает перемещающее присваивание.
|
* @brief Разрешает перемещающее присваивание.
|
||||||
|
*
|
||||||
|
* Передаёт владение ресурсами новому объекту.
|
||||||
*/
|
*/
|
||||||
Logger &operator=(Logger &&) = delete;
|
Logger &operator=(Logger &&) noexcept = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Записывает сообщение в журнал с указанным уровнем логирования.
|
* @brief Записывает сообщение в журнал с указанным уровнем логирования.
|
||||||
|
|||||||
Reference in New Issue
Block a user