Cleanup eqemu_logsys code and automatically inject new logging categories into the database if they do not exist

This commit is contained in:
Akkadius 2018-10-20 22:29:59 -05:00
parent 8115db3576
commit ab8075d629
4 changed files with 569 additions and 339 deletions

1
.gitignore vendored
View File

@ -40,3 +40,4 @@ logs/
vcpkg/ vcpkg/
.idea/* .idea/*
*cbp

View File

@ -2063,8 +2063,7 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id)
return atoi(row[0]); return atoi(row[0]);
} }
void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) {
{
// log_settings previously initialized to '0' by EQEmuLogSys::LoadLogSettingsDefaults() // log_settings previously initialized to '0' by EQEmuLogSys::LoadLogSettingsDefaults()
std::string query = std::string query =
@ -2077,37 +2076,78 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings)
"FROM " "FROM "
"logsys_categories " "logsys_categories "
"ORDER BY log_category_id"; "ORDER BY log_category_id";
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
int log_category = 0; int log_category_id = 0;
LogSys.file_logs_enabled = false; LogSys.file_logs_enabled = false;
int categories_in_database[1000] = {};
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
log_category = atoi(row[0]); log_category_id = atoi(row[0]);
if (log_category <= Logs::None || log_category >= Logs::MaxCategoryID) if (log_category_id <= Logs::None || log_category_id >= Logs::MaxCategoryID) {
continue; continue;
}
log_settings[log_category].log_to_console = atoi(row[2]); log_settings[log_category_id].log_to_console = atoi(row[2]);
log_settings[log_category].log_to_file = atoi(row[3]); log_settings[log_category_id].log_to_file = atoi(row[3]);
log_settings[log_category].log_to_gmsay = atoi(row[4]); log_settings[log_category_id].log_to_gmsay = atoi(row[4]);
/* Determine if any output method is enabled for the category /**
and set it to 1 so it can used to check if category is enabled */ * Determine if any output method is enabled for the category
const bool log_to_console = log_settings[log_category].log_to_console > 0; * and set it to 1 so it can used to check if category is enabled
const bool log_to_file = log_settings[log_category].log_to_file > 0; */
const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0; const bool log_to_console = log_settings[log_category_id].log_to_console > 0;
const bool log_to_file = log_settings[log_category_id].log_to_file > 0;
const bool log_to_gmsay = log_settings[log_category_id].log_to_gmsay > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay; const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
if (is_category_enabled) if (is_category_enabled) {
log_settings[log_category].is_category_enabled = 1; log_settings[log_category_id].is_category_enabled = 1;
}
/* /**
This determines whether or not the process needs to actually file log anything. * This determines whether or not the process needs to actually file log anything.
If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open * If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open
*/ */
if (log_settings[log_category].log_to_file > 0){ if (log_settings[log_category_id].log_to_file > 0) {
LogSys.file_logs_enabled = true; LogSys.file_logs_enabled = true;
} }
categories_in_database[log_category_id] = 1;
}
/**
* Auto inject categories that don't exist in the database...
*/
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
if (!categories_in_database[log_index]) {
Log(Logs::General,
Logs::Status,
"New Log Category '%s' doesn't exist... Automatically adding to `logsys_categories` table...",
Logs::LogCategoryName[log_index]
);
std::string inject_query = StringFormat(
"INSERT INTO logsys_categories "
"(log_category_id, "
"log_category_description, "
"log_to_console, "
"log_to_file, "
"log_to_gmsay) "
"VALUES "
"(%i, '%s', %i, %i, %i)",
log_index,
EscapeString(Logs::LogCategoryName[log_index]).c_str(),
log_settings[log_category_id].log_to_console,
log_settings[log_category_id].log_to_file,
log_settings[log_category_id].log_to_gmsay
);
QueryDatabase(inject_query);
}
} }
} }

View File

