18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#include "logger.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <cstdarg> 198bf80f4bSopenharmony_ci#include <mutex> 208bf80f4bSopenharmony_ci#include <securec.h> 218bf80f4bSopenharmony_ci#include <set> 228bf80f4bSopenharmony_ci 238bf80f4bSopenharmony_ci#include <base/containers/iterator.h> 248bf80f4bSopenharmony_ci#include <base/containers/string.h> 258bf80f4bSopenharmony_ci#include <base/containers/string_view.h> 268bf80f4bSopenharmony_ci#include <base/containers/type_traits.h> 278bf80f4bSopenharmony_ci#include <base/containers/unique_ptr.h> 288bf80f4bSopenharmony_ci#include <base/containers/vector.h> 298bf80f4bSopenharmony_ci#include <base/namespace.h> 308bf80f4bSopenharmony_ci#include <base/util/uid.h> 318bf80f4bSopenharmony_ci#include <core/intf_logger.h> 328bf80f4bSopenharmony_ci#include <core/log.h> 338bf80f4bSopenharmony_ci#include <core/namespace.h> 348bf80f4bSopenharmony_ci 358bf80f4bSopenharmony_ci#ifdef PLATFORM_HAS_JAVA 368bf80f4bSopenharmony_ci#include <os/java/java_internal.h> 378bf80f4bSopenharmony_ci#endif 388bf80f4bSopenharmony_ci 398bf80f4bSopenharmony_ci#include "log/logger_output.h" 408bf80f4bSopenharmony_ci 418bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE() 428bf80f4bSopenharmony_ciusing BASE_NS::string; 438bf80f4bSopenharmony_ciusing BASE_NS::string_view; 448bf80f4bSopenharmony_ciusing BASE_NS::Uid; 458bf80f4bSopenharmony_ci 468bf80f4bSopenharmony_cinamespace { 478bf80f4bSopenharmony_ci// Note: these must match the LogLevel enum. 488bf80f4bSopenharmony_ciconstexpr int LOG_LEVEL_COUNT = 7; 498bf80f4bSopenharmony_ciconstexpr const char* LOG_LEVEL_NAMES[LOG_LEVEL_COUNT] = { 508bf80f4bSopenharmony_ci "Verbose", 518bf80f4bSopenharmony_ci "Debug", 528bf80f4bSopenharmony_ci "Info", 538bf80f4bSopenharmony_ci "Warning", 548bf80f4bSopenharmony_ci "Error", 558bf80f4bSopenharmony_ci "Fatal", 568bf80f4bSopenharmony_ci "None", 578bf80f4bSopenharmony_ci}; 588bf80f4bSopenharmony_ci 598bf80f4bSopenharmony_ciconstexpr const char* LOG_LEVEL_NAMES_SHORT[LOG_LEVEL_COUNT] = { 608bf80f4bSopenharmony_ci "V", 618bf80f4bSopenharmony_ci "D", 628bf80f4bSopenharmony_ci "I", 638bf80f4bSopenharmony_ci "W", 648bf80f4bSopenharmony_ci "E", 658bf80f4bSopenharmony_ci "F", 668bf80f4bSopenharmony_ci "N", 678bf80f4bSopenharmony_ci}; 688bf80f4bSopenharmony_ciconstexpr const size_t MAX_BUFFER_SIZE = 1024; 698bf80f4bSopenharmony_ci} // namespace 708bf80f4bSopenharmony_ci 718bf80f4bSopenharmony_cistring_view Logger::GetLogLevelName(LogLevel logLevel, bool shortName) 728bf80f4bSopenharmony_ci{ 738bf80f4bSopenharmony_ci const int level = static_cast<int>(logLevel); 748bf80f4bSopenharmony_ci CORE_ASSERT(level >= 0 && level < LOG_LEVEL_COUNT); 758bf80f4bSopenharmony_ci 768bf80f4bSopenharmony_ci return shortName ? LOG_LEVEL_NAMES_SHORT[level] : LOG_LEVEL_NAMES[level]; 778bf80f4bSopenharmony_ci} 788bf80f4bSopenharmony_ci 798bf80f4bSopenharmony_ciLogger::Logger(bool defaultOutputs) 808bf80f4bSopenharmony_ci#ifdef NDEBUG 818bf80f4bSopenharmony_ci : logLevel_(LogLevel::LOG_ERROR) 828bf80f4bSopenharmony_ci#endif 838bf80f4bSopenharmony_ci{ 848bf80f4bSopenharmony_ci if (defaultOutputs) { 858bf80f4bSopenharmony_ci#if CORE_LOG_TO_CONSOLE == 1 868bf80f4bSopenharmony_ci AddOutput(CreateLoggerConsoleOutput()); 878bf80f4bSopenharmony_ci#endif 888bf80f4bSopenharmony_ci 898bf80f4bSopenharmony_ci#if CORE_LOG_TO_DEBUG_OUTPUT == 1 908bf80f4bSopenharmony_ci AddOutput(CreateLoggerDebugOutput()); 918bf80f4bSopenharmony_ci#endif 928bf80f4bSopenharmony_ci 938bf80f4bSopenharmony_ci#if CORE_LOG_TO_FILE == 1 948bf80f4bSopenharmony_ci AddOutput(CreateLoggerFileOutput("./logfile.txt")); 958bf80f4bSopenharmony_ci#endif 968bf80f4bSopenharmony_ci } 978bf80f4bSopenharmony_ci} 988bf80f4bSopenharmony_ci 998bf80f4bSopenharmony_civoid Logger::VLog( 1008bf80f4bSopenharmony_ci LogLevel logLevel, const string_view filename, int lineNumber, const string_view format, std::va_list args) 1018bf80f4bSopenharmony_ci{ 1028bf80f4bSopenharmony_ci CORE_ASSERT_MSG(logLevel != LogLevel::LOG_NONE, "'None' is not a valid log level for writing to the log."); 1038bf80f4bSopenharmony_ci 1048bf80f4bSopenharmony_ci if (logLevel_ > logLevel) { 1058bf80f4bSopenharmony_ci return; 1068bf80f4bSopenharmony_ci } 1078bf80f4bSopenharmony_ci 1088bf80f4bSopenharmony_ci // we need to make a copy of the args, since the va_list can be in an undefined state after use. 1098bf80f4bSopenharmony_ci std::va_list tmp; 1108bf80f4bSopenharmony_ci va_copy(tmp, args); 1118bf80f4bSopenharmony_ci 1128bf80f4bSopenharmony_ci // use vsnprintf to calculate the required size (not supported by the _s variant) 1138bf80f4bSopenharmony_ci const int sizeNeeded = vsnprintf(nullptr, 0, format.data(), args) + 1; 1148bf80f4bSopenharmony_ci 1158bf80f4bSopenharmony_ci std::lock_guard guard(loggerMutex_); 1168bf80f4bSopenharmony_ci 1178bf80f4bSopenharmony_ci if (sizeNeeded > 0 && static_cast<size_t>(sizeNeeded) > buffer_.size()) { 1188bf80f4bSopenharmony_ci buffer_.resize(static_cast<size_t>(sizeNeeded)); 1198bf80f4bSopenharmony_ci } 1208bf80f4bSopenharmony_ci 1218bf80f4bSopenharmony_ci int ret = vsnprintf_s(buffer_.data(), buffer_.size(), buffer_.size() - 1, format.data(), tmp); 1228bf80f4bSopenharmony_ci va_end(tmp); 1238bf80f4bSopenharmony_ci if (ret < 0) { 1248bf80f4bSopenharmony_ci return; 1258bf80f4bSopenharmony_ci } 1268bf80f4bSopenharmony_ci 1278bf80f4bSopenharmony_ci for (auto& output : outputs_) { 1288bf80f4bSopenharmony_ci output->Write(logLevel, filename, lineNumber, buffer_.data()); 1298bf80f4bSopenharmony_ci } 1308bf80f4bSopenharmony_ci} 1318bf80f4bSopenharmony_ci 1328bf80f4bSopenharmony_civoid Logger::VLogOnce(const string_view id, LogLevel logLevel, const string_view filename, int lineNumber, 1338bf80f4bSopenharmony_ci const string_view format, std::va_list args) 1348bf80f4bSopenharmony_ci{ 1358bf80f4bSopenharmony_ci std::lock_guard<std::mutex> guard(onceMutex_); 1368bf80f4bSopenharmony_ci 1378bf80f4bSopenharmony_ci auto const [pos, inserted] = registeredOnce_.insert(string(id)); 1388bf80f4bSopenharmony_ci if (inserted) { 1398bf80f4bSopenharmony_ci VLog(logLevel, filename, lineNumber, format, args); 1408bf80f4bSopenharmony_ci } 1418bf80f4bSopenharmony_ci} 1428bf80f4bSopenharmony_ci 1438bf80f4bSopenharmony_cibool Logger::VLogAssert(const string_view filename, int lineNumber, bool expression, const string_view expressionString, 1448bf80f4bSopenharmony_ci const string_view format, std::va_list args) 1458bf80f4bSopenharmony_ci{ 1468bf80f4bSopenharmony_ci if (!expression) { 1478bf80f4bSopenharmony_ci char buffer[MAX_BUFFER_SIZE]; 1488bf80f4bSopenharmony_ci const int numWritten = vsnprintf_s(buffer, MAX_BUFFER_SIZE, MAX_BUFFER_SIZE - 1, format.data(), args); 1498bf80f4bSopenharmony_ci if (numWritten >= 0) { 1508bf80f4bSopenharmony_ci buffer[numWritten] = '\0'; 1518bf80f4bSopenharmony_ci } else { 1528bf80f4bSopenharmony_ci buffer[0] = '\0'; 1538bf80f4bSopenharmony_ci } 1548bf80f4bSopenharmony_ci 1558bf80f4bSopenharmony_ci Log(LogLevel::LOG_FATAL, filename, lineNumber, "Assert failed (%s). %s", expressionString.data(), buffer); 1568bf80f4bSopenharmony_ci 1578bf80f4bSopenharmony_ci#ifdef PLATFORM_HAS_JAVA 1588bf80f4bSopenharmony_ci // Print also a java trace if available 1598bf80f4bSopenharmony_ci Log(LogLevel::LOG_FATAL, filename, lineNumber, "Java trace:"); 1608bf80f4bSopenharmony_ci JNIEnv* env = java_internal::GetJavaEnv(); 1618bf80f4bSopenharmony_ci if (env) { 1628bf80f4bSopenharmony_ci jclass cls = env->FindClass("java/lang/Exception"); 1638bf80f4bSopenharmony_ci if (cls) { 1648bf80f4bSopenharmony_ci jmethodID constructor = env->GetMethodID(cls, "<init>", "()V"); 1658bf80f4bSopenharmony_ci jobject exception = env->NewObject(cls, constructor); 1668bf80f4bSopenharmony_ci jmethodID printStackTrace = env->GetMethodID(cls, "printStackTrace", "()V"); 1678bf80f4bSopenharmony_ci env->CallVoidMethod(exception, printStackTrace); 1688bf80f4bSopenharmony_ci env->DeleteLocalRef(exception); 1698bf80f4bSopenharmony_ci } 1708bf80f4bSopenharmony_ci } 1718bf80f4bSopenharmony_ci#endif 1728bf80f4bSopenharmony_ci } 1738bf80f4bSopenharmony_ci 1748bf80f4bSopenharmony_ci return expression; 1758bf80f4bSopenharmony_ci} 1768bf80f4bSopenharmony_ci 1778bf80f4bSopenharmony_civoid Logger::CheckOnceReset() 1788bf80f4bSopenharmony_ci{ 1798bf80f4bSopenharmony_ci std::lock_guard<std::mutex> guard(onceMutex_); 1808bf80f4bSopenharmony_ci registeredOnce_.clear(); 1818bf80f4bSopenharmony_ci} 1828bf80f4bSopenharmony_ci 1838bf80f4bSopenharmony_ciFORMAT_FUNC(5, 6) 1848bf80f4bSopenharmony_civoid Logger::Log( 1858bf80f4bSopenharmony_ci LogLevel logLevel, const string_view filename, int lineNumber, FORMAT_ATTRIBUTE const char* format, ...) 1868bf80f4bSopenharmony_ci{ 1878bf80f4bSopenharmony_ci std::va_list vl; 1888bf80f4bSopenharmony_ci va_start(vl, format); 1898bf80f4bSopenharmony_ci VLog(logLevel, filename, lineNumber, format, vl); 1908bf80f4bSopenharmony_ci va_end(vl); 1918bf80f4bSopenharmony_ci} 1928bf80f4bSopenharmony_ci 1938bf80f4bSopenharmony_ciFORMAT_FUNC(6, 7) 1948bf80f4bSopenharmony_cibool Logger::LogAssert(const string_view filename, int lineNumber, bool expression, const string_view expressionString, 1958bf80f4bSopenharmony_ci FORMAT_ATTRIBUTE const char* format, ...) 1968bf80f4bSopenharmony_ci{ 1978bf80f4bSopenharmony_ci if (!expression) { 1988bf80f4bSopenharmony_ci std::va_list vl; 1998bf80f4bSopenharmony_ci va_start(vl, format); 2008bf80f4bSopenharmony_ci VLogAssert(filename, lineNumber, expression, expressionString, format, vl); 2018bf80f4bSopenharmony_ci va_end(vl); 2028bf80f4bSopenharmony_ci } 2038bf80f4bSopenharmony_ci return expression; 2048bf80f4bSopenharmony_ci} 2058bf80f4bSopenharmony_ci 2068bf80f4bSopenharmony_ciILogger::LogLevel Logger::GetLogLevel() const 2078bf80f4bSopenharmony_ci{ 2088bf80f4bSopenharmony_ci return logLevel_; 2098bf80f4bSopenharmony_ci} 2108bf80f4bSopenharmony_ci 2118bf80f4bSopenharmony_civoid Logger::SetLogLevel(LogLevel logLevel) 2128bf80f4bSopenharmony_ci{ 2138bf80f4bSopenharmony_ci logLevel_ = logLevel; 2148bf80f4bSopenharmony_ci} 2158bf80f4bSopenharmony_ci 2168bf80f4bSopenharmony_civoid Logger::AddOutput(IOutput::Ptr output) 2178bf80f4bSopenharmony_ci{ 2188bf80f4bSopenharmony_ci if (output) { 2198bf80f4bSopenharmony_ci std::lock_guard<std::mutex> guard(loggerMutex_); 2208bf80f4bSopenharmony_ci outputs_.push_back(move(output)); 2218bf80f4bSopenharmony_ci } 2228bf80f4bSopenharmony_ci} 2238bf80f4bSopenharmony_ci 2248bf80f4bSopenharmony_ciconst IInterface* Logger::GetInterface(const Uid& uid) const 2258bf80f4bSopenharmony_ci{ 2268bf80f4bSopenharmony_ci if ((uid == ILogger::UID) || (uid == IInterface::UID)) { 2278bf80f4bSopenharmony_ci return this; 2288bf80f4bSopenharmony_ci } 2298bf80f4bSopenharmony_ci return nullptr; 2308bf80f4bSopenharmony_ci} 2318bf80f4bSopenharmony_ci 2328bf80f4bSopenharmony_ciIInterface* Logger::GetInterface(const Uid& uid) 2338bf80f4bSopenharmony_ci{ 2348bf80f4bSopenharmony_ci if ((uid == ILogger::UID) || (uid == IInterface::UID)) { 2358bf80f4bSopenharmony_ci return this; 2368bf80f4bSopenharmony_ci } 2378bf80f4bSopenharmony_ci return nullptr; 2388bf80f4bSopenharmony_ci} 2398bf80f4bSopenharmony_ci 2408bf80f4bSopenharmony_civoid Logger::Ref() {} 2418bf80f4bSopenharmony_ci 2428bf80f4bSopenharmony_civoid Logger::Unref() {} 2438bf80f4bSopenharmony_ciCORE_END_NAMESPACE() 244