// Log format in clipboard: "2000/01/15 12:05:30 <LogType> <ProcessName> <FileName> <Line>: <Msg>" // Log format on the screen: in debug "<ProcessName> <FileName> <Line>: <Msg>" // in release "<Msg>" void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message) { #ifdef NL_OS_WINDOWS bool needSpace = false; // stringstream ss; string str; // create the string for the clipboard if (args.Date != 0) { str += dateToHumanString(args.Date); needSpace = true; } if (args.LogType != CLog::LOG_NO) { //if (needSpace) { ss << " "; needSpace = false; } if (needSpace) { str += " "; needSpace = false; } str += logTypeToString(args.LogType); needSpace = true; } if (!args.ProcessName.empty()) { //if (needSpace) { ss << " "; needSpace = false; } if (needSpace) { str += " "; needSpace = false; } str += args.ProcessName; needSpace = true; } if (args.FileName != NULL) { //if (needSpace) { ss << " "; needSpace = false; } if (needSpace) { str += " "; needSpace = false; } str += CFile::getFilename(args.FileName); needSpace = true; } if (args.Line != -1) { //if (needSpace) { ss << " "; needSpace = false; } if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString(args.Line); needSpace = true; } if (args.FuncName != NULL) { //if (needSpace) { ss << " "; needSpace = false; } if (needSpace) { str += " "; needSpace = false; } str += args.FuncName; needSpace = true; } if (needSpace) { str += ": "; needSpace = false; } str += message; CSystemUtils::copyTextToClipboard(str); // create the string on the screen needSpace = false; // stringstream ss2; string str2; #ifdef NL_DEBUG if (!args.ProcessName.empty()) { if (needSpace) { str2 += " "; needSpace = false; } str2 += args.ProcessName; needSpace = true; } if (args.FileName != NULL) { if (needSpace) { str2 += " "; needSpace = false; } str2 += CFile::getFilename(args.FileName); needSpace = true; } if (args.Line != -1) { if (needSpace) { str2 += " "; needSpace = false; } str2 += NLMISC::toString(args.Line); needSpace = true; } if (args.FuncName != NULL) { if (needSpace) { str2 += " "; needSpace = false; } str2 += args.FuncName; needSpace = true; } if (needSpace) { str2 += ": "; needSpace = false; } #endif // NL_DEBUG str2 += message; str2 += "\n\n(this message was copied in the clipboard)"; /* if (IsDebuggerPresent ()) { // Must break in assert call DebugNeedAssert = true; } else */ { // Display the report string body; body += toString(LogTypeToString[2][args.LogType]) + "\n"; body += "ProcName: " + args.ProcessName + "\n"; body += "Date: " + string(dateToHumanString(args.Date)) + "\n"; if(args.FileName == NULL) body += "File: <Unknown>\n"; else body += "File: " + string(args.FileName) + "\n"; body += "Line: " + toString(args.Line) + "\n"; if (args.FuncName == NULL) body += "FuncName: <Unknown>\n"; else body += "FuncName: " + string(args.FuncName) + "\n"; body += "Reason: " + toString(message); body += args.CallstackAndLog; string subject; // procname is host/service_name-sid we only want the service_name to avoid redondant mail string procname; string::size_type pos = args.ProcessName.find ("/"); if (pos == string::npos) { procname = args.ProcessName; } else { string::size_type pos2 = args.ProcessName.find ("-", pos+1); if (pos2 == string::npos) { procname = args.ProcessName.substr (pos+1); } else { procname = args.ProcessName.substr (pos+1, pos2-pos-1); } } subject += procname + " NeL " + toString(LogTypeToString[0][args.LogType]) + " " + (args.FileName?string(args.FileName):"") + " " + toString(args.Line) + " " + (args.FuncName?string(args.FuncName):""); // Check the envvar NEL_IGNORE_ASSERT if (getenv ("NEL_IGNORE_ASSERT") == NULL) { // yoyo: allow only to send the crash report once. Because users usually click ignore, // which create noise into list of bugs (once a player crash, it will surely continues to do it). std::string filename = getLogDirectory() + NL_CRASH_DUMP_FILE; if (ReportDebug == report (args.ProcessName + " NeL " + toString(logTypeToString(args.LogType, true)), "", subject, body, true, 2, true, 1, !isCrashAlreadyReported(), IgnoreNextTime, filename.c_str())) { INelContext::getInstance().setDebugNeedAssert(true); } // no more sent mail for crash setCrashAlreadyReported(true); } /* // Check the envvar NEL_IGNORE_ASSERT if (getenv ("NEL_IGNORE_ASSERT") == NULL) { // Ask the user to continue, debug or ignore int result = MessageBox (NULL, ss2.str().c_str (), logTypeToString(args.LogType, true), MB_ABORTRETRYIGNORE | MB_ICONSTOP); if (result == IDABORT) { // Exit the program now exit (EXIT_FAILURE); } else if (result == IDRETRY) { // Give the debugger a try DebugNeedAssert = true; } else if (result == IDIGNORE) { // Continue, do nothing } } */ } #endif }
// Log format: "2000/01/15 12:05:30 <ProcessName> <LogType> <ThreadId> <FileName> <Line> : <Msg>" void CFileDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message ) { bool needSpace = false; //stringstream ss; string str; // if the filename is not set, don't log if (_FileName.empty()) return; if (args.Date != 0 && !_Raw) { str += dateToHumanString(args.Date); needSpace = true; } if (args.LogType != CLog::LOG_NO && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += logTypeToString(args.LogType); needSpace = true; } // Write thread identifier if ( args.ThreadId != 0 && !_Raw) { if (needSpace) { str += " "; needSpace = false; } #ifdef NL_OS_WINDOWS str += NLMISC::toString("%4x", args.ThreadId); #else str += NLMISC::toString("%4u", args.ThreadId); #endif needSpace = true; } if (!args.ProcessName.empty() && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += args.ProcessName; needSpace = true; } if (args.FileName != NULL && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += CFile::getFilename(args.FileName); needSpace = true; } if (args.Line != -1 && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString(args.Line); needSpace = true; } if (args.FuncName != NULL && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += args.FuncName; needSpace = true; } if (needSpace) { str += " : "; needSpace = false; } str += message; if (_FilePointer > (FILE*)1) { // if the file is too big (>5mb), rename it and create another one (check only after 20 lines to speed up) if (_LastLogSizeChecked++ > 20) { int res = ftell (_FilePointer); if (res > 5*1024*1024) { fclose (_FilePointer); rename (_FileName.c_str(), CFile::findNewFile (_FileName).c_str()); _FilePointer = (FILE*) 1; _LastLogSizeChecked = 0; } } } if (_FilePointer == (FILE*)1) { _FilePointer = fopen (_FileName.c_str(), "at"); if (_FilePointer == NULL) printf ("Can't open log file '%s': %s\n", _FileName.c_str(), strerror (errno)); } if (_FilePointer != 0) { if (_NeedHeader) { const char *hs = HeaderString(); fwrite (hs, strlen (hs), 1, _FilePointer); _NeedHeader = false; } if(!str.empty()) fwrite (str.c_str(), str.size(), 1, _FilePointer); if(!args.CallstackAndLog.empty()) fwrite (args.CallstackAndLog.c_str(), args.CallstackAndLog.size (), 1, _FilePointer); fflush (_FilePointer); } }
// Log format : "<LogType> <ThreadNo> <FileName> <Line> <ProcessName> : <Msg>" void CStdDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message ) { bool needSpace = false; //stringstream ss; string str; if (args.LogType != CLog::LOG_NO) { //ss << logTypeToString(args.LogType); str += logTypeToString(args.LogType); needSpace = true; } // Write thread identifier if ( args.ThreadId != 0 ) { //ss << setw(5) << args.ThreadId; if (needSpace) { str += " "; needSpace = false; } #ifdef NL_OS_WINDOWS str += NLMISC::toString("%5x", args.ThreadId); #else str += NLMISC::toString("%08x", args.ThreadId); #endif needSpace = true; } if (args.FileName != NULL) { //if (needSpace) { ss << " "; needSpace = false; } if (needSpace) { str += " "; needSpace = false; } //ss << CFile::getFilename(args.FileName); str += CFile::getFilename(args.FileName); needSpace = true; } if (args.Line != -1) { //if (needSpace) { ss << " "; needSpace = false; } if (needSpace) { str += " "; needSpace = false; } //ss << args.Line; str += NLMISC::toString(args.Line); needSpace = true; } if (args.FuncName != NULL) { //if (needSpace) { ss << " "; needSpace = false; } if (needSpace) { str += " "; needSpace = false; } //ss << args.FuncName; str += args.FuncName; needSpace = true; } if (!args.ProcessName.empty()) { //if (needSpace) { ss << " "; needSpace = false; } if (needSpace) { str += " "; needSpace = false; } //ss << args.ProcessName; str += args.ProcessName; needSpace = true; } //if (needSpace) { ss << " : "; needSpace = false; } if (needSpace) { str += " : "; needSpace = false; } //ss << message; str += message; // string s = ss.str(); static bool consoleMode = true; #if defined(NL_OS_WINDOWS) static bool consoleModeTest = false; if (!consoleModeTest) { HANDLE handle = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); consoleMode = handle != INVALID_HANDLE_VALUE; if (consoleMode) CloseHandle (handle); consoleModeTest = true; } #endif // NL_OS_WINDOWS // Printf ? if (consoleMode) { // we don't use cout because sometimes, it crashs because cout isn't already init, printf doesn t crash. if (!str.empty()) printf ("%s", str.c_str()); if (!args.CallstackAndLog.empty()) printf ("%s", args.CallstackAndLog.c_str()); fflush(stdout); } #ifdef NL_OS_WINDOWS // display the string in the debugger is the application is started with the debugger if (IsDebuggerPresent ()) { //stringstream ss2; string str2; needSpace = false; if (args.FileName != NULL) str2 += args.FileName; if (args.Line != -1) { str2 += "(" + NLMISC::toString(args.Line) + ")"; needSpace = true; } if (needSpace) { str2 += " : "; needSpace = false; } if (args.FuncName != NULL) str2 += string(args.FuncName) + " "; if (args.LogType != CLog::LOG_NO) { str2 += logTypeToString(args.LogType); needSpace = true; } // Write thread identifier if ( args.ThreadId != 0 ) { str2 += NLMISC::toString("%5x: ", args.ThreadId); } str2 += message; const sint maxOutString = 2*1024; if(str2.size() < maxOutString) { ////////////////////////////////////////////////////////////////// // WARNING: READ THIS !!!!!!!!!!!!!!!! /////////////////////////// // If at the release time, it freezes here, it's a microsoft bug: // http://support.microsoft.com/support/kb/articles/q173/2/60.asp OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(str2).c_str()); } else { /*OutputDebugString(ss2.str().c_str()); OutputDebugString("\n\t\t\t"); OutputDebugString("message end: "); OutputDebugString(&message[strlen(message) - 1024]); OutputDebugString("\n");*/ sint count = 0; uint n = (uint)strlen(message); std::string s(&str2.c_str()[0], (str2.size() - n)); OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(s).c_str()); for(;;) { if((n - count) < maxOutString ) { s = std::string(&message[count], (n - count)); OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(s).c_str()); OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8("\n").c_str()); break; } else { s = std::string(&message[count] , count + maxOutString); OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(s).c_str()); OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8("\n\t\t\t").c_str()); count += maxOutString; } } } // OutputDebugString is a big shit, we can't display big string in one time, we need to split uint32 pos = 0; string splited; for(;;) { if (pos+1000 < args.CallstackAndLog.size ()) { splited = args.CallstackAndLog.substr (pos, 1000); OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(splited).c_str()); pos += 1000; } else { splited = args.CallstackAndLog.substr (pos); OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(splited).c_str()); break; } } } #endif }
void CWindowDisplayer::doDisplay (const NLMISC::CLog::TDisplayInfo &args, const char *message) { bool needSpace = false; //stringstream ss; string str; uint32 color = 0xFF000000; if (args.LogType != CLog::LOG_NO) { str += logTypeToString(args.LogType); if (args.LogType == CLog::LOG_ERROR || args.LogType == CLog::LOG_ASSERT) color = 0x00FF0000; else if (args.LogType == CLog::LOG_WARNING) color = 0x00800000; else if (args.LogType == CLog::LOG_DEBUG) color = 0x00808080; else color = 0; needSpace = true; } // Write thread identifier if ( args.ThreadId != 0 ) { if (needSpace) { str += " "; needSpace = false; } #ifdef NL_OS_WINDOWS str += NLMISC::toString("%4x", args.ThreadId); #else str += NLMISC::toString("%08x", args.ThreadId); #endif needSpace = true; } if (args.FileName != NULL) { if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString("%20s", CFile::getFilename(args.FileName).c_str()); needSpace = true; } if (args.Line != -1) { if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString("%4u", args.Line); //ss << setw(4) << args.Line; needSpace = true; } if (args.FuncName != NULL) { if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString("%20s", args.FuncName); needSpace = true; } if (needSpace) { str += ": "; needSpace = false; } uint nbl = 1; char *npos, *pos = const_cast<char *>(message); while ((npos = strchr (pos, '\n'))) { *npos = '\0'; str += pos; if (needSlashR) str += "\r"; str += "\n"; *npos = '\n'; pos = npos+1; nbl++; } str += pos; pos = const_cast<char *>(args.CallstackAndLog.c_str()); while ((npos = strchr (pos, '\n'))) { *npos = '\0'; str += pos; if (needSlashR) str += "\r"; str += "\n"; *npos = '\n'; pos = npos+1; nbl++; } str += pos; { CSynchronized<std::list<std::pair<uint32, std::string> > >::CAccessor access (&_Buffer); if (_HistorySize > 0 && access.value().size() >= (uint)_HistorySize) { access.value().erase (access.value().begin()); } access.value().push_back (make_pair (color, str)); } }
void CCommandLog::doDisplay(const CLog::TDisplayInfo& args, const char *message) { switch (args.LogType) { case CLog::LOG_DEBUG: m_DisplayerOutput->setTextColor(Qt::darkGray); break; case CLog::LOG_STAT: m_DisplayerOutput->setTextColor(Qt::darkGreen); break; case CLog::LOG_NO: case CLog::LOG_UNKNOWN: case CLog::LOG_INFO: m_DisplayerOutput->setTextColor(Qt::black); break; case CLog::LOG_WARNING: m_DisplayerOutput->setTextColor(Qt::darkBlue); break; case CLog::LOG_ERROR: case CLog::LOG_ASSERT: m_DisplayerOutput->setTextColor(Qt::darkRed); break; } bool needSpace = false; //stringstream ss; string str; if (args.LogType != CLog::LOG_NO) { str += logTypeToString(args.LogType); needSpace = true; } // Write thread identifier if (args.ThreadId != 0) { if (needSpace) { str += " "; needSpace = false; } #ifdef NL_OS_WINDOWS str += NLMISC::toString("%4x", args.ThreadId); #else str += NLMISC::toString("%08x", args.ThreadId); #endif needSpace = true; } if (args.FileName != NULL) { if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString("%20s", CFile::getFilename(args.FileName).c_str()); needSpace = true; } if (args.Line != -1) { if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString("%4u", args.Line); //ss << setw(4) << args.Line; needSpace = true; } if (args.FuncName != NULL) { if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString("%20s", args.FuncName); needSpace = true; } if (needSpace) { str += ": "; needSpace = false; } uint nbl = 1; char *npos, *pos = const_cast<char *>(message); while ((npos = strchr (pos, '\n'))) { *npos = '\0'; str += pos; /*if (needSlashR) str += "\r";*/ str += "\n"; *npos = '\n'; pos = npos+1; nbl++; } str += pos; pos = const_cast<char *>(args.CallstackAndLog.c_str()); while ((npos = strchr (pos, '\n'))) { *npos = '\0'; str += pos; /*if (needSlashR) str += "\r";*/ str += "\n"; *npos = '\n'; pos = npos+1; nbl++; } str += pos; m_DisplayerOutput->append(str.substr(0, str.size() - 1).c_str()); }
void CQtDisplayer::doDisplay ( const NLMISC::CLog::TDisplayInfo& args, const char *message ) { bool needSpace = false; std::string str; if(m_DlgDebug==NULL) return; QTextCharFormat format; if (args.Date != 0 && !_Raw) { str += dateToHumanString(args.Date); needSpace = true; } if (args.LogType != NLMISC::CLog::LOG_NO && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += logTypeToString(args.LogType); if (args.LogType == NLMISC::CLog::LOG_WARNING) format.setForeground(QBrush(QColor("red"))); else format.setForeground(QBrush(QColor("black"))); needSpace = true; } // Write thread identifier /*if ( args.ThreadId != 0 && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString(args.ThreadId); needSpace = true; }*/ /*if (!args.ProcessName.empty() && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += args.ProcessName; needSpace = true; }*/ //if (args.FileName != NULL && !_Raw) { // if (needSpace) { str += " "; needSpace = false; } // str += NLMISC::CFile::getFilename(args.FileName); // needSpace = true; //} /*if (args.Line != -1 && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += NLMISC::toString(args.Line); needSpace = true; }*/ if (args.FuncName != NULL && !_Raw) { if (needSpace) { str += " "; needSpace = false; } str += args.FuncName; needSpace = true; } if (needSpace) { str += " : "; needSpace = false; } str += message; m_DlgDebug->textCursor().insertText(str.c_str(), format); //m_DlgDebug->setCenterOnScroll(true); m_DlgDebug->centerCursor(); //m_DlgDebug->ensureCursorVisible(); }