mirror of
https://github.com/mangosfour/server.git
synced 2025-12-25 04:37:02 +00:00
563 lines
15 KiB
C++
563 lines
15 KiB
C++
/**
|
|
* MaNGOS is a full featured server for World of Warcraft, supporting
|
|
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
|
|
*
|
|
* Copyright (C) 2005-2017 MaNGOS project <https://getmangos.eu>
|
|
*
|
|
* 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
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; 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
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
|
|
* and lore are copyrighted by Blizzard Entertainment, Inc.
|
|
*/
|
|
|
|
#ifndef MANGOSSERVER_LOG_H
|
|
#define MANGOSSERVER_LOG_H
|
|
|
|
#include "Common/Common.h"
|
|
#include "Policies/Singleton.h"
|
|
|
|
#include <mutex>
|
|
|
|
class Config;
|
|
class ByteBuffer;
|
|
|
|
/**
|
|
* @brief various levels for logging
|
|
*
|
|
*/
|
|
enum LogLevel
|
|
{
|
|
LOG_LVL_MINIMAL = 0,
|
|
LOG_LVL_BASIC = 1,
|
|
LOG_LVL_DETAIL = 2,
|
|
LOG_LVL_DEBUG = 3
|
|
};
|
|
|
|
/**
|
|
* @brief bitmask (not forgot update logFilterData content)
|
|
*
|
|
*/
|
|
enum LogFilters
|
|
{
|
|
LOG_FILTER_TRANSPORT_MOVES = 0x000001, // 0 any related to transport moves
|
|
LOG_FILTER_CREATURE_MOVES = 0x000002, // 1 creature move by cells
|
|
LOG_FILTER_VISIBILITY_CHANGES = 0x000004, // 2 update visibility for diff objects and players
|
|
LOG_FILTER_ACHIEVEMENT_UPDATES = 0x000008, // 3 achievement update broadcasts
|
|
LOG_FILTER_WEATHER = 0x000010, // 4 weather changes
|
|
LOG_FILTER_PLAYER_STATS = 0x000020, // 5 player save data
|
|
LOG_FILTER_SQL_TEXT = 0x000040, // 6 raw SQL text send to DB engine
|
|
LOG_FILTER_PLAYER_MOVES = 0x000080, // 7 player moves by grid/cell
|
|
LOG_FILTER_PERIODIC_AFFECTS = 0x000100, // 8 DoT/HoT apply trace
|
|
LOG_FILTER_AI_AND_MOVEGENSS = 0x000200, // 9 AI/movement generators debug output
|
|
LOG_FILTER_DAMAGE = 0x000400, // 10 Direct/Area damage trace
|
|
LOG_FILTER_COMBAT = 0x000800, // 11 attack states/roll attack results/etc
|
|
LOG_FILTER_SPELL_CAST = 0x001000, // 12 spell cast/aura apply/spell proc events
|
|
LOG_FILTER_DB_STRICTED_CHECK = 0x002000, // 13 stricted DB data checks output (with possible false reports) for DB devs
|
|
LOG_FILTER_AHBOT_SELLER = 0x004000, // 14 Auction House Bot seller part
|
|
LOG_FILTER_AHBOT_BUYER = 0x008000, // 15 Auction House Bot buyer part
|
|
LOG_FILTER_PATHFINDING = 0x010000, // 16 Pathfinding
|
|
LOG_FILTER_MAP_LOADING = 0x020000, // 17 Map loading/unloading (MAP, VMAPS, MMAP)
|
|
LOG_FILTER_EVENT_AI_DEV = 0x040000, // 18 Event AI actions
|
|
LOG_FILTER_CALENDAR = 0x080000, // 19 Calendar
|
|
};
|
|
|
|
#define LOG_FILTER_COUNT 20
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
*/
|
|
struct LogFilterData
|
|
{
|
|
char const* name; /**< TODO */
|
|
char const* configName; /**< TODO */
|
|
bool defaultState; /**< TODO */
|
|
};
|
|
|
|
extern LogFilterData logFilterData[LOG_FILTER_COUNT]; /**< TODO */
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
*/
|
|
enum Color
|
|
{
|
|
BLACK,
|
|
RED,
|
|
GREEN,
|
|
BROWN,
|
|
BLUE,
|
|
MAGENTA,
|
|
CYAN,
|
|
GREY,
|
|
YELLOW,
|
|
LRED,
|
|
LGREEN,
|
|
LBLUE,
|
|
LMAGENTA,
|
|
LCYAN,
|
|
WHITE
|
|
};
|
|
|
|
const int Color_count = int(WHITE) + 1; /**< TODO */
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
*/
|
|
class Log : public MaNGOS::Singleton<Log, MaNGOS::ClassLevelLockable<Log, ACE_Thread_Mutex> >
|
|
{
|
|
friend class MaNGOS::OperatorNew<Log>;
|
|
/**
|
|
* @brief
|
|
*
|
|
*/
|
|
Log();
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
*/
|
|
~Log()
|
|
{
|
|
if (logfile != NULL)
|
|
{ fclose(logfile); }
|
|
logfile = NULL;
|
|
|
|
if (gmLogfile != NULL)
|
|
{ fclose(gmLogfile); }
|
|
gmLogfile = NULL;
|
|
|
|
if (charLogfile != NULL)
|
|
{ fclose(charLogfile); }
|
|
charLogfile = NULL;
|
|
|
|
if (dberLogfile != NULL)
|
|
{ fclose(dberLogfile); }
|
|
dberLogfile = NULL;
|
|
|
|
#ifdef ENABLE_ELUNA
|
|
if (elunaErrLogfile != NULL)
|
|
fclose(elunaErrLogfile);
|
|
elunaErrLogfile = NULL;
|
|
#endif /* ENABLE_ELUNA */
|
|
|
|
if (eventAiErLogfile != NULL)
|
|
{ fclose(eventAiErLogfile); }
|
|
eventAiErLogfile = NULL;
|
|
|
|
if (scriptErrLogFile != NULL)
|
|
{ fclose(scriptErrLogFile); }
|
|
scriptErrLogFile = NULL;
|
|
|
|
if (raLogfile != NULL)
|
|
{ fclose(raLogfile); }
|
|
raLogfile = NULL;
|
|
|
|
if (worldLogfile != NULL)
|
|
{ fclose(worldLogfile); }
|
|
worldLogfile = NULL;
|
|
|
|
if (wardenLogfile != NULL)
|
|
{
|
|
fclose(wardenLogfile);
|
|
}
|
|
wardenLogfile = NULL;
|
|
}
|
|
public:
|
|
/**
|
|
* @brief
|
|
*
|
|
*/
|
|
void Initialize();
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param init_str
|
|
*/
|
|
void InitColors(const std::string& init_str);
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param account
|
|
* @param str...
|
|
*/
|
|
void outCommand(uint32 account, const char* str, ...) ATTR_PRINTF(3, 4);
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
*/
|
|
void outString();
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outString(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param err...
|
|
*/
|
|
void outError(const char* err, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief log level >= 1
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outBasic(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief log level >= 2
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outDetail(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief log level >= 3
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outDebug(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
*/
|
|
void outErrorDb();
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outErrorDb(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outChar(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outErrorEluna();
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outErrorEluna(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
*/
|
|
void outErrorEventAI();
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outErrorEventAI(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
*/
|
|
void outErrorScriptLib();
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outErrorScriptLib(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param socket
|
|
* @param opcode
|
|
* @param opcodeName
|
|
* @param packet
|
|
* @param incoming
|
|
*/
|
|
void outWorldPacketDump(uint32 socket, uint32 opcode, char const* opcodeName, ByteBuffer const* packet, bool incoming);
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param str
|
|
* @param account_id
|
|
* @param guid
|
|
* @param name
|
|
*/
|
|
void outCharDump(const char* str, uint32 account_id, uint32 guid, const char* name);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outRALog(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
*/
|
|
void outWarden();
|
|
/**
|
|
* @brief any log level
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outWarden(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @return uint32
|
|
*/
|
|
uint32 GetLogLevel() const { return m_logLevel; }
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param Level
|
|
*/
|
|
void SetLogLevel(char* Level);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param Level
|
|
*/
|
|
void SetLogFileLevel(char* Level);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param stdout_stream
|
|
* @param color
|
|
*/
|
|
void SetColor(bool stdout_stream, Color color);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param stdout_stream
|
|
*/
|
|
void ResetColor(bool stdout_stream);
|
|
/**
|
|
* @brief
|
|
*
|
|
*/
|
|
void outTime();
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param file
|
|
*/
|
|
static void outTimestamp(FILE* file);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @return std::string
|
|
*/
|
|
static std::string GetTimestampStr();
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param filter
|
|
* @return bool
|
|
*/
|
|
bool HasLogFilter(uint32 filter) const { return m_logFilter & filter; }
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param filter
|
|
* @param on
|
|
*/
|
|
void SetLogFilter(LogFilters filter, bool on) { if (on) { m_logFilter |= filter; } else { m_logFilter &= ~filter; } }
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param loglvl
|
|
* @return bool
|
|
*/
|
|
bool HasLogLevelOrHigher(LogLevel loglvl) const { return m_logLevel >= loglvl || (m_logFileLevel >= loglvl && logfile); }
|
|
/**
|
|
* @brief
|
|
*
|
|
* @return bool
|
|
*/
|
|
bool IsOutCharDump() const { return m_charLog_Dump; }
|
|
/**
|
|
* @brief
|
|
*
|
|
* @return bool
|
|
*/
|
|
bool IsIncludeTime() const { return m_includeTime; }
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
*/
|
|
static void WaitBeforeContinueIfNeed();
|
|
|
|
/**
|
|
* @brief Set filename for scriptlibrary error output
|
|
*
|
|
* @param fname
|
|
* @param libName
|
|
*/
|
|
void setScriptLibraryErrorFile(char const* fname, char const* libName);
|
|
|
|
private:
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param configFileName
|
|
* @param configTimeStampFlag
|
|
* @param mode
|
|
* @return FILE
|
|
*/
|
|
FILE* openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param account
|
|
* @return FILE
|
|
*/
|
|
FILE* openGmlogPerAccount(uint32 account);
|
|
|
|
FILE* raLogfile; /**< TODO */
|
|
FILE* logfile; /**< TODO */
|
|
FILE* gmLogfile; /**< TODO */
|
|
FILE* charLogfile; /**< TODO */
|
|
FILE* dberLogfile; /**< TODO */
|
|
#ifdef ENABLE_ELUNA
|
|
FILE* elunaErrLogfile; /**< TODO */
|
|
#endif /* ENABLE_ELUNA */
|
|
FILE* eventAiErLogfile; /**< TODO */
|
|
FILE* scriptErrLogFile; /**< TODO */
|
|
FILE* worldLogfile; /**< TODO */
|
|
FILE* wardenLogfile; /**< TODO */
|
|
ACE_Thread_Mutex m_worldLogMtx; /**< TODO */
|
|
|
|
LogLevel m_logLevel; /**< log/console control */
|
|
LogLevel m_logFileLevel; /**< TODO */
|
|
bool m_colored; /**< TODO */
|
|
bool m_includeTime; /**< TODO */
|
|
Color m_colors[4]; /**< TODO */
|
|
uint32 m_logFilter; /**< TODO */
|
|
|
|
// cache values for after initilization use (like gm log per account case)
|
|
std::string m_logsDir; /**< TODO */
|
|
std::string m_logsTimestamp; /**< TODO */
|
|
|
|
// char log control
|
|
bool m_charLog_Dump; /**< TODO */
|
|
|
|
// gm log control
|
|
bool m_gmlog_per_account; /**< TODO */
|
|
std::string m_gmlog_filename_format; /**< TODO */
|
|
|
|
char const* m_scriptLibName; /**< TODO */
|
|
};
|
|
|
|
#define sLog MaNGOS::Singleton<Log>::Instance()
|
|
|
|
#define BASIC_LOG(...) \
|
|
do { \
|
|
if (sLog.HasLogLevelOrHigher(LOG_LVL_BASIC)) \
|
|
sLog.outBasic(__VA_ARGS__); \
|
|
} while(0)
|
|
|
|
#define BASIC_FILTER_LOG(F,...) \
|
|
do { \
|
|
if (sLog.HasLogLevelOrHigher(LOG_LVL_BASIC) && !sLog.HasLogFilter(F)) \
|
|
sLog.outBasic(__VA_ARGS__); \
|
|
} while(0)
|
|
|
|
#define DETAIL_LOG(...) \
|
|
do { \
|
|
if (sLog.HasLogLevelOrHigher(LOG_LVL_DETAIL)) \
|
|
sLog.outDetail(__VA_ARGS__); \
|
|
} while(0)
|
|
|
|
#define DETAIL_FILTER_LOG(F,...) \
|
|
do { \
|
|
if (sLog.HasLogLevelOrHigher(LOG_LVL_DETAIL) && !sLog.HasLogFilter(F)) \
|
|
sLog.outDetail(__VA_ARGS__); \
|
|
} while(0)
|
|
|
|
#define DEBUG_LOG(...) \
|
|
do { \
|
|
if (sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) \
|
|
sLog.outDebug(__VA_ARGS__); \
|
|
} while(0)
|
|
|
|
#define DEBUG_FILTER_LOG(F,...) \
|
|
do { \
|
|
if (sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG) && !sLog.HasLogFilter(F)) \
|
|
sLog.outDebug(__VA_ARGS__); \
|
|
} while(0)
|
|
|
|
#define ERROR_DB_FILTER_LOG(F,...) \
|
|
do { \
|
|
if (!sLog.HasLogFilter(F)) \
|
|
sLog.outErrorDb(__VA_ARGS__); \
|
|
} while(0)
|
|
|
|
#define ERROR_DB_STRICT_LOG(...) \
|
|
ERROR_DB_FILTER_LOG(LOG_FILTER_DB_STRICTED_CHECK, __VA_ARGS__)
|
|
|
|
/**
|
|
* @brief primary for script library
|
|
*
|
|
* @param str...
|
|
*/
|
|
void outstring_log(const char* str, ...) ATTR_PRINTF(1, 2);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param str...
|
|
*/
|
|
void detail_log(const char* str, ...) ATTR_PRINTF(1, 2);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param str...
|
|
*/
|
|
void debug_log(const char* str, ...) ATTR_PRINTF(1, 2);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param str...
|
|
*/
|
|
void error_log(const char* str, ...) ATTR_PRINTF(1, 2);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param str...
|
|
*/
|
|
void error_db_log(const char* str, ...) ATTR_PRINTF(1, 2);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param fname
|
|
* @param libName
|
|
*/
|
|
void setScriptLibraryErrorFile(char const* fname, char const* libName);
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param str...
|
|
*/
|
|
void script_error_log(const char* str, ...) ATTR_PRINTF(1, 2);
|
|
|
|
#endif
|