#include "log.h" #include "threadcontext.h" // std #include #include #include #include #include #include #include #include using namespace osdev::components::mqtt; namespace { std::string toString( LogLevel level ) { switch (level) { case LogLevel::Trace: return "T"; case LogLevel::Debug: return "D"; case LogLevel::Info: return "I"; case LogLevel::Warning: return "W"; case LogLevel::Error: return "E"; } return "U"; } } // namespace const std::string Log::s_startMarker = std::string("|________________________________________________________________________________________________________________________________|"); std::string Log::s_context = std::string(); std::string Log::s_fileName = std::string(); LogLevel Log::s_logLevel = LogLevel::Info; void Log::init( const std::string &context, const std::string &logFile, LogLevel logDepth ) { s_logLevel = logDepth; s_context = context; if( !logFile.empty()) { s_fileName = logFile; } } void Log::terminate() { s_context.clear(); s_fileName.clear(); s_logLevel = LogLevel::Info; } void Log::log( const std::string &category, const std::string &message, LogLevel level ) { std::lock_guard lock(m_mutex); std::string logCategory = s_context + '|' + toString( level ) + '|' + ThreadContext::instance().context() + '|' + category; std::string logMessage = message; if( logMessage.empty() ) { static const std::string emptyMessage( "--" ); logMessage = emptyMessage; } else { // Replace % signs ReplaceAll( logMessage, "%", "%%" ); } writeLog( logCategory, logMessage, level ); } std::string Log::fileinfoMessage( const char *file, int line, const std::string &message ) { static const std::string templ("%1:%2| %3"); QFileInfo fi(file); return templ.arg( fi.fileName() ).arg(line).arg(message); } void Log::writeLog(const std::string &category, const std::string &message, LogLevel level) { if( s_fileName.empty() ) { (void)level; // To be implemented. return; } else { setlogmask( LOG_UPTO( LOG_NOTICE ) ); openlog( category.c_str(), LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1 ); syslog( LOG_NOTICE, "%s", message.c_str() ); closelog(); } } void Log::trace(const std::string &category, const std::string &message) { log(category, message, LogLevel::Trace); } void Log::debug(const std::string& category, const std::string& message) { log( category, message, LogLevel::Debug ); } void Log::info(const std::string& category, const std::string& message) { log( category, message, LogLevel::Info ); } void Log::warning(const std::string& category, const std::string& message) { log(category, message, LogLevel::Warning ); } void Log::error(const std::string& category, const std::string& message) { log(category, message, LogLevel::Error ); } void Log::trace(const char *file, int line, const std::string &category, const std::string &message) { log(category, fileinfoMessage(file, line, message), LogLevel::Trace ); } void Log::debug(const char* file, int line, const std::string& category, const std::string& message) { log( category, fileinfoMessage(file, line, message), LogLevel::Debug ); } void Log::info(const char* file, int line, const std::string& category, const std::string& message) { log( category, fileinfoMessage(file, line, message), LogLevel::Info ); } void Log::warning(const char* file, int line, const std::string& category, const std::string& message) { log( category, fileinfoMessage(file, line, message), LogLevel::Warning); } void Log::error(const char* file, int line, const std::string& category, const std::string& message) { log( category, fileinfoMessage(file, line, message), LogLevel::Error ); } void Log::ReplaceAll( std::string &strToReplace, const std::string& from_chars, const std::string& to_chars ) { size_t start_pos = 0; while( ( start_pos = strToReplace.find( from_chars, start_pos ) ) != std::string::npos ) { strToReplace.replace( start_pos, from_chars.length(), to_chars ); start_pos += to_chars.length(); // Handles case where 'to' is a substring of 'from' } }