2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "Policies/SingletonImp.h"
22 #include "Config/ConfigEnv.h"
24 #include "ByteBuffer.h"
28 INSTANTIATE_SINGLETON_1( Log
);
38 const int LogType_count
= int(LogError
) +1;
41 raLogfile(NULL
), logfile(NULL
), gmLogfile(NULL
), charLogfile(NULL
),
42 dberLogfile(NULL
), m_colored(false), m_includeTime(false), m_gmlog_per_account(false)
47 void Log::InitColors(const std::string
& str
)
57 std::istringstream
ss(str
);
59 for(int i
= 0; i
< LogType_count
; ++i
)
66 if(color
[i
] < 0 || color
[i
] >= Color_count
)
70 for(int i
= 0; i
< LogType_count
; ++i
)
71 m_colors
[i
] = Color(color
[i
]);
76 void Log::SetColor(bool stdout_stream
, Color color
)
78 #if PLATFORM == PLATFORM_WINDOWS
80 static WORD WinColorFG
[Color_count
] =
83 FOREGROUND_RED
, // RED
84 FOREGROUND_GREEN
, // GREEN
85 FOREGROUND_RED
| FOREGROUND_GREEN
, // BROWN
86 FOREGROUND_BLUE
, // BLUE
87 FOREGROUND_RED
| FOREGROUND_BLUE
,// MAGENTA
88 FOREGROUND_GREEN
| FOREGROUND_BLUE
, // CYAN
89 FOREGROUND_RED
| FOREGROUND_GREEN
| FOREGROUND_BLUE
,// WHITE
91 FOREGROUND_RED
| FOREGROUND_GREEN
| FOREGROUND_INTENSITY
,
93 FOREGROUND_RED
| FOREGROUND_INTENSITY
,
95 FOREGROUND_GREEN
| FOREGROUND_INTENSITY
,
96 FOREGROUND_BLUE
| FOREGROUND_INTENSITY
, // BLUE_BOLD
98 FOREGROUND_RED
| FOREGROUND_BLUE
| FOREGROUND_INTENSITY
,
100 FOREGROUND_GREEN
| FOREGROUND_BLUE
| FOREGROUND_INTENSITY
,
102 FOREGROUND_RED
| FOREGROUND_GREEN
| FOREGROUND_BLUE
| FOREGROUND_INTENSITY
105 HANDLE hConsole
= GetStdHandle(stdout_stream
? STD_OUTPUT_HANDLE
: STD_ERROR_HANDLE
);
106 SetConsoleTextAttribute(hConsole
, WinColorFG
[color
]);
119 FG_BLACK
=30, FG_RED
, FG_GREEN
, FG_BROWN
, FG_BLUE
,
120 FG_MAGENTA
, FG_CYAN
, FG_WHITE
, FG_YELLOW
125 BG_BLACK
=40, BG_RED
, BG_GREEN
, BG_BROWN
, BG_BLUE
,
126 BG_MAGENTA
, BG_CYAN
, BG_WHITE
129 static uint8 UnixColorFG
[Color_count
] =
136 FG_MAGENTA
, // MAGENTA
143 FG_MAGENTA
, // LMAGENTA
148 fprintf((stdout_stream
? stdout
: stderr
), "\x1b[%d%sm",UnixColorFG
[color
],(color
>=YELLOW
&&color
<Color_count
?";1":""));
152 void Log::ResetColor(bool stdout_stream
)
154 #if PLATFORM == PLATFORM_WINDOWS
155 HANDLE hConsole
= GetStdHandle(stdout_stream
? STD_OUTPUT_HANDLE
: STD_ERROR_HANDLE
);
156 SetConsoleTextAttribute(hConsole
, FOREGROUND_BLUE
| FOREGROUND_GREEN
| FOREGROUND_RED
);
158 fprintf(( stdout_stream
? stdout
: stderr
), "\x1b[0m");
162 void Log::SetLogLevel(char *Level
)
164 int32 NewLevel
=atoi((char*)Level
);
167 m_logLevel
= NewLevel
;
169 printf( "LogLevel is %u\n",m_logLevel
);
172 void Log::SetLogFileLevel(char *Level
)
174 int32 NewLevel
=atoi((char*)Level
);
177 m_logFileLevel
= NewLevel
;
179 printf( "LogFileLevel is %u\n",m_logFileLevel
);
182 void Log::Initialize()
184 /// Common log files data
185 m_logsDir
= sConfig
.GetStringDefault("LogsDir","");
186 if(!m_logsDir
.empty())
188 if((m_logsDir
.at(m_logsDir
.length()-1)!='/') && (m_logsDir
.at(m_logsDir
.length()-1)!='\\'))
189 m_logsDir
.append("/");
192 m_logsTimestamp
= "_" + GetTimestampStr();
194 /// Open specific log files
195 logfile
= openLogFile("LogFile","LogTimestamp","w");
197 m_gmlog_per_account
= sConfig
.GetBoolDefault("GmLogPerAccount",false);
198 if(!m_gmlog_per_account
)
199 gmLogfile
= openLogFile("GMLogFile","GmLogTimestamp","a");
202 // GM log settings for per account case
203 m_gmlog_filename_format
= sConfig
.GetStringDefault("GMLogFile", "");
204 if(!m_gmlog_filename_format
.empty())
206 bool m_gmlog_timestamp
= sConfig
.GetBoolDefault("GmLogTimestamp",false);
208 size_t dot_pos
= m_gmlog_filename_format
.find_last_of(".");
209 if(dot_pos
!=m_gmlog_filename_format
.npos
)
211 if(m_gmlog_timestamp
)
212 m_gmlog_filename_format
.insert(dot_pos
,m_logsTimestamp
);
214 m_gmlog_filename_format
.insert(dot_pos
,"_#%u");
218 m_gmlog_filename_format
+= "_#%u";
220 if(m_gmlog_timestamp
)
221 m_gmlog_filename_format
+= m_logsTimestamp
;
224 m_gmlog_filename_format
= m_logsDir
+ m_gmlog_filename_format
;
228 charLogfile
= openLogFile("CharLogFile","CharLogTimestamp","a");
229 dberLogfile
= openLogFile("DBErrorLogFile",NULL
,"a");
230 raLogfile
= openLogFile("RaLogFile",NULL
,"a");
231 worldLogfile
= openLogFile("WorldLogFile","WorldLogTimestamp","a");
233 // Main log file settings
234 m_includeTime
= sConfig
.GetBoolDefault("LogTime", false);
235 m_logLevel
= sConfig
.GetIntDefault("LogLevel", 0);
236 m_logFileLevel
= sConfig
.GetIntDefault("LogFileLevel", 0);
237 InitColors(sConfig
.GetStringDefault("LogColors", ""));
241 if(sConfig
.GetBoolDefault("LogFilter_TransportMoves", true))
242 m_logFilter
|= LOG_FILTER_TRANSPORT_MOVES
;
243 if(sConfig
.GetBoolDefault("LogFilter_CreatureMoves", true))
244 m_logFilter
|= LOG_FILTER_CREATURE_MOVES
;
245 if(sConfig
.GetBoolDefault("LogFilter_VisibilityChanges", true))
246 m_logFilter
|= LOG_FILTER_VISIBILITY_CHANGES
;
247 if(sConfig
.GetBoolDefault("LogFilter_AchievementUpdates", true))
248 m_logFilter
|= LOG_FILTER_ACHIEVEMENT_UPDATES
;
251 m_charLog_Dump
= sConfig
.GetBoolDefault("CharLogDump", false);
254 FILE* Log::openLogFile(char const* configFileName
,char const* configTimeStampFlag
, char const* mode
)
256 std::string logfn
=sConfig
.GetStringDefault(configFileName
, "");
260 if(configTimeStampFlag
&& sConfig
.GetBoolDefault(configTimeStampFlag
,false))
262 size_t dot_pos
= logfn
.find_last_of(".");
263 if(dot_pos
!=logfn
.npos
)
264 logfn
.insert(dot_pos
,m_logsTimestamp
);
266 logfn
+= m_logsTimestamp
;
269 return fopen((m_logsDir
+logfn
).c_str(), mode
);
272 FILE* Log::openGmlogPerAccount(uint32 account
)
274 if(m_gmlog_filename_format
.empty())
277 char namebuf
[MANGOS_PATH_MAX
];
278 snprintf(namebuf
,MANGOS_PATH_MAX
,m_gmlog_filename_format
.c_str(),account
);
279 return fopen(namebuf
, "a");
282 void Log::outTimestamp(FILE* file
)
284 time_t t
= time(NULL
);
285 tm
* aTm
= localtime(&t
);
287 // MM month (2 digits 01-12)
288 // DD day (2 digits 01-31)
289 // HH hour (2 digits 00-23)
290 // MM minutes (2 digits 00-59)
291 // SS seconds (2 digits 00-59)
292 fprintf(file
,"%-4d-%02d-%02d %02d:%02d:%02d ",aTm
->tm_year
+1900,aTm
->tm_mon
+1,aTm
->tm_mday
,aTm
->tm_hour
,aTm
->tm_min
,aTm
->tm_sec
);
297 time_t t
= time(NULL
);
298 tm
* aTm
= localtime(&t
);
300 // MM month (2 digits 01-12)
301 // DD day (2 digits 01-31)
302 // HH hour (2 digits 00-23)
303 // MM minutes (2 digits 00-59)
304 // SS seconds (2 digits 00-59)
305 printf("%02d:%02d:%02d ",aTm
->tm_hour
,aTm
->tm_min
,aTm
->tm_sec
);
308 std::string
Log::GetTimestampStr()
310 time_t t
= time(NULL
);
311 tm
* aTm
= localtime(&t
);
313 // MM month (2 digits 01-12)
314 // DD day (2 digits 01-31)
315 // HH hour (2 digits 00-23)
316 // MM minutes (2 digits 00-59)
317 // SS seconds (2 digits 00-59)
319 snprintf(buf
,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm
->tm_year
+1900,aTm
->tm_mon
+1,aTm
->tm_mday
,aTm
->tm_hour
,aTm
->tm_min
,aTm
->tm_sec
);
320 return std::string(buf
);
323 void Log::outTitle( const char * str
)
329 SetColor(true,WHITE
);
331 // not expected utf8 and then send as-is
340 fprintf(logfile
, "%s", str
);
341 fprintf(logfile
, "\n" );
348 void Log::outString()
355 outTimestamp(logfile
);
356 fprintf(logfile
, "\n" );
362 void Log::outString( const char * str
, ... )
368 SetColor(true,m_colors
[LogNormal
]);
376 vutf8printf(stdout
, str
, &ap
);
385 outTimestamp(logfile
);
388 vfprintf(logfile
, str
, ap
);
389 fprintf(logfile
, "\n" );
397 void Log::outError( const char * err
, ... )
403 SetColor(false,m_colors
[LogError
]);
411 vutf8printf(stderr
, err
, &ap
);
417 fprintf( stderr
, "\n" );
420 outTimestamp(logfile
);
421 fprintf(logfile
, "ERROR:" );
424 vfprintf(logfile
, err
, ap
);
427 fprintf(logfile
, "\n" );
433 void Log::outErrorDb( const char * err
, ... )
439 SetColor(false,m_colors
[LogError
]);
447 vutf8printf(stderr
, err
, &ap
);
453 fprintf( stderr
, "\n" );
457 outTimestamp(logfile
);
458 fprintf(logfile
, "ERROR:" );
461 vfprintf(logfile
, err
, ap
);
464 fprintf(logfile
, "\n" );
470 outTimestamp(dberLogfile
);
474 vfprintf(dberLogfile
, err
, ap
);
477 fprintf(dberLogfile
, "\n" );
483 void Log::outBasic( const char * str
, ... )
491 SetColor(true,m_colors
[LogDetails
]);
498 vutf8printf(stdout
, str
, &ap
);
507 if(logfile
&& m_logFileLevel
> 0)
510 outTimestamp(logfile
);
512 vfprintf(logfile
, str
, ap
);
513 fprintf(logfile
, "\n" );
520 void Log::outDetail( const char * str
, ... )
529 SetColor(true,m_colors
[LogDetails
]);
536 vutf8printf(stdout
, str
, &ap
);
544 if(logfile
&& m_logFileLevel
> 1)
546 outTimestamp(logfile
);
550 vfprintf(logfile
, str
, ap
);
553 fprintf(logfile
, "\n" );
560 void Log::outDebugInLine( const char * str
, ... )
567 SetColor(true,m_colors
[LogDebug
]);
571 vutf8printf(stdout
, str
, &ap
);
577 if(logfile
&& m_logFileLevel
> 2)
581 vfprintf(logfile
, str
, ap
);
586 void Log::outDebug( const char * str
, ... )
593 SetColor(true,m_colors
[LogDebug
]);
600 vutf8printf(stdout
, str
, &ap
);
608 if(logfile
&& m_logFileLevel
> 2)
610 outTimestamp(logfile
);
614 vfprintf(logfile
, str
, ap
);
617 fprintf(logfile
, "\n" );
623 void Log::outCommand( uint32 account
, const char * str
, ... )
631 SetColor(true,m_colors
[LogDetails
]);
638 vutf8printf(stdout
, str
, &ap
);
646 if(logfile
&& m_logFileLevel
> 1)
649 outTimestamp(logfile
);
651 vfprintf(logfile
, str
, ap
);
652 fprintf(logfile
, "\n" );
657 if (m_gmlog_per_account
)
659 if (FILE* per_file
= openGmlogPerAccount (account
))
662 outTimestamp(per_file
);
664 vfprintf(per_file
, str
, ap
);
665 fprintf(per_file
, "\n" );
673 outTimestamp(gmLogfile
);
675 vfprintf(gmLogfile
, str
, ap
);
676 fprintf(gmLogfile
, "\n" );
684 void Log::outChar(const char * str
, ... )
693 outTimestamp(charLogfile
);
695 vfprintf(charLogfile
, str
, ap
);
696 fprintf(charLogfile
, "\n" );
702 void Log::outWorldPacketDump( uint32 socket
, uint32 opcode
, char const* opcodeName
, ByteBuffer
const* packet
, bool incoming
)
707 outTimestamp(worldLogfile
);
709 fprintf(worldLogfile
,"\n%s:\nSOCKET: %u\nLENGTH: " SIZEFMTD
"\nOPCODE: %s (0x%.4X)\nDATA:\n",
710 incoming
? "CLIENT" : "SERVER",
711 socket
, packet
->size(), opcodeName
, opcode
);
714 while (p
< packet
->size())
716 for (size_t j
= 0; j
< 16 && p
< packet
->size(); ++j
)
717 fprintf(worldLogfile
, "%.2X ", (*packet
)[p
++]);
719 fprintf(worldLogfile
, "\n");
722 fprintf(worldLogfile
, "\n\n");
723 fflush(worldLogfile
);
726 void Log::outCharDump( const char * str
, uint32 account_id
, uint32 guid
, const char * name
)
730 fprintf(charLogfile
, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n",account_id
,guid
,name
,str
);
735 void Log::outMenu( const char * str
, ... )
740 SetColor(true,m_colors
[LogNormal
]);
748 vutf8printf(stdout
, str
, &ap
);
755 outTimestamp(logfile
);
758 vfprintf(logfile
, str
, ap
);
761 fprintf(logfile
, "\n" );
767 void Log::outRALog( const char * str
, ... )
774 outTimestamp(raLogfile
);
776 vfprintf(raLogfile
, str
, ap
);
777 fprintf(raLogfile
, "\n" );
784 void outstring_log(const char * str
, ...)
792 vsnprintf(buf
, 256, str
, ap
);
795 sLog
.outString("%s", buf
);
798 void detail_log(const char * str
, ...)
806 vsnprintf(buf
,256, str
, ap
);
809 sLog
.outDetail("%s", buf
);
812 void debug_log(const char * str
, ...)
820 vsnprintf(buf
,256, str
, ap
);
823 sLog
.outDebug("%s", buf
);
826 void error_log(const char * str
, ...)
834 vsnprintf(buf
,256, str
, ap
);
837 sLog
.outError("%s", buf
);
840 void error_db_log(const char * str
, ...)
848 vsnprintf(buf
,256, str
, ap
);
851 sLog
.outErrorDb("%s", buf
);