<commit_before>#include <algorithm>
#include <fstream>
#include <ctime>
#include <unordered_set>

#ifdef WIN32
#  define WIN32_LEAN_AND_MEAN
#  include <Windows.h>
#else
#  include <sys/stat.h>
#endif

#include "LogManager.hpp"
#include "Logger.hpp"
#include "SampConfigReader.hpp"
#include "LogConfigReader.hpp"
#include "crashhandler.hpp"
#include "amx/amx2.h"

#include <fmt/format.h>
#include <fmt/time.h>

using samplog::LogLevel;


const char *GetLogLevelAsString(LogLevel level)
{
	switch (level)
	{
		case LogLevel::DEBUG:
			return "DEBUG";
		case LogLevel::INFO:
			return "INFO";
		case LogLevel::WARNING:
			return "WARNING";
		case LogLevel::ERROR:
			return "ERROR";
		case LogLevel::FATAL:
			return "FATAL";
		case LogLevel::VERBOSE:
			return "VERBOSE";
	}
	return "<unknown>";
}

void WriteCallInfoString(Message_t const &msg, fmt::MemoryWriter &log_string)
{
	if (!msg->call_info.empty())
	{
		log_string << " (";
		bool first = true;
		for (auto const &ci : msg->call_info)
		{
			if (!first)
				log_string << " -> ";
			log_string << ci.file << ":" << ci.line;
			first = false;
		}
		log_string << ")";
	}
}

void CreateFolder(std::string foldername)
{
#ifdef WIN32
	std::replace(foldername.begin(), foldername.end(), '/', '\\');
	CreateDirectoryA(foldername.c_str(), NULL);
#else
	std::replace(foldername.begin(), foldername.end(), '\\', '/');
	mkdir(foldername.c_str(), ACCESSPERMS);
#endif
}


LogManager::LogManager() :
	m_ThreadRunning(true),
	m_DateTimeFormat("{:%x %X}")
{
	crashhandler::Install();

	std::string cfg_time_format;
	if (SampConfigReader::Get()->GetVar("logtimeformat", cfg_time_format))
	{
		//delete brackets
		size_t pos = 0;
		while ((pos = cfg_time_format.find_first_of("[]()")) != std::string::npos)
			cfg_time_format.erase(pos, 1);

		m_DateTimeFormat = "{:" + cfg_time_format + "}";
		// quickly test out the format string
		// will assert if invalid and on Windows
		fmt::format(m_DateTimeFormat, fmt::localtime(std::time(nullptr)));
	}

	LogConfigReader::Get()->Initialize();

	CreateFolder("logs");

	m_WarningLog.open("logs/warnings.log");
	m_ErrorLog.open("logs/errors.log");
	m_FatalLog.open("logs/fatals.log");

	m_Thread = new std::thread(std::bind(&LogManager::Process, this));
}

LogManager::~LogManager()
{
	{
		std::lock_guard<std::mutex> lg(m_QueueMtx);
		m_ThreadRunning = false;
	}
	m_QueueNotifier.notify_one();
	m_Thread->join();
	delete m_Thread;
}

void LogManager::RegisterLogger(Logger *logger)
{
	std::lock_guard<std::mutex> lg(m_LoggersMutex);
	m_Loggers.emplace(logger->GetModuleName(), logger);
}

void LogManager::UnregisterLogger(Logger *logger)
{<commit_msg>close loglevel logs<commit_after>#include <algorithm>
#include <fstream>
#include <ctime>
#include <unordered_set>

#ifdef WIN32
#  define WIN32_LEAN_AND_MEAN
#  include <Windows.h>
#else
#  include <sys/stat.h>
#endif

#include "LogManager.hpp"
#include "Logger.hpp"
#include "SampConfigReader.hpp"
#include "LogConfigReader.hpp"
#include "crashhandler.hpp"
#include "amx/amx2.h"

#include <fmt/format.h>
#include <fmt/time.h>

using samplog::LogLevel;


const char *GetLogLevelAsString(LogLevel level)
{
	switch (level)
	{
		case LogLevel::DEBUG:
			return "DEBUG";
		case LogLevel::INFO:
			return "INFO";
		case LogLevel::WARNING:
			return "WARNING";
		case LogLevel::ERROR:
			return "ERROR";
		case LogLevel::FATAL:
			return "FATAL";
		case LogLevel::VERBOSE:
			return "VERBOSE";
	}
	return "<unknown>";
}

void WriteCallInfoString(Message_t const &msg, fmt::MemoryWriter &log_string)
{
	if (!msg->call_info.empty())
	{
		log_string << " (";
		bool first = true;
		for (auto const &ci : msg->call_info)
		{
			if (!first)
				log_string << " -> ";
			log_string << ci.file << ":" << ci.line;
			first = false;
		}
		log_string << ")";
	}
}

void CreateFolder(std::string foldername)
{
#ifdef WIN32
	std::replace(foldername.begin(), foldername.end(), '/', '\\');
	CreateDirectoryA(foldername.c_str(), NULL);
#else
	std::replace(foldername.begin(), foldername.end(), '\\', '/');
	mkdir(foldername.c_str(), ACCESSPERMS);
#endif
}


LogManager::LogManager() :
	m_ThreadRunning(true),
	m_DateTimeFormat("{:%x %X}")
{
	crashhandler::Install();

	std::string cfg_time_format;
	if (SampConfigReader::Get()->GetVar("logtimeformat", cfg_time_format))
	{
		//delete brackets
		size_t pos = 0;
		while ((pos = cfg_time_format.find_first_of("[]()")) != std::string::npos)
			cfg_time_format.erase(pos, 1);

		m_DateTimeFormat = "{:" + cfg_time_format + "}";
		// quickly test out the format string
		// will assert if invalid and on Windows
		fmt::format(m_DateTimeFormat, fmt::localtime(std::time(nullptr)));
	}

	LogConfigReader::Get()->Initialize();

	CreateFolder("logs");

	m_WarningLog.open("logs/warnings.log");
	m_ErrorLog.open("logs/errors.log");
	m_FatalLog.open("logs/fatals.log");

	m_Thread = new std::thread(std::bind(&LogManager::Process, this));
}

LogManager::~LogManager()
{
	{
		std::lock_guard<std::mutex> lg(m_QueueMtx);
		m_ThreadRunning = false;
	}
	m_QueueNotifier.notify_one();
	m_Thread->join();
	delete m_Thread;

	m_WarningLog.close();
	m_ErrorLog.close();
	m_FatalLog.close();
}

void LogManager::RegisterLogger(Logger *logger)
{
	std::lock_guard<std::mutex> lg(m_LoggersMutex);
	m_Loggers.emplace(logger->GetModuleName(), logger);
}

void LogManager::UnregisterLogger(Logger *logger)
{
{'fraction_non_alphanumeric': 0.17383177570093458, 'fraction_numerical': 0.0033644859813084112, 'mean_word_length': 5.317591499409681, 'pattern_counts': {'":': 2, '<': 49, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1503407', 'n_tokens_mistral': 2089, 'n_tokens_neox': 1980, 'n_words': 355}