From 55ce180f2867700b28921d99f9a0cb9c83330c91 Mon Sep 17 00:00:00 2001 From: Spp Date: Fri, 3 Aug 2012 14:20:18 +0200 Subject: Core/Logging: Add Asyncronous logging with Loggers ("What to log") and Appenders ("Where to log") system. Will allow to select to full log some parts of core while others are not even logged. - Logging System is asyncronous to improve performance. - Each msg and Logger has a Log Type and Log Level assigned. Each msg is assigned the Logger of same Log Type or "root" Logger is selected if there is no Logger configured for the given Log Type - Loggers have a list of Appenders to send the msg to. The Msg in the Logger is not sent to Appenders if the msg LogLevel is lower than Logger LogLevel. - There are three (at the moment) types of Appenders: Console, File or DB (this is WIP, not working ATM). Msg is not written to the resource if msg LogLevel is lower than Appender LogLevel. - Appender and Console Log levels can be changed while server is active with command '.set loglevel (a/l) name level' Explanation of use with Sample config: Appender.Console.Type=1 (1 = Console) Appender.Console.Level=2 (2 = Debug) Appender.Server.Type=2 (2 = File) Appender.Server.Level=3 (3 = Info) Appender.Server.File=Server.log Appender.SQL.Type=2 (2 = File) Appender.SQL.Level=1 (1 = Trace) Appender.SQL.File=sql.log Appenders=Console Server (NOTE: SQL has not been included here... that will make core ignore the config for "SQL" as it's not in this list) Logger.root.Type=0 (0 = Default - if it's not created by config, server will create it with LogLevel = DISABLED) Logger.root.Level=5 (5 = Error) Logger.root.Appenders=Console Logger.SQL.Type=26 (26 = SQL) Logger.SQL.Level=3 (2 = Debug) Logger.SQL.Appenders=Console Server SQL Logger.SomeRandomName.Type=24 (24 = Guild) Logger.SomeRandomName.Level=5 (5 = Error) Loggers=root SQL SomeRandomName * At loading Appender SQL will be ignored, as it's not present on "Appenders" * sLog->outDebug(LOG_FILTER_GUILD, "Some log msg related to Guilds") - Msg is sent to Logger of Type LOG_FILTER_GUILD (24). Logger with name SomeRandomName is found but it's LogLevel = 5 and Msg LogLevel=2... Msg is not logged * sLog->outError(LOG_FILTER_GUILD, "Some error log msg related to Guilds") - Msg is sent to Logger of Type LOG_FILTER_GUILD (24). Logger with name SomeRandomeName is found with proper LogLevel but Logger does not have any Appenders assigned to that logger... Msg is not logged * sLog->outDebug(LOG_FILTER_SQL, "Some msg related to SQLs") - Msg is sent to Logger SQL (matches type), as it matches LogLevel the msg is sent to Appenders Console, Server and SQL - Appender Console has lower Log Level: Msg is logged to Console - Appender Server has higher Log Level: Msg is not logged to file - Appender SQL has lower Log Level: Msg is logged to file sql.log * sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Some msg related to Battelgrounds") - Msg is sent to Logger root (Type 0) as no Logger was found with Type LOG_FILTER_BATTLEGROUND (13). As Logger has higher LogLevel msg is not sent to any appender * sLog->outError(LOG_FILTER_BATTLEGROUND, "Some error msg related to Battelgrounds") - Msg is sent to Logger root (Type 0) as no Logger was found with Type LOG_FILTER_BATTLEGROUND (13). Msg has lower LogLevel and is sent to Appender Console - Appender Console has lower LogLevel: Msg is logged to Console --- src/server/shared/Logging/Log.h | 209 ++++++++-------------------------------- 1 file changed, 41 insertions(+), 168 deletions(-) (limited to 'src/server/shared/Logging/Log.h') diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index 296c13d86c9..5e2b7972dc8 100755 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -19,196 +19,69 @@ #ifndef TRINITYCORE_LOG_H #define TRINITYCORE_LOG_H -#include "Common.h" -#include - -class Config; +#include "Define.h" +#include "Appender.h" +#include "LogWorker.h" +#include "Logger.h" -enum DebugLogFilters -{ - LOG_FILTER_NONE = 0x00000000, - LOG_FILTER_UNITS = 0x00000001, // Anything related to units that doesn't fit in other categories. ie. creature formations - LOG_FILTER_PETS = 0x00000002, - LOG_FILTER_VEHICLES = 0x00000004, - LOG_FILTER_TSCR = 0x00000008, // C++ AI, instance scripts, etc. - LOG_FILTER_DATABASE_AI = 0x00000010, // SmartAI, EventAI, CreatureAI - LOG_FILTER_MAPSCRIPTS = 0x00000020, - LOG_FILTER_NETWORKIO = 0x00000040, // Anything packet/netcode related - LOG_FILTER_SPELLS_AURAS = 0x00000080, - LOG_FILTER_ACHIEVEMENTSYS = 0x00000100, - LOG_FILTER_CONDITIONSYS = 0x00000200, - LOG_FILTER_POOLSYS = 0x00000400, - LOG_FILTER_AUCTIONHOUSE = 0x00000800, - LOG_FILTER_BATTLEGROUND = 0x00001000, // Anything related to arena's and battlegrounds - LOG_FILTER_OUTDOORPVP = 0x00002000, - LOG_FILTER_CHATSYS = 0x00004000, - LOG_FILTER_LFG = 0x00008000, - LOG_FILTER_MAPS = 0x00010000, // Maps, instances, grids, cells, visibility - LOG_FILTER_PLAYER_LOADING = 0x00020000, // Debug output from Player::_Load functions - LOG_FILTER_PLAYER_ITEMS = 0x00040000, // Anything item related - LOG_FILTER_PLAYER_SKILLS = 0x00080000, // Skills related - LOG_FILTER_LOOT = 0x00100000, // Loot related - LOG_FILTER_GUILD = 0x00200000, // Guild related - LOG_FILTER_TRANSPORTS = 0x00400000, // Transport related - LOG_FILTER_WARDEN = 0x00800000, // Warden related -}; - -enum LogTypes -{ - LOG_TYPE_STRING = 0, - LOG_TYPE_ERROR = 1, - LOG_TYPE_BASIC = 2, - LOG_TYPE_DETAIL = 3, - LOG_TYPE_DEBUG = 4, - LOG_TYPE_CHAR = 5, - LOG_TYPE_WORLD = 6, - LOG_TYPE_RA = 7, - LOG_TYPE_GM = 8, - LOG_TYPE_CRASH = 9, - LOG_TYPE_CHAT = 10, - MAX_LOG_TYPES -}; - -enum LogLevel -{ - LOGL_NORMAL = 0, - LOGL_BASIC, - LOGL_DETAIL, - LOGL_DEBUG -}; - -const int LogLevels = int(LOGL_DEBUG)+1; - -enum ColorTypes -{ - BLACK, - RED, - GREEN, - BROWN, - BLUE, - MAGENTA, - CYAN, - GREY, - YELLOW, - LRED, - LGREEN, - LBLUE, - LMAGENTA, - LCYAN, - WHITE -}; +#include -const int Colors = int(WHITE)+1; +#include +#include class Log { friend class ACE_Singleton; + typedef std::map LoggerMap; + private: Log(); ~Log(); public: - void Initialize(); - - void ReloadConfig(); - - void InitColors(const std::string& init_str); - void SetColor(bool stdout_stream, ColorTypes color); - void ResetColor(bool stdout_stream); - - void outErrorST(const char * err, ...) ATTR_PRINTF(2, 3); - void outDB(LogTypes type, const char * str); - void outString(const char * str, ...) ATTR_PRINTF(2, 3); - void outString(); - void outStringInLine(const char * str, ...) ATTR_PRINTF(2, 3); - void outError(const char * err, ...) ATTR_PRINTF(2, 3); - void outCrash(const char * err, ...) ATTR_PRINTF(2, 3); - void outBasic(const char * str, ...) ATTR_PRINTF(2, 3); - void outDetail(const char * str, ...) ATTR_PRINTF(2, 3); - void outSQLDev(const char * str, ...) ATTR_PRINTF(2, 3); - void outDebug(DebugLogFilters f, const char* str, ...) ATTR_PRINTF(3, 4); - void outStaticDebug(const char * str, ...) ATTR_PRINTF(2, 3); - void outDebugInLine(const char * str, ...) ATTR_PRINTF(2, 3); - void outErrorDb(const char * str, ...) ATTR_PRINTF(2, 3); - void outChar(const char * str, ...) ATTR_PRINTF(2, 3); - void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4); - void outRemote(const char * str, ...) ATTR_PRINTF(2, 3); - void outChat(const char * str, ...) ATTR_PRINTF(2, 3); - void outArena(const char * str, ...) ATTR_PRINTF(2, 3); - void outSQLDriver(const char* str, ...) ATTR_PRINTF(2, 3); - void outWarden(const char * str, ...) ATTR_PRINTF(2, 3); - void outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name); - - static void outTimestamp(FILE* file); - static std::string GetTimestampStr(); + void Close(); + bool ShouldLog(LogFilterType type, LogLevel level) const; + bool SetLogLevel(std::string const& name, char const* level, bool isLogger = true); - void SetLogLevel(char * Level); - void SetLogFileLevel(char * Level); - void SetDBLogLevel(char * Level); - void SetSQLDriverQueryLogging(bool newStatus) { m_sqlDriverQueryLogging = newStatus; } - void SetRealmID(uint32 id) { realm = id; } + void log(LogFilterType f, LogLevel level, char const* str, ...) ATTR_PRINTF(4,5); + + void outTrace(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4); + void outDebug(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4); + void outInfo(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4); + void outWarn(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4); + void outError(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4); + void outFatal(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4); + + void EnableDBAppenders(); + void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4); + static std::string GetTimestampStr(); - bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); } - bool IsOutCharDump() const { return m_charLog_Dump; } + void SetRealmID(uint32 id); - bool GetLogDB() const { return m_enableLogDB; } - bool GetLogDBLater() const { return m_enableLogDBLater; } - void SetLogDB(bool enable) { m_enableLogDB = enable; } - void SetLogDBLater(bool value) { m_enableLogDBLater = value; } - bool GetSQLDriverQueryLogging() const { return m_sqlDriverQueryLogging; } private: - FILE* openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode); - FILE* openGmlogPerAccount(uint32 account); - - FILE* raLogfile; - FILE* logfile; - FILE* gmLogfile; - FILE* charLogfile; - FILE* dberLogfile; - FILE* chatLogfile; - FILE* arenaLogFile; - FILE* sqlLogFile; - FILE* sqlDevLogFile; - FILE* wardenLogFile; - - // cache values for after initilization use (like gm log per account case) + void vlog(LogFilterType f, LogLevel level, char const* str, va_list argptr); + void write(LogMessage* msg); + + Logger* GetLoggerByType(LogFilterType filter); + Appender* GetAppenderByName(std::string const& name); + uint8 NextAppenderId(); + void CreateAppenderFromConfig(const char* name); + void CreateLoggerFromConfig(const char* name); + void ReadAppendersFromConfig(); + void ReadLoggersFromConfig(); + + AppenderMap appenders; + LoggerMap loggers; + uint8 AppenderId; + std::string m_logsDir; std::string m_logsTimestamp; - // gm log control - bool m_gmlog_per_account; - std::string m_gmlog_filename_format; - - bool m_enableLogDBLater; - bool m_enableLogDB; uint32 realm; - - // log coloring - bool m_colored; - ColorTypes m_colors[4]; - - // log levels: - // false: errors only, true: full query logging - bool m_sqlDriverQueryLogging; - - // log levels: - // 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug - uint8 m_dbLogLevel; - uint8 m_logLevel; - uint8 m_logFileLevel; - bool m_dbChar; - bool m_dbRA; - bool m_dbGM; - bool m_dbChat; - bool m_charLog_Dump; - bool m_charLog_Dump_Separate; - std::string m_dumpsDir; - - DebugLogFilters m_DebugLogMask; + LogWorker* worker; }; #define sLog ACE_Singleton::instance() #endif - -- cgit v1.2.3 From 5746b688fa156f2ea3a72a8f655042c24bdae8c4 Mon Sep 17 00:00:00 2001 From: Spp Date: Mon, 6 Aug 2012 09:30:47 +0200 Subject: Core/Logging: Reload Logging options when .reload config is used --- src/server/game/World/World.cpp | 1 + src/server/shared/Logging/Log.cpp | 26 +++++++++++++++----------- src/server/shared/Logging/Log.h | 1 + 3 files changed, 17 insertions(+), 11 deletions(-) (limited to 'src/server/shared/Logging/Log.h') diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 3a13f48d807..ab3b7150089 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -398,6 +398,7 @@ void World::LoadConfigSettings(bool reload) sLog->outError(LOG_FILTER_GENERAL, "World settings reload fail: can't read settings from %s.", ConfigMgr::GetFilename().c_str()); return; } + sLog->LoadFromConfig(); } ///- Read the player limit and the Message of the day from the config file diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index 0bf8bcded86..cce670922f4 100755 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -32,18 +32,8 @@ Log::Log() { SetRealmID(0); - AppenderId = 0; - /// Common log files data - m_logsDir = ConfigMgr::GetStringDefault("LogsDir", ""); - if (!m_logsDir.empty()) - if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) - m_logsDir.push_back('/'); - m_logsTimestamp = "_" + GetTimestampStr(); - - ReadAppendersFromConfig(); - ReadLoggersFromConfig(); - worker = new LogWorker(); + LoadFromConfig(); } Log::~Log() @@ -426,6 +416,20 @@ void Log::Close() it->second = NULL; } appenders.clear(); + loggers.clear(); delete worker; worker = NULL; } + +void Log::LoadFromConfig() +{ + Close(); + AppenderId = 0; + m_logsDir = ConfigMgr::GetStringDefault("LogsDir", ""); + if (!m_logsDir.empty()) + if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) + m_logsDir.push_back('/'); + ReadAppendersFromConfig(); + ReadLoggersFromConfig(); + worker = new LogWorker(); +} diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index 5e2b7972dc8..7b0e8cd381b 100755 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -40,6 +40,7 @@ class Log ~Log(); public: + void LoadFromConfig(); void Close(); bool ShouldLog(LogFilterType type, LogLevel level) const; bool SetLogLevel(std::string const& name, char const* level, bool isLogger = true); -- cgit v1.2.3 From 52a5991c1258073d561e8b74ef99a7b940808d92 Mon Sep 17 00:00:00 2001 From: Spp Date: Wed, 15 Aug 2012 19:58:02 +0200 Subject: Core/Logging: Added documentation about this system - Restored old CharDump (LOG_FILTER_PLAYER_DUMP) but disabled by default. - "%s" is now used to set dynamic file names, only used by GM commands and Player dump --- doc/LoggingHOWTO.txt | 276 ++++++++++++++++++++++++++ src/server/authserver/authserver.conf.dist | 2 +- src/server/game/Handlers/CharacterHandler.cpp | 8 +- src/server/shared/Logging/Appender.h | 9 +- src/server/shared/Logging/AppenderFile.cpp | 4 +- src/server/shared/Logging/Log.cpp | 22 +- src/server/shared/Logging/Log.h | 1 + src/server/worldserver/worldserver.conf.dist | 21 +- 8 files changed, 325 insertions(+), 18 deletions(-) create mode 100644 doc/LoggingHOWTO.txt (limited to 'src/server/shared/Logging/Log.h') diff --git a/doc/LoggingHOWTO.txt b/doc/LoggingHOWTO.txt new file mode 100644 index 00000000000..12850eb06cf --- /dev/null +++ b/doc/LoggingHOWTO.txt @@ -0,0 +1,276 @@ +Logging system "log4j-like" + +--- LOGGERS AND APPENDERS --- + +Logging system has two components: loggers and appenders. These types of +components enable users to log messages according to message type and level and +control at runtime where they are reported. + +LOGGERS + +The first and foremost advantage of this system resided in the ability to +disable certain log statements while allowing others to print unhindered. +This capability assumes that the loggers are categorized according to some +developer-chosen criteria. + +Loggers follow hierarchy, if a logger is not defined a root logger will be used + +Loggers may be assigned levels. The set of possible levels are TRACE, DEBUG, +INFO, WARN, ERROR AND FATAL, or be disabled using level DISABLED. + +By definition the printing method determines the level of a logging request. +For example, sLog->outInfo(...) is a logging request of level INFO. + +A logging request is said to be enabled if its level is higher than or equal to +the level of its logger. Otherwise, the request is said to be disabled. A logger +without an assigned level will inherit one from the hierarchy + +Example +Logger Name Assigned Level Inherited Level +root Proot Proot +Network None Proot + +As Network is not defined, it uses the root logger and it's log level. +TRACE < DEBUG < INFO < WARN < ERROR < FATAL. + + +APPENDERS + +The ability to selectively enable of dissable logging request based on their +loggers is only part of the picture. This system allows logging requests to +print to multiple destinations. An output destination is called an appender. +Current system defines appenders for Console, files and Database, but can be +easily extended to remote socket server, NT event loggers, syslog daemons or +any other system. + +More than one appender can be attached to one logger. Each enabled logging +request for a given logger will be forwarded to all the appenders in that +logger + + +CONFIGURATION + +System will read "Loggers" and "Appenders" to know the list of loggers and +appenders to read from config file. Both are a list of elements separated +by space. + +Once we have the list of appenders to read, system will try to configure a new +appender from its config line. Appender config line follows the format: + + Type,LogLevel,Flags,optional1,optional2 + +Its a list of elements separated by comma where each element has its own meaning + Type: Type of the appender + 1 - (Console) + 2 - (File) + 3 - (DB) + LogLevel: Log level + 0 - (Disabled) + 1 - (Trace) + 2 - (Debug) + 3 - (Info) + 4 - (Warn) + 5 - (Error) + 6 - (Fatal) + Flags: Define some extra modifications to do to logging message + 1 - Prefix Timestamp to the text + 2 - Prefix Log Level to the text + 4 - Prefix Log Filter type to the text + 8 - Append timestamp to the log file name. Format: YYYY-MM-DD_HH-MM-SS + (Only used with Type = 2) + 16 - Make a backup of existing file before overwrite + (Only used with Mode = w) + +Depending on the type, elements optional1 and optional2 will take different + + Colors (read as optional1 if Type = Console) + Format: "fatal error warn info debug trace" + 0 - BLACK + 1 - RED + 2 - GREEN + 3 - BROWN + 4 - BLUE + 5 - MAGENTA + 6 - CYAN + 7 - GREY + 8 - YELLOW + 9 - LRED + 10 - LGREEN + 11 - LBLUE + 12 - LMAGENTA + 13 - LCYAN + 14 - WHITE + Example: "13 11 9 5 3 1" + + File: Name of the file (read as optional1 if Type = File) + Allows to use one "%u" to create dynamic files + + Mode: Mode to open the file (read as optional2 if Type = File) + a - (Append) + w - (Overwrite) + +Example: + Appender.Console1=1,2,6 + + Creates new appender to log to console any message with log level DEBUG + or higher and prefixes log type and level to the message. + + Appender.Console2=1,5,1,13 11 9 5 3 1 + + Creates new appender to log to console any message with log level ERROR + or higher and prefixes timestamp to the message using colored text. + + Appender.File=2,2,7,Auth.log,w + + Creates new appender to log to file "Auth.log" any message with log level + DEBUG or higher and prefixes timestamp, type and level to message + +In the example, having two different loggers to log to console is perfectly +legal but redundant. + +Once we have the list of loggers to read, system will try to configure a new +logger from its config line. Logger config line follows the format: + + Type,LogLevel,AppenderList + +Its a list of elements separated by comma where each element has its own meaning + Type: Type of the logger ( + 0 - Default. Each type that has no config will + rely on this one. Core will create this logger + (disabled) if it's not configured + 1 - Units that doesn't fit in other categories + 2 - Pets + 3 - Vehicles + 4 - C++ AI, instance scripts, etc. + 5 - DB AI, such as SAI, EAI, CreatureAI + 6 - DB map scripts + 7 - Network input/output, + such as packet handlers and netcode logs + 8 - Spellsystem and aurasystem + 9 - Achievement system + 10 - Condition system + 11 - Pool system + 12 - Auction house + 13 - Arena's and battlegrounds + 14 - Outdoor PVP + 15 - Chat system + 16 - LFG system + 17 - Maps, instances (not scripts), + grids, cells, visibility, etc. + 18 - Player that doesn't fit in other categories. + 19 - Player loading from DB + (Player::_LoadXXX functions) + 20 - Items + 21 - Player skills (do not confuse with spells) + 22 - Player chat logs + 23 - loot + 24 - guilds + 25 - transports + 26 - SQL. DB errors + 27 - GM Commands + 28 - Remote Access Commands + 29 - Warden + 30 - Authserver + 31 - Worldserver + 32 - Game Events + 33 - Calendar + 34 - Character (Exclusive to login, logout, create, rename and delete) + 35 - Arenas + 36 - SQL Driver + 37 - SQL Dev + LogLevel + 0 - (Disabled) + 1 - (Trace) + 2 - (Debug) + 3 - (Info) + 4 - (Warn) + 5 - (Error) + 6 - (Fatal) + AppenderList: List of appenders linked to logger + (Using spaces as separator). + +--- EXAMPLES --- + +EXAMPLE 1 + +Log errors to console and a file called server.log that only contain +logs for this server run. File should prefix timestamp, type and log level to +the messages. Console should prefix type and log level. + + Appenders=Console Server + Loggers=Root + Appender.Console=1,5,6 + Appender.Server=2,5,7,Server.log,w + Logger.Root=0,5,Console Server + +Lets trace how system will log two different messages: + 1) sLog->outError(LOG_FILTER_GUILD, "Guild 1 created"); + System will try to find logger of type GUILD, as no logger is configured + for GUILD it will use Root logger. As message Log Level is equal or higher + than the Log level of logger the message is sent to the Appenders + configured in the Logger. "Console" and "Server". + Console will write: "ERROR [GUILD ] Guild 1 created" + Server will write to file "2012-08-15 ERROR [GUILD ] Guild 1 created" + + 2) sLog->outInfo(LOG_FILTER_CHARACTER, "Player Name Logged in"); + System will try to find logger of type CHARACTER, as no logger is + configured for CHARACTER it will use Root logger. As message Log Level is + not equal or higher than the Log level of logger the message its discarted. + +EXAMPLE 2 + +Same example that above, but now i want to see all messages of level INFO on +file and server file should add timestamp on creation. + + Appenders=Console Server + Loggers=Root + Appender.Console=1,5,6 + Appender.Server=2,4,15,Server.log + Logger.Root=0,4,Console Server + +Lets trace how system will log two different messages: + 1) sLog->outError(LOG_FILTER_GUILD, "Guild 1 created"); + Performs exactly as example 1. + 2) sLog->outInfo(LOG_FILTER_CHARACTER, "Player Name Logged in"); + System will try to find logger of type CHARACTER, as no logger is + configured for CHARACTER it will use Root logger. As message Log Level is + equal or higher than the Log level of logger the message is sent to the + Appenders configured in the Logger. "Console" and "Server". + Console will discard msg as Log Level is not higher or equal to this + appender + Server will write to file + "2012-08-15 INFO [CHARACTER ] Guild 1 Player Name Logged in" + +EXAMPLE 3 +As a dev, i may be interested in logging just a particular part of the core +while i'm trying to fix something. So... i want to debug GUILDS to maximum +and also some CHARACTER events to some point. Also im checking some Waypoints +so i want SQLDEV to be logged to file without prefixes. All other messages +should only be logged to console, GUILD to TRACE and CHARACTER to INFO + + Appenders=Console SQLDev + Loggers=Guild Characters SQLDev + Appender.Console=1,1 + Appender.SQLDev=2,2,0,SQLDev.log + Logger.Guild=24,1,Console + Logger.Characters=34,3,Console + Logger.SQLDev=37,3,SQLDev + +With this config, any message logger with a Log type different to GUILD, +CHARACTER or SQLDEV will be ignored, as we didn't define a logger Root and +system created a default Root disabled. Appender Console, log level should be +defined to allow all possible messages of its loggers, in this case GUILD uses +TRACE (1), so Appender should allow it. Logger Characters will limit it's own +messages to INFO (3) + +--- SOME EXTRA COMMENTS --- +why this system is better than previous one? +- Can be extended: Anyone can easily create new appenders to log to new + systems as syslog or IRC, having all code related to that system in particular + files +- It's asyncronous: Uses threads to write messages, so core performance wont be + affected by IO operations +- Lets us select "What to log" and "Where to log" on the fly. You can log to a + dozen of files without having to change a single line of code + + \ No newline at end of file diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist index d1c92dcf1d0..15dd02d9052 100644 --- a/src/server/authserver/authserver.conf.dist +++ b/src/server/authserver/authserver.conf.dist @@ -170,7 +170,7 @@ LoginDatabase.WorkerThreads = 1 # 5 - (Error) # 6 - (Fatal) # -# Flags: Default Console = 6, File = 7, DB = 0 +# Flags: # 0 - None # 1 - Prefix Timestamp to the text # 2 - Prefix Log Level to the text diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 7451bd2dc2a..8544266840f 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -719,11 +719,15 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket & recv_data) sScriptMgr->OnPlayerDelete(guid); sWorld->DeleteCharaceterNameData(GUID_LOPART(guid)); - if (sLog->ShouldLog(LOG_FILTER_CHARACTER, LOG_LEVEL_DEBUG)) // optimize GetPlayerDump call + if (sLog->ShouldLog(LOG_FILTER_PLAYER_DUMP, LOG_LEVEL_INFO)) // optimize GetPlayerDump call { std::string dump; if (PlayerDumpWriter().GetDump(GUID_LOPART(guid), dump)) - sLog->outDebug(LOG_FILTER_CHARACTER, dump.c_str(), GetAccountId(), GUID_LOPART(guid), name.c_str()); + { + std::ostringstream ss; + ss << GetAccountId() << '_' << name.c_str(); + sLog->outCharDump(ss.str().c_str(), dump.c_str(), GetAccountId(), GUID_LOPART(guid), name.c_str()); + } } Player::DeleteFromDB(guid, GetAccountId()); diff --git a/src/server/shared/Logging/Appender.h b/src/server/shared/Logging/Appender.h index 332edbf170c..ebe7408d400 100644 --- a/src/server/shared/Logging/Appender.h +++ b/src/server/shared/Logging/Appender.h @@ -62,10 +62,12 @@ enum LogFilterType LOG_FILTER_CHARACTER, LOG_FILTER_ARENAS, LOG_FILTER_SQL_DRIVER, - LOG_FILTER_SQL_DEV + LOG_FILTER_SQL_DEV, + LOG_FILTER_PLAYER_DUMP, + LOG_FILTER_BATTLEFIELD }; -const uint8 MaxLogFilter = uint8(LOG_FILTER_SQL_DEV) + 1; +const uint8 MaxLogFilter = uint8(LOG_FILTER_BATTLEFIELD) + 1; // Values assigned have their equivalent in enum ACE_Log_Priority enum LogLevel @@ -105,7 +107,6 @@ struct LogMessage : level(_level) , type(_type) , text(_text) - , param1(0) { mtime = time(NULL); } @@ -117,7 +118,7 @@ struct LogMessage LogFilterType type; std::string text; std::string prefix; - uint32 param1; + std::string param1; time_t mtime; }; diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp index 01a2f34baa7..67adff39aae 100644 --- a/src/server/shared/Logging/AppenderFile.cpp +++ b/src/server/shared/Logging/AppenderFile.cpp @@ -24,7 +24,7 @@ AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, co , logDir(_logDir) , mode(_mode) { - dynamicName = std::string::npos != filename.find("%u"); + dynamicName = std::string::npos != filename.find("%s"); backup = _flags & APPENDER_FLAGS_MAKE_FILE_BACKUP; logfile = !dynamicName ? OpenFile(_filename, _mode, backup) : NULL; @@ -44,7 +44,7 @@ void AppenderFile::_write(LogMessage& message) if (dynamicName) { char namebuf[TRINITY_PATH_MAX]; - snprintf(namebuf, TRINITY_PATH_MAX, filename.c_str(), message.param1); + snprintf(namebuf, TRINITY_PATH_MAX, filename.c_str(), message.param1.c_str()); logfile = OpenFile(namebuf, mode, backup); } diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index 27f33754da9..64f7e697f1f 100755 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -449,6 +449,23 @@ void Log::outFatal(LogFilterType filter, const char * str, ...) va_end(ap); } +void Log::outCharDump(const char* param, const char * str, ...) +{ + if (!str || !ShouldLog(LOG_FILTER_PLAYER_DUMP, LOG_LEVEL_INFO)) + return; + + va_list ap; + va_start(ap, str); + char text[MAX_QUERY_LEN]; + vsnprintf(text, MAX_QUERY_LEN, str, ap); + va_end(ap); + + LogMessage* msg = new LogMessage(LOG_LEVEL_INFO, LOG_FILTER_PLAYER_DUMP, text); + msg->param1 = param; + + write(msg); +} + void Log::outCommand(uint32 account, const char * str, ...) { if (!str || !ShouldLog(LOG_FILTER_GMCOMMAND, LOG_LEVEL_INFO)) @@ -461,7 +478,10 @@ void Log::outCommand(uint32 account, const char * str, ...) va_end(ap); LogMessage* msg = new LogMessage(LOG_LEVEL_INFO, LOG_FILTER_GMCOMMAND, text); - msg->param1 = account; + + std::ostringstream ss; + ss << account; + msg->param1 = ss.str(); write(msg); } diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index 7b0e8cd381b..cd1e9dc80df 100755 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -56,6 +56,7 @@ class Log void EnableDBAppenders(); void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4); + void outCharDump(const char* param, const char* str, ...) ATTR_PRINTF(3, 4); static std::string GetTimestampStr(); void SetRealmID(uint32 id); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index be5a452c7b4..789af4e371b 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -2592,7 +2592,7 @@ PlayerDump.DisallowOverwrite = 1 # 5 - (Error) # 6 - (Fatal) # -# Flags: Default Console = 6, File = 7, DB = 0 +# Flags: # 0 - None # 1 - Prefix Timestamp to the text # 2 - Prefix Log Level to the text @@ -2629,13 +2629,14 @@ PlayerDump.DisallowOverwrite = 1 Appender.Console=1,2,6 Appender.Server=2,2,7,Server.log,w -Appender.GM=2,2,7,GM.log +Appender.GM=2,2,7,GM_%s.log Appender.SQL=2,2,7,SQL.log Appender.DBErrors=2,2,7,DBErrors.log Appender.Char=2,2,7,Char.log,w +Appender.CharDump=2,2,0,chardumps/%s.log Appender.RA=2,2,7,RA.log Appender.Arenas=2,2,7,Arena.log -Appender.SQLDev=2,2,7,SQLDev.log +Appender.SQLDev=2,2,0,SQLDev.log Appender.SQLDriver=2,2,7,SQLDriver.log Appender.Warden=2,2,7,Warden.log Appender.Chat=2,2,7,Chat.log @@ -2684,12 +2685,14 @@ Appender.Chat=2,2,7,Chat.log # 31 - Worldserver # 32 - Game Events # 33 - Calendar -# 34 - Character (Exclusive to log login, logout, create, rename, delete actions) +# 34 - Character (Exclusive to log login, logout, create, rename) # 35 - Arenas # 36 - SQL Driver # 37 - SQL Dev +# 38 - Player Dump +# 39 - Battlefield -Logger.Root=0,5,Console Server +Logger.Root=0,3,Console Server Logger.Units=1,3,Console Server Logger.Pets=2,3,Console Server Logger.Vehicles=3,3,Console Server @@ -2715,7 +2718,7 @@ Logger.PlayerChat=22,3,Chat Logger.Loot=23,3,Console Server Logger.Guilds=24,3,Console Server Logger.Transports=25,3,Console Server -Logger.SQL=26,2,Console Server SQL +Logger.SQL=26,2,Console Server DBErrors Logger.GM=27,3,Console Server GM Logger.RA=28,3,RA Logger.Warden=29,3,Warden @@ -2727,6 +2730,8 @@ Logger.Character=34,3,Char Logger.Arenas=35,3,Arenas Logger.SQLDriver=36,5,SQLDriver Logger.SQLDev=37,3,SQLDev +Logger.CharDump=38,5,CharDump +Logger.Battlefield=39,3,Console Server # LogLevel # 0 - (Disabled) @@ -2745,7 +2750,7 @@ Logger.SQLDev=37,3,SQLDev # (Using spaces as separator). # Default: "Console Server" -Appenders=Console Server +Appenders=Console Server GM Char Arenas Warden DBErrors CharDump # # Loggers @@ -2753,4 +2758,4 @@ Appenders=Console Server # (Using spaces as separator). # Default: "root" -Loggers=Root +Loggers=Root GM Character Arenas Warden SQL -- cgit v1.2.3