Files
Tools_CPP/lib/logger.cpp
2024-11-06 19:45:13 +05:00

154 lines
5.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//---------------------------------------------------------------------------
#include "logger.h"
#include "stdTools.h"
#include <cstring>
#include <iomanip>
#include <ctime>
#include <iostream>
#include <sstream>
#include <filesystem>
#include <sys/stat.h>
//---------------------------------------------------------------------------
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<std::mutex> 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<std::mutex> 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<std::mutex> 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\":\"" <<thread<<"\", \"level\":\""<<level<<"\", \"message\":\"" << data <<"\"}" << std::endl;
if (cout)
std::cout << "[" << dateTime << "] " << data << std::endl; //Повтор лога в консоль
file.write(str.str().c_str(), str.str().length());
file.flush();
// Обновляем время последней записи
lastWriteTime = std::time(nullptr);
}
}
//---------------------------------------------------------------------------
//std::string Logger::getCurrentDate() {
// std::time_t now = std::time(nullptr);
// std::tm* nowTm = std::localtime(&now);
// std::ostringstream timeStream;
// timeStream << std::put_time(nowTm, "%Y-%m-%d");
// return timeStream.str();
//}
//---------------------------------------------------------------------------