MojErr MojSyslogAppender::append(MojLogger::Level level, MojLogger* logger, const MojChar* format, va_list args) { MojAssertNoLog(format); static const int s_syslogLevels[] = { LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING, LOG_ERR, LOG_CRIT }; MojAssertNoLog(sizeof(s_syslogLevels) / sizeof(int) == MojLogger::LevelMax); int syslogLevel = LOG_DEBUG; if (level >= 0 && level < MojLogger::LevelMax) syslogLevel = s_syslogLevels[level]; m_buf.clear(); if (logger) { MojErr err = m_buf.appendFormat(_T("[%s] "), logger->name()); MojErrCheckNoLog(err); } MojErr err = m_buf.appendVFormat(format, args); MojErrCheckNoLog(err); (void) syslog(syslogLevel, "%s", m_buf.data()); return MojErrNone; }
void MojLogger::vlog(Level level, const MojChar* format, va_list args) { MojAssertNoLog(format); MojAssertNoLog(m_engine); if (level >= m_level) { m_engine->log(level, this, format, args); } }
void MojLogger::log(Level level, const MojChar* format, ...) { MojAssertNoLog(format); MojAssertNoLog(m_engine); if (level >= m_level) { va_list args; va_start(args, format); m_engine->log(level, this, format, args); va_end(args); } }
MojErr MojFileAppender::open(const MojChar* path) { MojAssertNoLog(m_file == MojInvalidFile); MojAssertNoLog(path); MojErr err = MojFileOpen(m_file, path, MOJ_O_CREAT | MOJ_O_APPEND | MOJ_O_WRONLY, MOJ_S_IRUSR | MOJ_S_IWUSR); MojErrCheckNoLog(err); m_close = true; return MojErrNone; }
void MojLogEngine::removeLogger(MojLogger* logger) { MojAssertNoLog(logger); MojThreadGuard guard(m_mutex); m_loggers.erase(logger); }
void MojLogEngine::addLogger(MojLogger* logger) { MojAssertNoLog(logger); MojThreadGuard guard(m_mutex); m_loggers.pushBack(logger); updateLoggerLevel(logger); }
MojLogTracer::MojLogTracer(MojLogger& logger, const MojChar* function, const MojChar* file, int line) : m_logger(logger), m_function(function), m_level(indentLevel(1)) { MojAssertNoLog(function && file); logger.log(MojLogger::LevelTrace, _T("%*s-> %s (%s:%d)"), m_level * IndentSpaces, _T(""), function, MojFileNameFromPath(file), line); }
MojErr MojFileAppender::append(MojLogger::Level level, MojLogger* logger, const MojChar* format, va_list args) { MojAssertNoLog(format); MojAssertNoLog(m_file != MojInvalidFile); // get current time MojTime time = 0; MojErr err = MojGetCurrentTime(time); MojErrCheckNoLog(err); MojTmT tm; err = MojLocalTime(time, tm); MojErrCheckNoLog(err); // format message err = m_buf.format(_T("[%04d-%02d-%02d %02d:%02d:%02d:%03d] [%p] [%s]"), tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, time.millisecsPart(), (void*) (MojIntPtr) MojThreadCurrentId(), MojLogger::stringFromLevel(level)); MojErrCheckNoLog(err); if (logger) { err = m_buf.appendFormat(_T(" [%s]: "), logger->name()); MojErrCheckNoLog(err); } else { err = m_buf.append(_T(": ")); MojErrCheckNoLog(err); } err = m_buf.appendVFormat(format, args); MojErrCheckNoLog(err); err = m_buf.append(_T('\n')); MojErrCheckNoLog(err); // append to file const MojByte* begin = (const MojByte*) m_buf.begin(); const MojByte* end = (const MojByte*) m_buf.end(); while (begin < end) { MojSize written = 0; err = MojFileWrite(m_file, begin, end - begin, written); MojErrCheckNoLog(err); begin += written; } return MojErrNone; }
void MojLogEngine::log(MojLogger::Level level, MojLogger* logger, const MojChar* format, va_list args) { MojAssertNoLog(logger && format); MojAssert(m_appender); // prevent recursive logging of errors that occur during logging MojThreadIdT self = MojThreadCurrentId(); if (m_logThread == self) return; // suppress logger name for traces and error macros if (level == MojLogger::LevelTrace || logger == &m_errorLogger) logger = NULL; MojThreadGuard guard(m_mutex); MojAssertNoLog(m_logThread == MojInvalidThreadId); m_logThread = self; (void) m_appender->append(level, logger, format, args); m_logThread = MojInvalidThreadId; }
MojLogger::MojLogger(const MojChar* name, MojLogEngine* engine) : m_engine(engine), m_name(name), m_level(LevelDefault), m_data(NULL) { MojAssertNoLog(name); if (m_engine == NULL) m_engine = MojLogEngine::instance(); m_engine->addLogger(this); }
MojErr MojLogger::levelFromString(const MojChar* str, Level& levelOut) { MojAssertNoLog(str); for (int i = 0; i <= LevelMax; ++i) { if (!MojStrCmp(str, s_levelNames[i])) { levelOut = (Level) i; return MojErrNone; } } MojErrThrowMsg(MojErrLogLevelNotFound, _T("log: level not found: '%s'"), str); }
void MojFileAppender::open(MojFileT file) { MojAssertNoLog(m_file == MojInvalidFile && m_close == false); m_file = file; }