2 * Copyright (C) 2005-2009 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"
27 INSTANTIATE_SINGLETON_1( Log
);
37 const int LogType_count
= int(LogError
) +1;
40 raLogfile(NULL
), logfile(NULL
), gmLogfile(NULL
), charLogfile(NULL
),
41 dberLogfile(NULL
), m_colored(false), m_includeTime(false), m_gmlog_per_account(false)
46 void Log::InitColors(const std::string
& str
)
56 std::istringstream
ss(str
);
58 for(int i
= 0; i
< LogType_count
; ++i
)
65 if(color
[i
] < 0 || color
[i
] >= Color_count
)
69 for(int i
= 0; i
< LogType_count
; ++i
)
70 m_colors
[i
] = Color(color
[i
]);
75 void Log::SetColor(bool stdout_stream
, Color color
)
77 #if PLATFORM == PLATFORM_WINDOWS
79 static WORD WinColorFG
[Color_count
] =
82 FOREGROUND_RED
, // RED
83 FOREGROUND_GREEN
, // GREEN
84 FOREGROUND_RED
| FOREGROUND_GREEN
, // BROWN
85 FOREGROUND_BLUE
, // BLUE
86 FOREGROUND_RED
| FOREGROUND_BLUE
,// MAGENTA
87 FOREGROUND_GREEN
| FOREGROUND_BLUE
, // CYAN
88 FOREGROUND_RED
| FOREGROUND_GREEN
| FOREGROUND_BLUE
,// WHITE
90 FOREGROUND_RED
| FOREGROUND_GREEN
| FOREGROUND_INTENSITY
,
92 FOREGROUND_RED
| FOREGROUND_INTENSITY
,
94 FOREGROUND_GREEN
| FOREGROUND_INTENSITY
,
95 FOREGROUND_BLUE
| FOREGROUND_INTENSITY
, // BLUE_BOLD
97 FOREGROUND_RED
| FOREGROUND_BLUE
| FOREGROUND_INTENSITY
,
99 FOREGROUND_GREEN
| FOREGROUND_BLUE
| FOREGROUND_INTENSITY
,
101 FOREGROUND_RED
| FOREGROUND_GREEN
| FOREGROUND_BLUE
| FOREGROUND_INTENSITY
104 HANDLE hConsole
= GetStdHandle(stdout_stream
? STD_OUTPUT_HANDLE
: STD_ERROR_HANDLE
);
105 SetConsoleTextAttribute(hConsole
, WinColorFG
[color
]);
118 FG_BLACK
=30, FG_RED
, FG_GREEN
, FG_BROWN
, FG_BLUE
,
119 FG_MAGENTA
, FG_CYAN
, FG_WHITE
, FG_YELLOW
124 BG_BLACK
=40, BG_RED
, BG_GREEN
, BG_BROWN
, BG_BLUE
,
125 BG_MAGENTA
, BG_CYAN
, BG_WHITE
128 static uint8 UnixColorFG
[Color_count
] =
135 FG_MAGENTA
, // MAGENTA
142 FG_MAGENTA
, // LMAGENTA
147 fprintf((stdout_stream
? stdout
: stderr
), "\x1b[%d%sm",UnixColorFG
[color
],(color
>=YELLOW
&&color
<Color_count
?";1":""));
151 void Log::ResetColor(bool stdout_stream
)
153 #if PLATFORM == PLATFORM_WINDOWS
154 HANDLE hConsole
= GetStdHandle(stdout_stream
? STD_OUTPUT_HANDLE
: STD_ERROR_HANDLE
);
155 SetConsoleTextAttribute(hConsole
, FOREGROUND_BLUE
| FOREGROUND_GREEN
| FOREGROUND_RED
);
157 fprintf(( stdout_stream
? stdout
: stderr
), "\x1b[0m");
161 void Log::SetLogLevel(char *Level
)
163 int32 NewLevel
=atoi((char*)Level
);
166 m_logLevel
= NewLevel
;
168 printf( "LogLevel is %u\n",m_logLevel
);
171 void Log::SetLogFileLevel(char *Level
)
173 int32 NewLevel
=atoi((char*)Level
);
176 m_logFileLevel
= NewLevel
;
178 printf( "LogFileLevel is %u\n",m_logFileLevel
);
181 void Log::Initialize()
183 /// Common log files data
184 m_logsDir
= sConfig
.GetStringDefault("LogsDir","");
185 if(!m_logsDir
.empty())
187 if((m_logsDir
.at(m_logsDir
.length()-1)!='/') && (m_logsDir
.at(m_logsDir
.length()-1)!='\\'))
188 m_logsDir
.append("/");
191 m_logsTimestamp
= "_" + GetTimestampStr();
193 /// Open specific log files
194 logfile
= openLogFile("LogFile","LogTimestamp","w");
196 m_gmlog_per_account
= sConfig
.GetBoolDefault("GmLogPerAccount",false);
197 if(!m_gmlog_per_account
)
198 gmLogfile
= openLogFile("GMLogFile","GmLogTimestamp","a");
201 // GM log settings for per account case
202 m_gmlog_filename_format
= sConfig
.GetStringDefault("GMLogFile", "");
203 if(!m_gmlog_filename_format
.empty())
205 bool m_gmlog_timestamp
= sConfig
.GetBoolDefault("GmLogTimestamp",false);
207 size_t dot_pos
= m_gmlog_filename_format
.find_last_of(".");
208 if(dot_pos
!=m_gmlog_filename_format
.npos
)
210 if(m_gmlog_timestamp
)
211 m_gmlog_filename_format
.insert(dot_pos
,m_logsTimestamp
);
213 m_gmlog_filename_format
.insert(dot_pos
,"_#%u");
217 m_gmlog_filename_format
+= "_#%u";
219 if(m_gmlog_timestamp
)
220 m_gmlog_filename_format
+= m_logsTimestamp
;
223 m_gmlog_filename_format
= m_logsDir
+ m_gmlog_filename_format
;
227 charLogfile
= openLogFile("CharLogFile","CharLogTimestamp","a");
229 dberLogfile
= openLogFile("DBErrorLogFile",NULL
,"a");
230 raLogfile
= openLogFile("RaLogFile",NULL
,"a");
232 // Main log file settings
233 m_includeTime
= sConfig
.GetBoolDefault("LogTime", false);
234 m_logLevel
= sConfig
.GetIntDefault("LogLevel", 0);
235 m_logFileLevel
= sConfig
.GetIntDefault("LogFileLevel", 0);
236 InitColors(sConfig
.GetStringDefault("LogColors", ""));
240 if(sConfig
.GetBoolDefault("LogFilter_TransportMoves", true))
241 m_logFilter
|= LOG_FILTER_TRANSPORT_MOVES
;
242 if(sConfig
.GetBoolDefault("LogFilter_CreatureMoves", true))
243 m_logFilter
|= LOG_FILTER_CREATURE_MOVES
;
244 if(sConfig
.GetBoolDefault("LogFilter_VisibilityChanges", true))
245 m_logFilter
|= LOG_FILTER_VISIBILITY_CHANGES
;
246 if(sConfig
.GetBoolDefault("LogFilter_AchievementUpdates", true))
247 m_logFilter
|= LOG_FILTER_ACHIEVEMENT_UPDATES
;
250 m_charLog_Dump
= sConfig
.GetBoolDefault("CharLogDump", false);
253 FILE* Log::openLogFile(char const* configFileName
,char const* configTimeStampFlag
, char const* mode
)
255 std::string logfn
=sConfig
.GetStringDefault(configFileName
, "");
259 if(configTimeStampFlag
&& sConfig
.GetBoolDefault(configTimeStampFlag
,false))
261 size_t dot_pos
= logfn
.find_last_of(".");
262 if(dot_pos
!=logfn
.npos
)
263 logfn
.insert(dot_pos
,m_logsTimestamp
);
265 logfn
+= m_logsTimestamp
;
268 return fopen((m_logsDir
+logfn
).c_str(), mode
);
271 FILE* Log::openGmlogPerAccount(uint32 account
)
273 if(m_gmlog_filename_format
.empty())
276 char namebuf
[MANGOS_PATH_MAX
];
277 snprintf(namebuf
,MANGOS_PATH_MAX
,m_gmlog_filename_format
.c_str(),account
);
278 return fopen(namebuf
, "a");
281 void Log::outTimestamp(FILE* file
)
283 time_t t
= time(NULL
);
284 tm
* aTm
= localtime(&t
);
286 // MM month (2 digits 01-12)
287 // DD day (2 digits 01-31)
288 // HH hour (2 digits 00-23)
289 // MM minutes (2 digits 00-59)
290 // SS seconds (2 digits 00-59)
291 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
);
296 time_t t
= time(NULL
);
297 tm
* aTm
= localtime(&t
);
299 // MM month (2 digits 01-12)
300 // DD day (2 digits 01-31)
301 // HH hour (2 digits 00-23)
302 // MM minutes (2 digits 00-59)
303 // SS seconds (2 digits 00-59)
304 printf("%02d:%02d:%02d ",aTm
->tm_hour
,aTm
->tm_min
,aTm
->tm_sec
);
307 std::string
Log::GetTimestampStr()
309 time_t t
= time(NULL
);
310 tm
* aTm
= localtime(&t
);
312 // MM month (2 digits 01-12)
313 // DD day (2 digits 01-31)
314 // HH hour (2 digits 00-23)
315 // MM minutes (2 digits 00-59)
316 // SS seconds (2 digits 00-59)
318 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
);
319 return std::string(buf
);
322 void Log::outTitle( const char * str
)
328 SetColor(true,WHITE
);
330 // not expected utf8 and then send as-is
339 fprintf(logfile
, str
);
340 fprintf(logfile
, "\n" );
347 void Log::outString()
354 outTimestamp(logfile
);
355 fprintf(logfile
, "\n" );
361 void Log::outString( const char * str
, ... )
367 SetColor(true,m_colors
[LogNormal
]);
372 UTF8PRINTF(stdout
,str
,);
380 outTimestamp(logfile
);
384 vfprintf(logfile
, str
, ap
);
385 fprintf(logfile
, "\n" );
393 void Log::outError( const char * err
, ... )
399 SetColor(false,m_colors
[LogError
]);
404 UTF8PRINTF(stderr
,err
,);
409 fprintf( stderr
, "\n" );
412 outTimestamp(logfile
);
413 fprintf(logfile
, "ERROR:" );
417 vfprintf(logfile
, err
, ap
);
420 fprintf(logfile
, "\n" );
426 void Log::outErrorDb( const char * err
, ... )
432 SetColor(false,m_colors
[LogError
]);
437 UTF8PRINTF(stderr
,err
,);
442 fprintf( stderr
, "\n" );
446 outTimestamp(logfile
);
447 fprintf(logfile
, "ERROR:" );
451 vfprintf(logfile
, err
, ap
);
454 fprintf(logfile
, "\n" );
460 outTimestamp(dberLogfile
);
464 vfprintf(dberLogfile
, err
, ap
);
467 fprintf(dberLogfile
, "\n" );
473 void Log::outBasic( const char * str
, ... )
481 SetColor(true,m_colors
[LogDetails
]);
486 UTF8PRINTF(stdout
,str
,);
494 if(logfile
&& m_logFileLevel
> 0)
497 outTimestamp(logfile
);
499 vfprintf(logfile
, str
, ap
);
500 fprintf(logfile
, "\n" );
507 void Log::outDetail( const char * str
, ... )
516 SetColor(true,m_colors
[LogDetails
]);
521 UTF8PRINTF(stdout
,str
,);
528 if(logfile
&& m_logFileLevel
> 1)
531 outTimestamp(logfile
);
533 vfprintf(logfile
, str
, ap
);
534 fprintf(logfile
, "\n" );
542 void Log::outDebugInLine( const char * str
, ... )
549 SetColor(true,m_colors
[LogDebug
]);
551 UTF8PRINTF(stdout
,str
,);
556 if(logfile
&& m_logFileLevel
> 2)
560 vfprintf(logfile
, str
, ap
);
565 void Log::outDebug( const char * str
, ... )
572 SetColor(true,m_colors
[LogDebug
]);
577 UTF8PRINTF(stdout
,str
,);
584 if(logfile
&& m_logFileLevel
> 2)
586 outTimestamp(logfile
);
590 vfprintf(logfile
, str
, ap
);
593 fprintf(logfile
, "\n" );
599 void Log::outCommand( uint32 account
, const char * str
, ... )
607 SetColor(true,m_colors
[LogDetails
]);
612 UTF8PRINTF(stdout
,str
,);
619 if(logfile
&& m_logFileLevel
> 1)
622 outTimestamp(logfile
);
624 vfprintf(logfile
, str
, ap
);
625 fprintf(logfile
, "\n" );
630 if (m_gmlog_per_account
)
632 if (FILE* per_file
= openGmlogPerAccount (account
))
635 outTimestamp(per_file
);
637 vfprintf(per_file
, str
, ap
);
638 fprintf(per_file
, "\n" );
646 outTimestamp(gmLogfile
);
648 vfprintf(gmLogfile
, str
, ap
);
649 fprintf(gmLogfile
, "\n" );
657 void Log::outChar(const char * str
, ... )
666 outTimestamp(charLogfile
);
668 vfprintf(charLogfile
, str
, ap
);
669 fprintf(charLogfile
, "\n" );
675 void Log::outCharDump( const char * str
, uint32 account_id
, uint32 guid
, const char * name
)
679 fprintf(charLogfile
, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n",account_id
,guid
,name
,str
);
684 void Log::outMenu( const char * str
, ... )
689 SetColor(true,m_colors
[LogNormal
]);
694 UTF8PRINTF(stdout
,str
,);
700 outTimestamp(logfile
);
704 vfprintf(logfile
, str
, ap
);
707 fprintf(logfile
, "\n" );
713 void Log::outRALog( const char * str
, ... )
720 outTimestamp(raLogfile
);
722 vfprintf(raLogfile
, str
, ap
);
723 fprintf(raLogfile
, "\n" );
730 void outstring_log(const char * str
, ...)
738 vsnprintf(buf
,256, str
, ap
);
741 MaNGOS::Singleton
<Log
>::Instance().outString(buf
);
744 void detail_log(const char * str
, ...)
752 vsnprintf(buf
,256, str
, ap
);
755 MaNGOS::Singleton
<Log
>::Instance().outDetail(buf
);
758 void debug_log(const char * str
, ...)
766 vsnprintf(buf
,256, str
, ap
);
769 MaNGOS::Singleton
<Log
>::Instance().outDebug(buf
);
772 void error_log(const char * str
, ...)
780 vsnprintf(buf
,256, str
, ap
);
783 MaNGOS::Singleton
<Log
>::Instance().outError(buf
);
786 void error_db_log(const char * str
, ...)
794 vsnprintf(buf
,256, str
, ap
);
797 MaNGOS::Singleton
<Log
>::Instance().outErrorDb(buf
);