Files
Tools_CPP/lib/logger.cpp
2024-11-01 12:23:13 +05:00

161 lines
5.6 KiB
C++
Raw 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);
// Ждем до 1 минуты или пока условие не выполнится
queueCondition.wait_for(lock, std::chrono::minutes(1), [this] { return !logQueue.empty() || stop; });
if (stop && logQueue.empty()){
break;
}
if(!logQueue.empty()){
LogRec rec = std::move(logQueue.front());
logQueue.pop();
writeLog(rec.thread,rec.level,rec.data,rec.cout);
}
//Всё что ниже для переименовывания старого файла
if(!std::filesystem::exists(fileName)){
continue;
}
// Получаем время создания файла (st_ctime)
struct stat fileInfo;
if (stat(fileName.c_str(), &fileInfo) != 0) {
std::cerr << "Error getting file info: " << fileName << std::endl;
continue;
}
std::time_t creationTime = fileInfo.st_ctime;
std::tm* creation_tm = std::localtime(&creationTime);
// Получаем текущее время
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( (now_tm->tm_year != creation_tm->tm_year) ||
(now_tm->tm_mon != creation_tm->tm_mon) ||
(now_tm->tm_mday != creation_tm->tm_mday)){
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", creation_tm);
std::ostringstream newFileName;
newFileName << Utility::BeforeLast(fileName,'.') << "_" << buffer << "." << Utility::AfterLast(fileName,'.');
std::string 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);
}
}
}
}
//---------------------------------------------------------------------------
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();
}
}
//---------------------------------------------------------------------------
//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();
//}
//---------------------------------------------------------------------------