//! create with overwriting LoggerId LogerManager::createLogger(const char* key) { if (key == NULL) { return LOG4Z_INVALID_LOGGER_ID; } std::string copyKey = key; trimLogConfig(copyKey); LoggerId newID = LOG4Z_INVALID_LOGGER_ID; { std::map<std::string, LoggerId>::iterator iter = _ids.find(copyKey); if (iter != _ids.end()) { newID = iter->second; } } if (newID == LOG4Z_INVALID_LOGGER_ID) { if (_lastId +1 >= LOG4Z_LOGGER_MAX) { showColorText("log4z: CreateLogger can not create|writeover, because loggerid need < LOGGER_MAX! \r\n", LOG_LEVEL_FATAL); return LOG4Z_INVALID_LOGGER_ID; } newID = ++ _lastId; _ids[copyKey] = newID; _loggers[newID]._enable = true; _loggers[newID]._key = copyKey; _loggers[newID]._name = copyKey; } return newID; }
bool LogerManager::stop() { if (_runing) { showColorText("log4z stopping \r\n", LOG_LEVEL_FATAL); _runing = false; wait(); return true; } return false; }
bool LogerManager::start() { if (_runing) { showColorText("log4z already start \r\n", LOG_LEVEL_FATAL); return false; } _semaphore.create(0); bool ret = ThreadHelper::start(); return ret && _semaphore.wait(3000); }
bool LogerManager::closeLogger(LoggerId id) { if (id < 0 || id >_lastId) { showColorText("log4z: closeLogger can not close, invalide logger id! \r\n", LOG_LEVEL_FATAL); return false; } LoggerInfo * pLogger = &_loggers[id]; if (pLogger->_handle.isOpen()) { pLogger->_handle.close(); return true; } return false; }
void LogerManager::run() { _runing = true; pushLog(0, LOG_LEVEL_ALARM, "----------------- log4z thread started! ----------------------------", NULL, 0); for (int i = 0; i <= _lastId; i++) { if (_loggers[i]._enable) { std::stringstream ss; ss <<"logger id=" <<i <<" key=" <<_loggers[i]._key <<" name=" <<_loggers[i]._name <<" path=" <<_loggers[i]._path <<" level=" << _loggers[i]._level <<" display=" << _loggers[i]._display; pushLog(0, LOG_LEVEL_ALARM, ss.str().c_str(), NULL, 0); } } _semaphore.post(); LogData * pLog = NULL; int needFlush[LOG4Z_LOGGER_MAX] = {0}; time_t lastCheckUpdate = time(NULL); while (true) { while(popLog(pLog)) { // _ullStatusTotalPopLog ++; //discard LoggerInfo & curLogger = _loggers[pLog->_id]; if (!curLogger._enable || pLog->_level <curLogger._level ) { delete pLog; pLog = NULL; continue; } if (curLogger._display && !LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { showColorText(pLog->_content, pLog->_level); } if (LOG4Z_ALL_DEBUGOUTPUT_DISPLAY && !LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { #ifdef WIN32 OutputDebugStringA(pLog->_content); #endif } if (curLogger._outfile && !LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { if (!openLogger(pLog)) { delete pLog; pLog = NULL; continue; } curLogger._handle.write(pLog->_content, pLog->_contentLen); curLogger._curWriteLen += (unsigned int)pLog->_contentLen; needFlush[pLog->_id] ++; _ullStatusTotalWriteFileCount++; _ullStatusTotalWriteFileBytes += pLog->_contentLen; } else if (!LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { _ullStatusTotalWriteFileCount++; _ullStatusTotalWriteFileBytes += pLog->_contentLen; } delete pLog; pLog = NULL; } for (int i=0; i<=_lastId; i++) { if (_loggers[i]._enable && needFlush[i] > 0) { _loggers[i]._handle.flush(); needFlush[i] = 0; } if(!_loggers[i]._enable && _loggers[i]._handle.isOpen()) { _loggers[i]._handle.close(); } } //! delay. sleepMillisecond(100); //! quit if (!_runing && _logs.empty()) { break; } if (_hotUpdateInterval != 0 && time(NULL) - lastCheckUpdate > _hotUpdateInterval) { updateConfig(); lastCheckUpdate = time(NULL); } } for (int i=0; i <= _lastId; i++) { if (_loggers[i]._enable) { _loggers[i]._enable = false; closeLogger(i); } } }
bool LogerManager::openLogger(LogData * pLog) { int id = pLog->_id; if (id < 0 || id >_lastId) { showColorText("log4z: openLogger can not open, invalide logger id! \r\n", LOG_LEVEL_FATAL); return false; } LoggerInfo * pLogger = &_loggers[id]; if (!pLogger->_enable || !pLogger->_outfile || pLog->_level < pLogger->_level) { return false; } bool sameday = isSameDay(pLog->_time, pLogger->_curFileCreateTime); bool needChageFile = pLogger->_curWriteLen > pLogger->_limitsize * 1024 * 1024; if (!sameday || needChageFile || pLogger->_hotChange) { if (!sameday || pLogger->_hotChange) { pLogger->_curFileIndex = 0; } else { pLogger->_curFileIndex++; } if (pLogger->_handle.isOpen()) { pLogger->_handle.close(); } } if (!pLogger->_handle.isOpen()) { pLogger->_curFileCreateTime = pLog->_time; pLogger->_curWriteLen = 0; tm t = timeToTm(pLogger->_curFileCreateTime); std::string name; std::string path; _hotLock.lock(); name = pLogger->_name; path = pLogger->_path; pLogger->_hotChange = false; _hotLock.unLock(); char buf[100] = { 0 }; if (pLogger->_monthdir) { sprintf(buf, "%04d_%02d/", t.tm_year + 1900, t.tm_mon + 1); path += buf; } if (!isDirectory(path)) { createRecursionDir(path); } sprintf(buf, "%s_%04d%02d%02d%02d%02d_%s_%03d.log", name.c_str(), t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, _pid.c_str(), pLogger->_curFileIndex); path += buf; pLogger->_handle.open(path.c_str(), "ab"); if (!pLogger->_handle.isOpen()) { pLogger->_outfile = false; return false; } return true; } return true; }
bool LogerManager::pushLog(LoggerId id, int level, const char * log, const char * file, int line) { // discard log if (id < 0 || id > _lastId || !_runing || !_loggers[id]._enable) { return false; } //filter log if (level < _loggers[id]._level) { return false; } //create log data LogData * pLog = new LogData; pLog->_id =id; pLog->_level = level; //append precise time to log { #ifdef WIN32 FILETIME ft; GetSystemTimeAsFileTime(&ft); unsigned long long now = ft.dwHighDateTime; now <<= 32; now |= ft.dwLowDateTime; now /=10; now -=11644473600000000ULL; now /=1000; pLog->_time = now/1000; pLog->_precise = (unsigned int)(now%1000); #else struct timeval tm; gettimeofday(&tm, NULL); pLog->_time = tm.tv_sec; pLog->_precise = tm.tv_usec/1000; #endif } //format log { tm tt = timeToTm(pLog->_time); if (file == NULL || !_loggers[pLog->_id]._fileLine) { #ifdef WIN32 int ret = _snprintf_s(pLog->_content, LOG4Z_LOG_BUF_SIZE, _TRUNCATE, "%d-%02d-%02d %02d:%02d:%02d.%03d %s %s \r\n", tt.tm_year + 1900, tt.tm_mon + 1, tt.tm_mday, tt.tm_hour, tt.tm_min, tt.tm_sec, pLog->_precise, LOG_STRING[pLog->_level], log); if (ret == -1) { ret = LOG4Z_LOG_BUF_SIZE - 1; } pLog->_contentLen = ret; #else int ret = snprintf(pLog->_content, LOG4Z_LOG_BUF_SIZE, "%d-%02d-%02d %02d:%02d:%02d.%03d %s %s \r\n", tt.tm_year + 1900, tt.tm_mon + 1, tt.tm_mday, tt.tm_hour, tt.tm_min, tt.tm_sec, pLog->_precise, LOG_STRING[pLog->_level], log); if (ret == -1) { ret = 0; } if (ret >= LOG4Z_LOG_BUF_SIZE) { ret = LOG4Z_LOG_BUF_SIZE-1; } pLog->_contentLen = ret; #endif } else { const char * pNameBegin = file+strlen(file); do { if (*pNameBegin == '\\' || *pNameBegin == '/'){ pNameBegin++; break;} if (pNameBegin == file){break;} pNameBegin--; } while (true); #ifdef WIN32 int ret = _snprintf_s(pLog->_content, LOG4Z_LOG_BUF_SIZE, _TRUNCATE, "%d-%02d-%02d %02d:%02d:%02d.%03d %s %s (%s):%d \r\n", tt.tm_year + 1900, tt.tm_mon + 1, tt.tm_mday, tt.tm_hour, tt.tm_min, tt.tm_sec, pLog->_precise, LOG_STRING[pLog->_level], log, pNameBegin, line); if (ret == -1) { ret = LOG4Z_LOG_BUF_SIZE - 1; } pLog->_contentLen = ret; #else int ret = snprintf(pLog->_content, LOG4Z_LOG_BUF_SIZE, "%d-%02d-%02d %02d:%02d:%02d.%03d %s %s (%s):%d \r\n", tt.tm_year + 1900, tt.tm_mon + 1, tt.tm_mday, tt.tm_hour, tt.tm_min, tt.tm_sec, pLog->_precise, LOG_STRING[pLog->_level], log, pNameBegin, line); if (ret == -1) { ret = 0; } if (ret >= LOG4Z_LOG_BUF_SIZE) { ret = LOG4Z_LOG_BUF_SIZE-1; } pLog->_contentLen = ret; #endif } if (pLog->_contentLen >= 2) { pLog->_content[pLog->_contentLen - 2] = '\r'; pLog->_content[pLog->_contentLen - 1] = '\n'; } } if (_loggers[pLog->_id]._display && LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { showColorText(pLog->_content, pLog->_level); } if (LOG4Z_ALL_DEBUGOUTPUT_DISPLAY && LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { #ifdef WIN32 OutputDebugStringA(pLog->_content); #endif } if (_loggers[pLog->_id]._outfile && LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { AutoLock l(_logLock); if (openLogger(pLog)) { _loggers[pLog->_id]._handle.write(pLog->_content, pLog->_contentLen); closeLogger(pLog->_id); _ullStatusTotalWriteFileCount++; _ullStatusTotalWriteFileBytes += pLog->_contentLen; } } if (LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { delete pLog; return true; } AutoLock l(_logLock); _logs.push_back(pLog); _ullStatusTotalPushLog ++; return true; }
bool LogerManager::openLogger(LogData * pLog) { int id = pLog->_id; if (id < 0 || id >_lastId) { showColorText("log4z: openLogger can not open, invalide logger id! \r\n", LOG_LEVEL_FATAL); return false; } LoggerInfo * pLogger = &_loggers[id]; if (!pLogger->_enable || !pLogger->_outfile || pLog->_level < pLogger->_level) { return false; } bool sameday = isSameDay(pLog->_time, pLogger->_curFileCreateTime); bool needChageFile = pLogger->_curWriteLen > pLogger->_limitsize * 1024 * 1024; if (!sameday || needChageFile) { if (!sameday) { pLogger->_curFileIndex = 0; } else { pLogger->_curFileIndex++; } if (pLogger->_handle.isOpen()) { pLogger->_handle.close(); } } if (!pLogger->_handle.isOpen()) { pLogger->_curFileCreateTime = pLog->_time; pLogger->_curWriteLen = 0; tm t = timeToTm(pLogger->_curFileCreateTime); std::string name; std::string path; name = pLogger->_name; path = pLogger->_path; char buf[500] = { 0 }; if (pLogger->_monthdir) { sprintf(buf, "%04d_%02d/", t.tm_year + 1900, t.tm_mon + 1); path += buf; } if (!isDirectory(path)) { createRecursionDir(path); } sprintf(buf, "%s_%s_%04d%02d%02d%02d%02d_%s_%03u.log", _proName.c_str(), name.c_str(), t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, _pid.c_str(), pLogger->_curFileIndex); path += buf; pLogger->_handle.open(path.c_str(), "ab"); if (!pLogger->_handle.isOpen()) { sprintf(buf, "log4z: can not open log file %s. \r\n", path.c_str()); showColorText("!!!!!!!!!!!!!!!!!!!!!!!!!! \r\n", LOG_LEVEL_FATAL); showColorText(buf, LOG_LEVEL_FATAL); showColorText("!!!!!!!!!!!!!!!!!!!!!!!!!! \r\n", LOG_LEVEL_FATAL); pLogger->_outfile = false; return false; } if (pLogger->_logReserveTime > 0 ) { if (pLogger->_historyLogs.size() > LOG4Z_FORCE_RESERVE_FILE_COUNT) { while (!pLogger->_historyLogs.empty() && pLogger->_historyLogs.front().first < time(NULL) - pLogger->_logReserveTime) { pLogger->_handle.removeFile(pLogger->_historyLogs.front().second.c_str()); pLogger->_historyLogs.pop_front(); } } pLogger->_historyLogs.push_back(std::make_pair(time(NULL), path)); } return true; } return true; }
bool LogerManager::pushLog(LogData * pLog, const char * file, int line) { // discard log if (pLog->_id < 0 || pLog->_id > _lastId || !_runing || !_loggers[pLog->_id]._enable) { freeLogData(pLog); return false; } //filter log if (pLog->_level < _loggers[pLog->_id]._level) { freeLogData(pLog); return false; } if (_loggers[pLog->_id]._fileLine && file) { const char * pNameBegin = file + strlen(file); do { if (*pNameBegin == '\\' || *pNameBegin == '/') { pNameBegin++; break; } if (pNameBegin == file) { break; } pNameBegin--; } while (true); zsummer::log4z::Log4zStream ss(pLog->_content + pLog->_contentLen, LOG4Z_LOG_BUF_SIZE - pLog->_contentLen); ss << " " << pNameBegin << ":" << line; pLog->_contentLen += ss.getCurrentLen(); } if (pLog->_contentLen < 3) pLog->_contentLen = 3; if (pLog->_contentLen +3 <= LOG4Z_LOG_BUF_SIZE ) pLog->_contentLen += 3; pLog->_content[pLog->_contentLen - 1] = '\0'; pLog->_content[pLog->_contentLen - 2] = '\n'; pLog->_content[pLog->_contentLen - 3] = '\r'; pLog->_contentLen--; //clean '\0' if (_loggers[pLog->_id]._display && LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { showColorText(pLog->_content, pLog->_level); } if (LOG4Z_ALL_DEBUGOUTPUT_DISPLAY && LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { #ifdef WIN32 OutputDebugStringA(pLog->_content); #endif } if (_loggers[pLog->_id]._outfile && LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { AutoLock l(_logLock); if (openLogger(pLog)) { _loggers[pLog->_id]._handle.write(pLog->_content, pLog->_contentLen); closeLogger(pLog->_id); _ullStatusTotalWriteFileCount++; _ullStatusTotalWriteFileBytes += pLog->_contentLen; } } if (LOG4Z_ALL_SYNCHRONOUS_OUTPUT) { freeLogData(pLog); return true; } AutoLock l(_logLock); _logs.push(pLog); _ullStatusTotalPushLog ++; return true; }