nlsCppSdk/utils/nlog.cpp (352 lines of code) (raw):

/* * Copyright 2021 Alibaba Group Holding Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdarg.h> #include <stdio.h> #include <string.h> #include <ctime> #include <iostream> #if defined(__ANDRIOD__) #include <android/log.h> #elif defined(_MSC_VER) || defined(__linux__) #include "log4cpp/Appender.hh" #include "log4cpp/Category.hh" #include "log4cpp/FileAppender.hh" #include "log4cpp/PatternLayout.hh" #include "log4cpp/Priority.hh" #include "log4cpp/RollingFileAppender.hh" #endif #include "event.h" #include "nlog.h" #include "utility.h" namespace AlibabaNls { namespace utility { using std::cout; using std::endl; using std::string; #define LOG_BUFFER_SIZE 2048 #define LOG_BUFFER_PLUS_SIZE 2560 #define LOG_FILES_NUMBER 20 #define LOG_FILE_BASE_SIZE 1024 * 1024 #define LOG_TAG "AliSpeechLib" #define LOG_FORMAT_STRING(a, l, f, b) \ do { \ char tmpBuffer[LOG_BUFFER_SIZE] = {0}; \ va_list arg; \ va_start(arg, f); \ vsnprintf(tmpBuffer, LOG_BUFFER_SIZE - 1, f, arg); \ va_end(arg); \ _ssnprintf(b, LOG_BUFFER_SIZE, "[ID:0x%lx][%s:%d]%s", pthreadSelfId(), a, \ l, tmpBuffer); \ } while (0) #define LOG_WASH(in, str) \ do { \ std::string delim = "%"; \ std::vector<std::string> str_vector; \ std::string tmp_str(in); \ int pos1 = 0; \ int pos2 = tmp_str.find(delim); \ int len = delim.length(); \ while (pos2 != string::npos) { \ str_vector.push_back(tmp_str.substr(pos1, pos2 - pos1)); \ pos1 = pos2 + len; \ pos2 = tmp_str.find(delim, pos1); \ } \ if (pos1 != tmp_str.length()) { \ str_vector.push_back(tmp_str.substr(pos1)); \ } \ std::vector<std::string>::iterator iter; \ for (iter = str_vector.begin(); iter != str_vector.end();) { \ str += *iter; \ if (++iter != str_vector.end()) { \ str += "%%"; \ } \ } \ } while (0) #define LOG_PRINT_COMMON(level, message) \ do { \ time_t tt = time(NULL); \ struct tm* ptm = localtime(&tt); \ fprintf(stdout, "%4d-%02d-%02d %02d:%02d:%02d %s(%s): %s\n", \ (int)ptm->tm_year + 1900, (int)ptm->tm_mon + 1, (int)ptm->tm_mday, \ (int)ptm->tm_hour, (int)ptm->tm_min, (int)ptm->tm_sec, LOG_TAG, \ level, message); \ } while (0) #define LOG_PRINT_CALLBACK(level, message, callback) \ do { \ if (callback) { \ time_t ttc = time(NULL); \ struct tm* ptmc = localtime(&ttc); \ char timestamp[128] = {0}; \ char log_mesg[LOG_BUFFER_PLUS_SIZE] = {0}; \ snprintf(timestamp, 128, "%4d-%02d-%02d %02d:%02d:%02d", \ (int)ptmc->tm_year + 1900, (int)ptmc->tm_mon + 1, \ (int)ptmc->tm_mday, (int)ptmc->tm_hour, (int)ptmc->tm_min, \ (int)ptmc->tm_sec); \ snprintf(log_mesg, LOG_BUFFER_PLUS_SIZE, "[%s] %s", LOG_TAG, message); \ callback(timestamp, level, log_mesg); \ } \ } while (0) #if defined(_MSC_VER) HANDLE NlsLog::_mtxLog = CreateMutex(NULL, FALSE, NULL); #else pthread_mutex_t NlsLog::_mtxLog = PTHREAD_MUTEX_INITIALIZER; #endif NlsLog* NlsLog::_logInstance = NULL; NlsLog::NlsLog() : _callback(NULL), _logLevel(1), _isStdout(true), _isConfig(false), _logFileName(""), _logLibeventFileName("") {} NlsLog::~NlsLog() { #if (!defined(__ANDRIOD__)) && (!defined(__APPLE__)) #if defined(_MSC_VER) || defined(__linux__) if (!_isStdout && _isConfig) { log4cpp::Category::shutdown(); } #endif #endif _isStdout = true; _isConfig = false; _callback = NULL; } unsigned long NlsLog::pthreadSelfId() { #if defined(_MSC_VER) return GetCurrentThreadId(); #elif defined(__APPLE__) return pthread_self()->__sig; #else return pthread_self(); #endif } NlsLog* NlsLog::getInstance() { if (_logInstance == NULL) { _logInstance = new NlsLog(); } return _logInstance; } void NlsLog::destroyLogInstance() { if (_logInstance) { delete _logInstance; _logInstance = NULL; } } #if (!defined(__ANDRIOD__)) && (!defined(__APPLE__)) #if defined(_MSC_VER) || defined(__linux__) static log4cpp::Category& getCategory() { log4cpp::Category& _category = log4cpp::Category::getRoot().getInstance("alibabaNlsLog"); return _category; } #endif #endif void NlsLog::logConfig(const char* name, int level, size_t fileSize, size_t fileNum, LogCallbackMethod callback) { if (name) { cout << "Begin LogConfig: " << _isConfig << " , " << name << " , " << level << " , " << fileSize << endl; } else { cout << "Begin LogConfig: " << _isConfig << " , " << level << " , " << fileSize << endl; } if (fileNum < 1) { fileNum = LOG_FILES_NUMBER; } _callback = callback; MUTEX_LOCK(_mtxLog); if (!_isConfig) { #if (!defined(__ANDRIOD__)) && (!defined(__APPLE__)) if (name && (fileSize > 0)) { log4cpp::PatternLayout* layout; layout = new log4cpp::PatternLayout(); layout->setConversionPattern("%d: %p %c%x: %m%n"); _logFileName = name; _logLibeventFileName = name; _logFileName += ".log"; _logLibeventFileName += "_libevent.log"; log4cpp::RollingFileAppender* rollfileAppender; rollfileAppender = new log4cpp::RollingFileAppender( name, _logFileName, fileSize * LOG_FILE_BASE_SIZE, fileNum); rollfileAppender->setLayout(layout); switch (level) { case 1: log4cpp::Category::getRoot().setPriority(log4cpp::Priority::ERROR); break; case 2: log4cpp::Category::getRoot().setPriority(log4cpp::Priority::WARN); break; case 3: log4cpp::Category::getRoot().setPriority(log4cpp::Priority::INFO); break; case 4: log4cpp::Category::getRoot().setPriority(log4cpp::Priority::DEBUG); break; default: log4cpp::Category::getRoot().setPriority(log4cpp::Priority::ERROR); break; } getCategory().addAppender(rollfileAppender); _isStdout = false; } else { _isStdout = true; } #endif _logLevel = level; _isConfig = true; } MUTEX_UNLOCK(_mtxLog); cout << "LogConfig Done." << endl; return; } void NlsLog::logVerbose(const char* function, int line, const char* format, ...) { if (!format || !_isConfig) { return; } char message[LOG_BUFFER_PLUS_SIZE] = {0}; std::string str_in = ""; LOG_FORMAT_STRING(function, line, format, message); LOG_WASH(message, str_in); #if defined(__ANDRIOD__) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", str_in.c_str()); #elif defined(_MSC_VER) || defined(__linux__) if (!_isStdout) { getCategory().debug(str_in.c_str()); } else { LOG_PRINT_COMMON("VERBOSE", str_in.c_str()); } #else LOG_PRINT_COMMON("VERBOSE", str_in.c_str()); #endif LOG_PRINT_CALLBACK(AlibabaNls::LogDebug, str_in.c_str(), _callback); } void NlsLog::logDebug(const char* function, int line, const char* format, ...) { if (!format || !_isConfig) { return; } if (_logLevel >= 4) { char message[LOG_BUFFER_PLUS_SIZE] = {0}; std::string str_in = ""; LOG_FORMAT_STRING(function, line, format, message); LOG_WASH(message, str_in); #if defined(__ANDRIOD__) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", str_in.c_str()); #elif defined(_MSC_VER) || defined(__linux__) if (!_isStdout) { getCategory().debug(str_in.c_str()); } else { LOG_PRINT_COMMON("DEBUG", str_in.c_str()); } #else LOG_PRINT_COMMON("DEBUG", str_in.c_str()); #endif LOG_PRINT_CALLBACK(AlibabaNls::LogDebug, str_in.c_str(), _callback); } } void NlsLog::logInfo(const char* function, int line, const char* format, ...) { if (!format || !_isConfig) { return; } if (_logLevel >= 3) { char message[LOG_BUFFER_PLUS_SIZE] = {0}; std::string str_in = ""; LOG_FORMAT_STRING(function, line, format, message); LOG_WASH(message, str_in); #if defined(__ANDRIOD__) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", str_in.c_str()); #elif defined(_MSC_VER) || defined(__linux__) if (!_isStdout) { getCategory().info(str_in.c_str()); } else { LOG_PRINT_COMMON("INFO", str_in.c_str()); } #else LOG_PRINT_COMMON("INFO", str_in.c_str()); #endif LOG_PRINT_CALLBACK(AlibabaNls::LogInfo, str_in.c_str(), _callback); } } void NlsLog::logWarn(const char* function, int line, const char* format, ...) { if (!format || !_isConfig) { return; } if (_logLevel >= 2) { char message[LOG_BUFFER_PLUS_SIZE] = {0}; std::string str_in = ""; LOG_FORMAT_STRING(function, line, format, message); LOG_WASH(message, str_in); #if defined(__ANDRIOD__) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", str_in.c_str()); #elif defined(_MSC_VER) || defined(__linux__) if (!_isStdout) { getCategory().warn(str_in.c_str()); } else { LOG_PRINT_COMMON("WARN", str_in.c_str()); } #else LOG_PRINT_COMMON("WARN", str_in.c_str()); #endif LOG_PRINT_CALLBACK(AlibabaNls::LogWarning, str_in.c_str(), _callback); } } void NlsLog::logError(const char* function, int line, const char* format, ...) { if (!format || !_isConfig) { return; } if (_logLevel >= 1) { char message[LOG_BUFFER_PLUS_SIZE] = {0}; std::string str_in = ""; LOG_FORMAT_STRING(function, line, format, message); LOG_WASH(message, str_in); #if defined(__ANDRIOD__) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", str_in.c_str()); #elif defined(_MSC_VER) || defined(__linux__) if (!_isStdout) { getCategory().error(str_in.c_str()); } else { LOG_PRINT_COMMON("ERROR", str_in.c_str()); } #else LOG_PRINT_COMMON("ERROR", str_in.c_str()); #endif LOG_PRINT_CALLBACK(AlibabaNls::LogError, str_in.c_str(), _callback); } } // FATAL void NlsLog::logException(const char* function, int line, const char* format, ...) { if (!format || !_isConfig) { return; } char message[LOG_BUFFER_PLUS_SIZE] = {0}; std::string str_in = ""; LOG_FORMAT_STRING(function, line, format, message); LOG_WASH(message, str_in); #if defined(__ANDRIOD__) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", str_in.c_str()); #elif defined(_MSC_VER) || defined(__linux__) if (!_isStdout) { getCategory().fatal(str_in.c_str()); } else { LOG_PRINT_COMMON("EXCEPTION", str_in.c_str()); } #else LOG_PRINT_COMMON("EXCEPTION", str_in.c_str()); #endif LOG_PRINT_CALLBACK(AlibabaNls::LogError, str_in.c_str(), _callback); } void NlsLog::dumpEvents(void* evbase) { #ifdef ENABLE_NLS_DEBUG if (!_logLibeventFileName.empty()) { FILE* f = fopen(_logLibeventFileName.c_str(), "a+"); if (f) { char log_mesg[256] = {0}; snprintf(log_mesg, 256, "Dump events about evbase %p:\n", evbase); fwrite(log_mesg, strnlen(log_mesg, 256), 1, f); struct event_base* base = (struct event_base*)evbase; event_base_dump_events(base, f); fclose(f); } } #endif } } // namespace utility } // namespace AlibabaNls