//--------------------------------------------------------------------------- #include "logger.h" #include "stdTools.h" #include #include #include #include #include #include #include //--------------------------------------------------------------------------- Logger::Logger(std::string fileName){ this->fileName = fileName; this->stop = false; std::string folder = Utility::BeforeLast(fileName,Utility::separator()); if (!Utility::createFolder(folder)) { std::cerr << "Error create folder: " << folder << std::endl; } openLogFile(); logThread = std::thread(&Logger::processQueue, this); }; //--------------------------------------------------------------------------- Logger::~Logger() { { std::unique_lock lock(queueMutex); stop = true; } queueCondition.notify_all(); logThread.join(); }; //--------------------------------------------------------------------------- //Сервисная функция std::string Logger::getCurrentDateTime() { std::time_t now = std::time(nullptr); std::tm* nowTm = std::localtime(&now); std::ostringstream timeStream; timeStream << std::put_time(nowTm, "%Y-%m-%dT%H:%M:%S"); return timeStream.str(); } //--------------------------------------------------------------------------- void Logger::log(std::string thread, std::string level, std::string data, bool cout) { { std::unique_lock lock(queueMutex); LogRec rec; rec.thread = thread; rec.level = level; rec.data = data; rec.cout = cout; logQueue.push(rec); } queueCondition.notify_one(); } //--------------------------------------------------------------------------- void Logger::processQueue() { while (true) { { std::unique_lock lock(queueMutex); queueCondition.wait(lock, [this] { return !logQueue.empty() || stop; }); if (stop && logQueue.empty()){ break; } //Пытаемся переименовать файл если он существует auto now = std::chrono::system_clock::now(); std::time_t now_c = std::chrono::system_clock::to_time_t(now); std::tm* now_tm = std::localtime(&now_c); // Проверяем, нужно ли переименовать файл if (lastWriteTime != 0 && (now_c - lastWriteTime) >= 86400) { if(std::filesystem::exists(fileName)){ if(file.is_open()) { file.close(); } char buffer[11]; // Длина строки "YYYY-MM-DD" + '\0' std::memset(buffer, 0, sizeof(buffer)); std::strftime(buffer, sizeof(buffer), "%Y-%m-%d", now_tm); std::ostringstream newFileName; newFileName << Utility::BeforeLast(fileName,'.') << "_" << buffer << "." << Utility::AfterLast(fileName,'.'); std::string newName = newFileName.str(); if(std::filesystem::exists(newName)){ //Не знаю по какой причине если файл существует... std::ostringstream newFileName; newFileName << Utility::BeforeLast(fileName,'.') << "_" << buffer << "_" << now_c << "." << Utility::AfterLast(fileName,'.'); newName = newFileName.str(); } try { std::filesystem::rename(fileName, newName); } catch (const std::filesystem::filesystem_error& e) { std::cerr << "Error renaming file: " << e.what() << std::endl; } //Удаляю старые файлы std::string folder = Utility::BeforeLast(fileName,Utility::separator()); Utility::deleteOldFiles(folder,10); } } //Записываю лог в файл if(!logQueue.empty()){ LogRec rec = std::move(logQueue.front()); logQueue.pop(); writeLog(rec.thread,rec.level,rec.data,rec.cout); } } } } //--------------------------------------------------------------------------- void Logger::openLogFile() { file.open(fileName, std::ios::out | std::ios::app); if (!file.is_open()) { std::cerr << "Error open file: " << fileName << std::endl; } } //--------------------------------------------------------------------------- void Logger::writeLog(std::string thread, std::string level, std::string data, bool cout) { if (!file.is_open()){ openLogFile(); } //Записываем лог if (file.is_open()) { std::stringstream str(std::stringstream::out | std::stringstream::binary); std::string dateTime = getCurrentDateTime(); thread = Utility::escape_json(thread); level = Utility::escape_json(level); data = Utility::escape_json(data); str << "{\"timestamp\":\"" << dateTime << "\", \"thread\":\"" <