@ -1,22 +1,23 @@
/* EQEMu: Everquest Server Emulator /**
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) * EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2018 EQEmulator Development Team (https://github.com/EQEmu/Server)
This program is free software; you can redistribute it and/or modify *
it under the terms of the GNU General Public License as published by * This program is free software; you can redistribute it and/or modify
the Free Software Foundation; version 2 of the License. * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, *
but WITHOUT ANY WARRANTY except by those people which sell it, which * This program is distributed in the hope that it will be useful,
are required to give you total support for your newly bought product; * but WITHOUT ANY WARRANTY except by those people which sell it, which
without even the implied warranty of MERCHANTABILITY or FITNESS FOR * are required to give you total support for your newly bought product;
A PARTICULAR PURPOSE. See the GNU General Public License for more details. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License *
along with this program; if not, write to the Free Software * You should have received a copy of the GNU General Public License
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/ */
#include "eqemu_logsys.h" #include "eqemu_logsys.h"
#include "platform.h" #include "platform.h"
#include "string_util.h" #include "string_util.h"
@ -40,11 +41,15 @@ std::ofstream process_log;
#include <windows.h> #include <windows.h>
#include <process.h> #include <process.h>
#else #else
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
/* Linux ANSI console color defines */ /**
* Linux ANSI console color defines
*/
#define LC_RESET "\033[0m" #define LC_RESET "\033[0m"
#define LC_BLACK "\033[30m" /* Black */ #define LC_BLACK "\033[30m" /* Black */
#define LC_RED "\033[31m" /* Red */ #define LC_RED "\033[31m" /* Red */
@ -76,6 +81,17 @@ namespace Console {
}; };
} }
enum GameChatColor {
yellow = 15,
red = 13,
light_green = 14,
light_cyan = 258,
light_purple = 5
};
/**
* EQEmuLogSys Constructor
*/
EQEmuLogSys::EQEmuLogSys() EQEmuLogSys::EQEmuLogSys()
{ {
on_log_gmsay_hook = [](uint16 log_type, const std::string &) {}; on_log_gmsay_hook = [](uint16 log_type, const std::string &) {};
@ -83,19 +99,28 @@ EQEmuLogSys::EQEmuLogSys()
int log_platform = 0; int log_platform = 0;
} }
/**
* EQEmuLogSys Deconstructor
*/
EQEmuLogSys::~EQEmuLogSys() EQEmuLogSys::~EQEmuLogSys()
{ {
} }
void EQEmuLogSys::LoadLogSettingsDefaults() void EQEmuLogSys::LoadLogSettingsDefaults()
{ {
/* Get Executable platform currently running this code (Zone/World/etc) */ /**
* Get Executable platform currently running this code (Zone/World/etc)
*/
log_platform = GetExecutablePlatformInt(); log_platform = GetExecutablePlatformInt();
/* Zero out Array */ /**
* Zero out Array
*/
memset(log_settings, 0, sizeof(LogSettings) * Logs::LogCategory::MaxCategoryID); memset(log_settings, 0, sizeof(LogSettings) * Logs::LogCategory::MaxCategoryID);
/* Set Defaults */ /**
* Set Defaults
*/
log_settings[Logs::World_Server].log_to_console = Logs::General; log_settings[Logs::World_Server].log_to_console = Logs::General;
log_settings[Logs::Zone_Server].log_to_console = Logs::General; log_settings[Logs::Zone_Server].log_to_console = Logs::General;
log_settings[Logs::QS_Server].log_to_console = Logs::General; log_settings[Logs::QS_Server].log_to_console = Logs::General;
@ -105,7 +130,9 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::Login_Server].log_to_console = Logs::General; log_settings[Logs::Login_Server].log_to_console = Logs::General;
log_settings[Logs::Headless_Client].log_to_console = Logs::General; log_settings[Logs::Headless_Client].log_to_console = Logs::General;
/* Set Category enabled status on defaults */ /**
* Set Category enabled status on defaults
*/
log_settings[Logs::World_Server].is_category_enabled = 1; log_settings[Logs::World_Server].is_category_enabled = 1;
log_settings[Logs::Zone_Server].is_category_enabled = 1; log_settings[Logs::Zone_Server].is_category_enabled = 1;
log_settings[Logs::QS_Server].is_category_enabled = 1; log_settings[Logs::QS_Server].is_category_enabled = 1;
@ -114,25 +141,37 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::MySQLError].is_category_enabled = 1; log_settings[Logs::MySQLError].is_category_enabled = 1;
log_settings[Logs::Login_Server].is_category_enabled = 1; log_settings[Logs::Login_Server].is_category_enabled = 1;
/* Declare process file names for log writing /**
If there is no process_file_name declared, no log file will be written, simply * Declare process file names for log writing=
*/ */
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld) if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld) {
platform_file_name = "world"; platform_file_name = "world";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ) }
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ) {
platform_file_name = "query_server"; platform_file_name = "query_server";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) }
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
platform_file_name = "zone"; platform_file_name = "zone";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS) }
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS) {
platform_file_name = "ucs"; platform_file_name = "ucs";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) }
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) {
platform_file_name = "login"; platform_file_name = "login";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch) }
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch) {
platform_file_name = "launcher"; platform_file_name = "launcher";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformHC) }
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformHC) {
platform_file_name = "hc"; platform_file_name = "hc";
} }
}
/**
* @param log_category
* @param in_message
* @return
*/
std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::string &in_message) std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::string &in_message)
{ {
std::string ret; std::string ret;
@ -144,17 +183,33 @@ std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::
return ret; return ret;
} }
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message) void EQEmuLogSys::ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message)
{ {
/* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash */ /**
if (log_category == Logs::LogCategory::Netcode) * Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash
*/
if (log_category == Logs::LogCategory::Netcode) {
return; return;
/* Check to see if the process that actually ran this is zone */
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone)
on_log_gmsay_hook(log_category, message);
} }
/**
* Check to see if the process that actually ran this is zone
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
on_log_gmsay_hook(log_category, message);
}
}
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message) void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message)
{ {
if (log_category == Logs::Crash) { if (log_category == Logs::Crash) {
@ -162,7 +217,10 @@ void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const
EQEmuLogSys::SetCurrentTimeStamp(time_stamp); EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
std::ofstream crash_log; std::ofstream crash_log;
EQEmuLogSys::MakeDirectory("logs/crashes"); EQEmuLogSys::MakeDirectory("logs/crashes");
crash_log.open(StringFormat("logs/crashes/crash_%s_%i.log", platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out); crash_log.open(
StringFormat("logs/crashes/crash_%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
crash_log << time_stamp << " " << message << "\n"; crash_log << time_stamp << " " << message << "\n";
crash_log.close(); crash_log.close();
} }
@ -170,11 +228,17 @@ void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const
char time_stamp[80]; char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp); EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
if (process_log) if (process_log) {
process_log << time_stamp << " " << message << std::endl; process_log << time_stamp << " " << message << std::endl;
} }
}
uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category) { /**
* @param log_category
* @return
*/
uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) { switch (log_category) {
case Logs::Status: case Logs::Status:
case Logs::Normal: case Logs::Normal:
@ -197,7 +261,12 @@ uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category) {
} }
} }
std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category) { /**
* @param log_category
* @return
*/
std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) { switch (log_category) {
case Logs::Status: case Logs::Status:
case Logs::Normal: case Logs::Normal:
@ -220,32 +289,41 @@ std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category) {
} }
} }
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) { /**
* @param log_category
* @return
*/
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
{
switch (log_category) { switch (log_category) {
case Logs::Status: case Logs::Status:
case Logs::Normal: case Logs::Normal:
return 15; /* Yellow */ return GameChatColor::yellow;
case Logs::MySQLError: case Logs::MySQLError:
case Logs::Error: case Logs::Error:
return 13; /* Red */ return GameChatColor::red;
case Logs::MySQLQuery: case Logs::MySQLQuery:
case Logs::Debug: case Logs::Debug:
return 14; /* Light Green */ return GameChatColor::light_green;
case Logs::Quests: case Logs::Quests:
return 258; /* Light Cyan */ return GameChatColor::light_cyan;
case Logs::Commands: case Logs::Commands:
case Logs::Mercenaries: case Logs::Mercenaries:
return 5; /* Light Purple */ return GameChatColor::light_purple;
case Logs::Crash: case Logs::Crash:
return 13; /* Red */ return GameChatColor::red;
default: default:
return 15; /* Yellow */ return GameChatColor::yellow;
} }
} }
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message) void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message)
{ {
#ifdef _WINDOWS #ifdef _WINDOWS
HANDLE console_handle; HANDLE console_handle;
console_handle = GetStdHandle(STD_OUTPUT_HANDLE); console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
@ -263,9 +341,16 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category,
#endif #endif
} }
/**
* Core logging function
*
* @param debug_level
* @param log_category
* @param message
* @param ...
*/
void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...) void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...)
{ {
bool log_to_console = true; bool log_to_console = true;
if (log_settings[log_category].log_to_console < debug_level) { if (log_settings[log_category].log_to_console < debug_level) {
log_to_console = false; log_to_console = false;
@ -282,8 +367,9 @@ void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::st
} }
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay; const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay;
if (nothing_to_log) if (nothing_to_log) {
return; return;
}
va_list args; va_list args;
va_start(args, message); va_start(args, message);
@ -292,11 +378,20 @@ void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::st
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, output_message); std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, output_message);
if (log_to_console) EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message); if (log_to_console) {
if (log_to_gmsay) EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message); EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
if (log_to_file) EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message); }
if (log_to_gmsay) {
EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
}
if (log_to_file) {
EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message);
}
} }
/**
* @param time_stamp
*/
void EQEmuLogSys::SetCurrentTimeStamp(char *time_stamp) void EQEmuLogSys::SetCurrentTimeStamp(char *time_stamp)
{ {
time_t raw_time; time_t raw_time;
@ -306,6 +401,9 @@ void EQEmuLogSys::SetCurrentTimeStamp(char* time_stamp)
strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info); strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info);
} }
/**
* @param directory_name
*/
void EQEmuLogSys::MakeDirectory(const std::string &directory_name) void EQEmuLogSys::MakeDirectory(const std::string &directory_name)
{ {
#ifdef _WINDOWS #ifdef _WINDOWS
@ -315,8 +413,9 @@ void EQEmuLogSys::MakeDirectory(const std::string &directory_name)
_mkdir(directory_name.c_str()); _mkdir(directory_name.c_str());
#else #else
struct stat st; struct stat st;
if (stat(directory_name.c_str(), &st) == 0) // exists if (stat(directory_name.c_str(), &st) == 0) { // exists
return; return;
}
mkdir(directory_name.c_str(), 0755); mkdir(directory_name.c_str(), 0755);
#endif #endif
} }
@ -328,29 +427,75 @@ void EQEmuLogSys::CloseFileLogs()
} }
} }
/**
* @param log_name
*/
void EQEmuLogSys::StartFileLogs(const std::string &log_name) void EQEmuLogSys::StartFileLogs(const std::string &log_name)
{ {
EQEmuLogSys::CloseFileLogs(); EQEmuLogSys::CloseFileLogs();
/* When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one... */ /**
if (file_logs_enabled == false) * When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one...
*/
if (!file_logs_enabled) {
return; return;
}
/**
* Zone
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) { if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
if (!log_name.empty()) if (!log_name.empty()) {
platform_file_name = log_name; platform_file_name = log_name;
}
if (platform_file_name.empty()) if (platform_file_name.empty()) {
return; return;
}
EQEmuLogSys::Out(Logs::General, Logs::Status, "Starting File Log 'logs/%s_%i.log'", platform_file_name.c_str(), getpid()); EQEmuLogSys::Out(
Logs::General,
Logs::Status,
"Starting File Log 'logs/%s_%i.log'",
platform_file_name.c_str(),
getpid());
/**
* Make directory if not exists
*/
EQEmuLogSys::MakeDirectory("logs/zone"); EQEmuLogSys::MakeDirectory("logs/zone");
process_log.open(StringFormat("logs/zone/%s_%i.log", platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out);
} else {
if (platform_file_name.empty())
return;
EQEmuLogSys::Out(Logs::General, Logs::Status, "Starting File Log 'logs/%s_%i.log'", platform_file_name.c_str(), getpid()); /**
process_log.open(StringFormat("logs/%s_%i.log", platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out); * Open file pointer
*/
process_log.open(
StringFormat("logs/zone/%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
}
else {
/**
* All other processes
*/
if (platform_file_name.empty()) {
return;
}
EQEmuLogSys::Out(
Logs::General,
Logs::Status,
"Starting File Log 'logs/%s_%i.log'",
platform_file_name.c_str(),
getpid());
/**
* Open file pointer
*/
process_log.open(
StringFormat("logs/%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
} }
} }

View File

@ -1,20 +1,21 @@
/**
/* EQEMu: Everquest Server Emulator * EQEmulator: Everquest Server Emulator
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) * Copyright (C) 2001-2018 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. * the Free Software Foundation; version 2 of the License.
*
This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which * but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product; * are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR * without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details. * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/ */
#ifndef EQEMU_LOGSYS_H #ifndef EQEMU_LOGSYS_H
@ -34,11 +35,11 @@ namespace Logs {
Detail /* 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication */ Detail /* 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication */
}; };
/* /**
If you add to this, make sure you update LogCategoryName * If you add to this, make sure you update LogCategoryName
NOTE: Only add to the bottom of the enum because that is the type ID assignment *
* NOTE: Only add to the bottom of the enum because that is the type ID assignment
*/ */
enum LogCategory { enum LogCategory {
None = 0, None = 0,
AA, AA,
@ -91,10 +92,13 @@ enum LogCategory {
Food, Food,
Traps, Traps,
NPCRoamBox, NPCRoamBox,
NPCScaling,
MaxCategoryID /* Don't Remove this */ MaxCategoryID /* Don't Remove this */
}; };
/* If you add to this, make sure you update LogCategory */ /**
* If you add to this, make sure you update LogCategory
*/
static const char* LogCategoryName[LogCategory::MaxCategoryID] = { static const char* LogCategoryName[LogCategory::MaxCategoryID] = {
"", "",
"AA", "AA",
@ -146,7 +150,8 @@ static const char* LogCategoryName[LogCategory::MaxCategoryID] = {
"FixZ", "FixZ",
"Food", "Food",
"Traps", "Traps",
"NPC Roam Box" "NPC Roam Box",
"NPC Scaling"
}; };
} }
@ -165,21 +170,30 @@ public:
EQEmuLogSys(); EQEmuLogSys();
~EQEmuLogSys(); ~EQEmuLogSys();
void CloseFileLogs(); /* Close File Logs wherever necessary, either at zone shutdown or entire process shutdown for everything else. This should be handled on deconstructor but to be safe we use it anyways. */ /**
void LoadLogSettingsDefaults(); /* Initializes log_settings and sets some defaults if DB is not present */ * Close File Logs wherever necessary, either at zone shutdown or entire process shutdown for everything else.
void MakeDirectory(const std::string &directory_name); /* Platform independent way of performing a MakeDirectory based on name */ * This should be handled on deconstructor but to be safe we use it anyways.
/* */
The one and only Logging function that uses a debug level as a parameter, as well as a log_category void CloseFileLogs();
log_category - defined in Logs::LogCategory::[] void LoadLogSettingsDefaults();
log_category name resolution works by passing the enum int ID to Logs::LogCategoryName[category_id] void MakeDirectory(const std::string &directory_name);
Example: EQEmuLogSys::Out(Logs::General, Logs::Guilds, "This guild has no leader present"); /**
- This would pipe the same category and debug level to all output formats, but the internal memory reference of log_settings would * The one and only Logging function that uses a debug level as a parameter, as well as a log_category
be checked against to see if that piped output is set to actually process it for the category and debug level * log_category - defined in Logs::LogCategory::[]
* log_category name resolution works by passing the enum int ID to Logs::LogCategoryName[category_id]
*
* Example: EQEmuLogSys::Out(Logs::General, Logs::Guilds, "This guild has no leader present");
* - This would pipe the same category and debug level to all output formats, but the internal memory reference of log_settings would
* be checked against to see if that piped output is set to actually process it for the category and debug level
*/ */
void Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...); void Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...);
void SetCurrentTimeStamp(char* time_stamp); /* Used in file logs to prepend a timestamp entry for logs */
void StartFileLogs(const std::string &log_name = ""); /* Used to declare the processes file log and to keep it open for later use */ /**
* Used in file logs to prepend a timestamp entry for logs
*/
void SetCurrentTimeStamp(char* time_stamp);
void StartFileLogs(const std::string &log_name = "");
template <typename... Args> template <typename... Args>
void OutF(Logs::DebugLevel debug_level, uint16 log_category, const char *fmt, const Args&... args) void OutF(Logs::DebugLevel debug_level, uint16 log_category, const char *fmt, const Args&... args)
@ -188,16 +202,16 @@ public:
Out(debug_level, log_category, log_str); Out(debug_level, log_category, log_str);
} }
/* /**
LogSettings Struct * LogSettings Struct
*
This struct is the master reference for all settings for each category, and for each output * This struct is the master reference for all settings for each category, and for each output
*
log_to_file[category_id] = [1-3] - Sets debug level for category to output to file * log_to_file[category_id] = [1-3] - Sets debug level for category to output to file
log_to_console[category_id] = [1-3] - Sets debug level for category to output to console * log_to_console[category_id] = [1-3] - Sets debug level for category to output to console
log_to_gmsay[category_id] = [1-3] - Sets debug level for category to output to gmsay * log_to_gmsay[category_id] = [1-3] - Sets debug level for category to output to gmsay
*
*/ */
struct LogSettings { struct LogSettings {
uint8 log_to_file; uint8 log_to_file;
uint8 log_to_console; uint8 log_to_console;
@ -205,32 +219,62 @@ public:
uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */ uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */
}; };
/* Internally used memory reference for all log settings per category. /**
These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults. * Internally used memory reference for all log settings per category
Database loaded via Database::LoadLogSettings(log_settings) * These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults
* Database loaded via Database::LoadLogSettings(log_settings)
*/ */
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]; LogSettings log_settings[Logs::LogCategory::MaxCategoryID];
bool file_logs_enabled; /* Set when log settings are loaded to determine if keeping a file open is necessary */ bool file_logs_enabled;
int log_platform; /* Sets Executable platform (Zone/World/UCS) etc. */ /**
* Sets Executable platform (Zone/World/UCS) etc.
*/
int log_platform;
std::string platform_file_name; /* File name used in writing logs */ /**
* File name used in writing logs
*/
std::string platform_file_name;
uint16 GetGMSayColorFromCategory(uint16 log_category); /* GMSay Client Message colors mapped by category */ /**
* GMSay Client Message colors mapped by category
*
* @param log_category
* @return
*/
uint16 GetGMSayColorFromCategory(uint16 log_category);
void OnLogHookCallBackZone(std::function<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; } void OnLogHookCallBackZone(std::function<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; }
private: private:
std::function<void(uint16 log_category, const std::string&)> on_log_gmsay_hook; /* Callback pointer to zone process for hooking logs to zone using GMSay */
std::string FormatOutMessageString(uint16 log_category, const std::string &in_message); /* Formats log messages like '[Category] This is a log message' */
std::string GetLinuxConsoleColorFromCategory(uint16 log_category); /* Linux console color messages mapped by category */
uint16 GetWindowsConsoleColorFromCategory(uint16 log_category); /* Windows console color messages mapped by category */ /**
* Callback pointer to zone process for hooking logs to zone using GMSay
*/
std::function<void(uint16 log_category, const std::string&)> on_log_gmsay_hook;
void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message); /* ProcessConsoleMessage called via Log */ /**
void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message); /* ProcessGMSay called via Log */ * Formats log messages like '[Category] This is a log message'
void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message); /* ProcessLogWrite called via Log */ */
std::string FormatOutMessageString(uint16 log_category, const std::string &in_message);
/**
* Linux console color messages mapped by category
* @param log_category
* @return
*/
std::string GetLinuxConsoleColorFromCategory(uint16 log_category);
/**
* Windows console color messages mapped by category
*/
uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message);
void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message);
void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message);
}; };
extern EQEmuLogSys LogSys; extern EQEmuLogSys LogSys;