00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef _CSP_KERNEL_Log_H
00025 #define _CSP_KERNEL_Log_H
00026
00027
00028 #include <vector>
00029 #include <fstream>
00030
00031
00032 CSP_NAMESPACE_BEGIN(csp);
00033
00034
00036 enum LogLevel
00037 {
00038 Info = 0,
00039 Error,
00040 Warning,
00041 Notice,
00042 Debug0,
00043 Debug1,
00044 Debug2,
00045 Debug,
00046 MaxLevel
00047 };
00048
00049
00050 enum LogPreambleFlags
00051 {
00052 LogProgram = 1,
00053 LogProcessId = 2,
00054 LogThreadId = 4,
00055 LogDate = 8,
00056 LogTime = 16,
00057 LogLevelName = 32,
00058 LogCategory = 64,
00059 LogIndentationLevel = 128,
00060 LogAll = 0xFFFFFFFF
00061 };
00062
00063
00072 class CSP_API GlobalLog
00073 {
00074 public:
00075 typedef unsigned int PreambleFlags;
00076
00092 GlobalLog(
00093 const wstring& programName,
00094 Mutex::GlobalData& globalData,
00095 size_t maxLineLength);
00096
00101 ~GlobalLog() { while (m_mutex.iHoldIt()) m_mutex.release(); }
00102
00108 void registerPattern(const wstring& pattern);
00109
00115 void unregisterPattern(const wstring& pattern);
00116
00121 void clearPatterns()
00122 {
00123 m_patterns.clear();
00124 registerPattern(L"csp::Log");
00125 }
00126
00132 const vector<wstring>& patterns() const { return m_patterns; }
00133
00141 LogLevel level() const { return m_level; }
00142
00150 void setLevel(const LogLevel level);
00151
00159 LogLevel threshold() const { return m_threshold; }
00160
00168 void setThreshold(const LogLevel threshold);
00169
00177 void setPreambleFlags(const PreambleFlags preambleFlags) {
00178 m_preambleFlags = preambleFlags; }
00179
00184 void lock() { m_mutex.acquire(); }
00185
00191 void unlock() { m_mutex.release(); }
00192
00199 bool isEnabled(const LogLevel level) {
00200
00201 return level <= m_level && level >= 0; }
00202
00210 bool isEnabled(const wstring& category);
00211
00213 const wstring levelName(const LogLevel level) const;
00214
00216 const wstring levelColor(const LogLevel level) const;
00217
00225 void write(
00226 const wstring& category,
00227 const LogLevel level,
00228 wostringstream& wos);
00229
00231 void setIndentationState(const bool useIndentation)
00232 {
00233 m_useIndentation = useIndentation;
00234 }
00235
00242 void setIndentationAmount(const size_t spaces);
00243
00252 void registerIndentationLevelPlaceholder(int& indentationLevel);
00253
00257 void unregisterIndentationLevelPlaceholder();
00258
00264 const int& indentationLevelPlaceholder() const;
00265
00271 bool outputToTTY() const
00272 {
00273 #ifdef _WIN32
00274 return false;
00275 #else
00276 return isatty(2);
00277 #endif
00278 }
00279
00280 protected:
00290 const wstring preamble(
00291 const wstring& category,
00292 const LogLevel level);
00293
00303 void splitLine(
00304 const wstring& line,
00305 vector<wstring>& lines,
00306 wstring::size_type reserved);
00307
00315 void splitMultiLine(const wstring& line, vector<wstring>& lines);
00316
00325 const wstring indent(const int threadId) const;
00326
00333 const int indentationLevel(const int threadId) const;
00334
00345 const wstring fit(const wstring& text, const size_t limit);
00346
00348 wstring m_programName;
00349
00351 LogLevel m_level;
00352
00354 LogLevel m_threshold;
00355
00362 vector<wstring> m_patterns;
00363
00365 vector<pair<wstring, wstring> > m_levelInfo;
00366
00371 PreambleFlags m_preambleFlags;
00372
00377 size_t m_maxLineLength;
00378
00380 bool m_useIndentation;
00381
00383 size_t m_spaces;
00384
00386 size_t m_maxLogLevelNameLength;
00387
00395 hash_map<int, int*> m_indentationLevels;
00396
00398 bool m_useColors;
00399
00404 Mutex::GlobalData& m_globalData;
00405
00410 Mutex m_mutex;
00411 };
00412
00413
00414 extern CSP_API GlobalLog* g_log;
00415
00416
00423 class CSP_API Log
00424 {
00425 public:
00426 Log(const wstring& programName);
00427 ~Log();
00428
00429 static void registerPattern(const wstring& pattern) {
00430 g_log->registerPattern(pattern); }
00431 static void unregisterPattern(const wstring& pattern) {
00432 g_log->unregisterPattern(pattern); }
00433 static void clearPatterns() {
00434 g_log->clearPatterns(); }
00435 static const vector<wstring>& patterns() {
00436 return g_log->patterns(); }
00437 static LogLevel level() {
00438 return g_log->level(); }
00439 static void setLevel(LogLevel level) {
00440 g_log->setLevel(level); }
00441 static LogLevel threshold() {
00442 return g_log->threshold(); }
00443 static void setThreshold(LogLevel threshold) {
00444 g_log->setThreshold(threshold); }
00445 static void setPreambleFlags(const GlobalLog::PreambleFlags flags) {
00446 g_log->setPreambleFlags(flags); }
00447 static bool isEnabled(const LogLevel level) {
00448 return g_log->isEnabled(level); }
00449 static bool isEnabled(const wstring& category) {
00450 return g_log->isEnabled(category); }
00451 static const wstring levelName(const LogLevel level) {
00452 return g_log->levelName(level); }
00453 static const wstring levelColor(const LogLevel level) {
00454 return g_log->levelColor(level); }
00455 static void write(
00456 const wstring& category,
00457 const LogLevel level,
00458 wostringstream& wos) {
00459 return g_log->write(category, level, wos); }
00460 static void setIndentationState(const bool indentation) {
00461 g_log->setIndentationState(indentation); }
00462 static void setIndentationAmount(const size_t spaces) {
00463 g_log->setIndentationAmount(spaces); }
00464 static void registerIndentationLevelPlaceholder(int& indentationLevel) {
00465 g_log->registerIndentationLevelPlaceholder(indentationLevel); }
00466 static void unregisterIndentationLevelPlaceholder() {
00467 g_log->unregisterIndentationLevelPlaceholder(); }
00468 static bool outputToTTY() {
00469 return g_log->outputToTTY(); }
00470
00471 };
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 #define LOG(category, level, message)\
00490 {\
00491 using namespace csp;\
00492 assert(g_log);\
00493 if (g_log->isEnabled(level))\
00494 {\
00495 g_log->lock();\
00496 if (((level) <= g_log->threshold()) || g_log->isEnabled(category))\
00497 {\
00498 std::wostringstream wos;\
00499 wos << message;\
00500 g_log->write((category), (level), wos);\
00501 }\
00502 g_log->unlock();\
00503 }\
00504 }
00505
00506
00507 CSP_NAMESPACE_END(csp);
00508
00509
00510 #endif // _CSP_KERNEL_Log_H
00511
00512
00513
00514