1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#ifndef ECMASCRIPT_LOG_H 17#define ECMASCRIPT_LOG_H 18 19#include <cstdint> 20#include <iostream> 21#include <sstream> 22 23#include "ecmascript/common.h" 24#include "ecmascript/napi/include/jsnapi.h" 25 26#ifdef ENABLE_HILOG 27#if defined(__clang__) 28#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 29#elif defined(__GNUC__) 30#pragma GCC diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 31#endif 32#include "hilog/log.h" 33#undef LOG_DOMAIN 34#define LOG_DOMAIN 0xD003F00 35#undef LOG_TAG 36#define LOG_TAG "ArkCompiler" 37#endif 38 39 40using LOG_LEVEL = panda::RuntimeOption::LOG_LEVEL; 41enum Level { 42 VERBOSE, 43 DEBUG, 44 INFO, 45 WARN, 46 ERROR, 47 FATAL, 48}; 49 50using ComponentMark = uint64_t; 51enum Component { 52 NONE = 0ULL, 53 GC = 1ULL << 0ULL, 54 INTERPRETER = 1ULL << 1ULL, 55 COMPILER = 1ULL << 2ULL, 56 DEBUGGER = 1ULL << 3ULL, 57 ECMASCRIPT = 1ULL << 4ULL, 58 BUILTINS = 1ULL << 5ULL, 59 TRACE = 1ULL << 6ULL, 60 JIT = 1UL << 7ULL, 61 BASELINEJIT = 1UL << 8ULL, 62 SA = 1ULL << 9ULL, 63 NO_TAG = 0xFFFFFFFFULL >> 1ULL, 64 ALL = 0xFFFFFFFFULL, 65}; 66 67namespace panda::ecmascript { 68#ifdef ENABLE_HILOG 69 70#if ECMASCRIPT_ENABLE_VERBOSE_LEVEL_LOG 71// print Debug level log if enable Verbose log 72#define LOG_VERBOSE LOG_DEBUG 73#else 74#define LOG_VERBOSE LOG_LEVEL_MIN 75#endif 76#endif // ENABLE_HILOG 77 78class JSRuntimeOptions; 79class PUBLIC_API Log { 80public: 81 static void Initialize(const JSRuntimeOptions &options); 82 static inline bool LogIsLoggable(Level level, Component component) 83 { 84 switch (component) 85 { 86 case Component::SA: 87 return ((components_ & component) != 0ULL); 88 default: 89 return (level >= level_) && ((components_ & component) != 0ULL); 90 } 91 } 92 static inline std::string GetComponentStr(Component component) 93 { 94 switch (component) 95 { 96 case Component::NO_TAG: 97 return ""; 98 case Component::GC: 99 return "[gc] "; 100 case Component::ECMASCRIPT: 101 return "[ecmascript] "; 102 case Component::INTERPRETER: 103 return "[interpreter] "; 104 case Component::DEBUGGER: 105 return "[debugger] "; 106 case Component::COMPILER: 107 return "[compiler] "; 108 case Component::BUILTINS: 109 return "[builtins] "; 110 case Component::TRACE: 111 return "[trace] "; 112 case Component::JIT: 113 return "[jit] "; 114 case Component::BASELINEJIT: 115 return "[baselinejit] "; 116 case Component::SA: 117 return "[sa] "; 118 case Component::ALL: 119 return "[default] "; 120 default: 121 return "[unknown] "; 122 } 123 } 124 static std::string LevelToString(Level level); 125 static Level ConvertFromRuntime(LOG_LEVEL level); 126 127private: 128 static void SetLogLevelFromString(const std::string& level); 129 static void SetLogComponentFromString(const std::vector<std::string>& components); 130 static int32_t PrintLogger(int32_t, int32_t level, const char *, const char *, const char *message); 131 132 static Level level_; 133 static ComponentMark components_; 134}; 135 136#if defined(ENABLE_HILOG) 137template<LogLevel level, Component component> 138class HiLog { 139public: 140 HiLog() 141 { 142 std::string str = Log::GetComponentStr(component); 143 stream_ << str; 144 } 145 ~HiLog() 146 { 147 if constexpr (level == LOG_LEVEL_MIN) { 148 // print nothing 149 } else if constexpr (level == LOG_DEBUG) { 150 HILOG_DEBUG(LOG_CORE, "%{public}s", stream_.str().c_str()); 151 } else if constexpr (level == LOG_INFO) { 152 HILOG_INFO(LOG_CORE, "%{public}s", stream_.str().c_str()); 153 } else if constexpr (level == LOG_WARN) { 154 HILOG_WARN(LOG_CORE, "%{public}s", stream_.str().c_str()); 155 } else if constexpr (level == LOG_ERROR) { 156 HILOG_ERROR(LOG_CORE, "%{public}s", stream_.str().c_str()); 157 } else { 158 HILOG_FATAL(LOG_CORE, "%{public}s", stream_.str().c_str()); 159 std::abort(); 160 } 161 } 162 template<class type> 163 std::ostream &operator <<(type input) 164 { 165 stream_ << input; 166 return stream_; 167 } 168 169private: 170 std::ostringstream stream_; 171}; 172#elif defined(ENABLE_ANLOG) // ENABLE_ANLOG 173template<Level level> 174class PUBLIC_API AndroidLog { 175public: 176 AndroidLog() 177 { 178 std::string str = "[default] "; 179 stream_ << str; 180 } 181 ~AndroidLog(); 182 183 template<class type> 184 std::ostream &operator <<(type input) 185 { 186 stream_ << input; 187 return stream_; 188 } 189 190private: 191 std::ostringstream stream_; 192}; 193#else 194template<Level level, Component component> 195class StdLog { 196public: 197 StdLog() 198 { 199 std::string str = Log::GetComponentStr(component); 200 stream_ << str; 201 } 202 ~StdLog() 203 { 204 if constexpr (level == FATAL || level == ERROR) { 205 std::cerr << stream_.str().c_str() << std::endl; 206 } else { 207 std::cout << stream_.str().c_str() << std::endl; 208 } 209 210 if constexpr (level == FATAL) { 211 std::abort(); 212 } 213 } 214 215 template<class type> 216 std::ostream &operator <<(type input) 217 { 218 stream_ << input; 219 return stream_; 220 } 221 222private: 223 std::ostringstream stream_; 224}; 225#endif 226 227#if defined(ENABLE_HILOG) 228#define ARK_LOG(level, component) panda::ecmascript::Log::LogIsLoggable(level, component) && \ 229 panda::ecmascript::HiLog<LOG_##level, (component)>() 230#elif defined(ENABLE_ANLOG) 231#define ARK_LOG(level, component) panda::ecmascript::AndroidLog<(level)>() 232#else 233#if defined(OHOS_UNIT_TEST) 234#define ARK_LOG(level, component) ((level >= INFO) || panda::ecmascript::Log::LogIsLoggable(level, component)) && \ 235 panda::ecmascript::StdLog<(level), (component)>() 236#else 237#define ARK_LOG(level, component) panda::ecmascript::Log::LogIsLoggable(level, component) && \ 238 panda::ecmascript::StdLog<(level), (component)>() 239#endif 240#endif 241} // namespace panda::ecmascript 242#endif // ECMASCRIPT_LOG_H 243