#include #include #include #include #include #include #include static const char * LogLevelStrings[] = { "", "DEBUG", "INFO", "WARNING", "ERROR" }; static const int LogLevelSysLog[] = { LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR }; static unsigned int loggerCount = 0; static unsigned int loggerId = 0; std::map *Logger::LoggerMap = nullptr; Logger::LogLevel Logger::GLOBAL_MIN_LOG_LEVEL = Logger::UNSET; LoggerManager* LoggerManager::_instance = nullptr; Logger* Logger::getInstance(QString name, Logger::LogLevel minLevel) { qRegisterMetaType(); Logger* log = nullptr; if (LoggerMap == nullptr) { LoggerMap = new std::map; } if ( LoggerMap->find(name) == LoggerMap->end() ) { log = new Logger(name,minLevel); LoggerMap->insert(std::pair(name,log)); // compat version, replace it with following line if we have 100% c++11 //LoggerMap->emplace(name,log); // not compat with older linux distro's e.g. wheezy connect(log, SIGNAL(newLogMessage(Logger::T_LOG_MESSAGE)), LoggerManager::getInstance(), SLOT(handleNewLogMessage(Logger::T_LOG_MESSAGE))); } else { log = LoggerMap->at(name); } return log; } void Logger::deleteInstance(QString name) { if (LoggerMap == nullptr) return; if ( name.isEmpty() ) { std::map::iterator it; for ( it=LoggerMap->begin(); it != LoggerMap->end(); it++) { delete it->second; } LoggerMap->clear(); } else if (LoggerMap->find(name) != LoggerMap->end()) { delete LoggerMap->at(name); LoggerMap->erase(name); } } void Logger::setLogLevel(LogLevel level,QString name) { if ( name.isEmpty() ) { GLOBAL_MIN_LOG_LEVEL = level; } else { Logger* log = Logger::getInstance(name,level); log->setMinLevel(level); } } Logger::LogLevel Logger::getLogLevel(QString name) { if ( name.isEmpty() ) { return GLOBAL_MIN_LOG_LEVEL; } Logger* log = Logger::getInstance(name); return log->getMinLevel(); } Logger::Logger ( QString name, LogLevel minLevel ) : QObject() , _name(name) , _minLevel(minLevel) , _syslogEnabled(true) , _loggerId(loggerId++) { #ifdef __GLIBC__ const char* _appname_char = program_invocation_short_name; #else const char* _appname_char = getprogname(); #endif _appname = QString(_appname_char).toLower(); loggerCount++; if (_syslogEnabled && loggerCount == 1 ) { openlog (_appname_char, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL0); } } Logger::~Logger() { //Debug(this, "logger '%s' destroyed", QSTRING_CSTR(_name) ); loggerCount--; if ( loggerCount == 0 ) closelog(); } void Logger::Message(LogLevel level, const char* sourceFile, const char* func, unsigned int line, const char* fmt, ...) { if ( (GLOBAL_MIN_LOG_LEVEL == Logger::UNSET && level < _minLevel) // no global level, use level from logger || (GLOBAL_MIN_LOG_LEVEL > Logger::UNSET && level < GLOBAL_MIN_LOG_LEVEL) ) // global level set, use global level return; const size_t max_msg_length = 1024; char msg[max_msg_length]; va_list args; va_start (args, fmt); vsnprintf (msg, max_msg_length, fmt, args); va_end (args); Logger::T_LOG_MESSAGE logMsg; logMsg.appName = _appname; logMsg.loggerName = _name; logMsg.function = QString(func); logMsg.line = line; logMsg.fileName = FileUtils::getBaseName(sourceFile); time(&(logMsg.utime)); logMsg.message = QString(msg); logMsg.level = level; logMsg.levelString = LogLevelStrings[level]; emit newLogMessage(logMsg); QString location; if ( level == Logger::DEBUG ) { location = "<" + logMsg.fileName + ":" + QString::number(line)+":"+ logMsg.function + "()> "; } std::cout << QString("[" + _appname + " " + _name + "] <" + LogLevelStrings[level] + "> " + location + msg).toStdString() << std::endl; if ( _syslogEnabled && level >= Logger::WARNING ) syslog (LogLevelSysLog[level], "%s", msg); } LoggerManager::LoggerManager() : QObject() , _loggerMaxMsgBufferSize(200) { } void LoggerManager::handleNewLogMessage(Logger::T_LOG_MESSAGE msg) { _logMessageBuffer.append(msg); if (_logMessageBuffer.length() > _loggerMaxMsgBufferSize) { _logMessageBuffer.erase(_logMessageBuffer.begin()); } emit newLogMessage(msg); } LoggerManager* LoggerManager::getInstance() { if ( _instance == nullptr ) _instance = new LoggerManager(); return _instance; }