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 40 using LOG_LEVEL = panda::RuntimeOption::LOG_LEVEL; 41 enum Level { 42 VERBOSE, 43 DEBUG, 44 INFO, 45 WARN, 46 ERROR, 47 FATAL, 48 }; 49 50 using ComponentMark = uint64_t; 51 enum 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 67 namespace 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 78 class JSRuntimeOptions; 79 class PUBLIC_API Log { 80 public: 81 static void Initialize(const JSRuntimeOptions &options); LogIsLoggable(Level level, Component component)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 } GetComponentStr(Component component)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 127 private: 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) 137 template<LogLevel level, Component component> 138 class HiLog { 139 public: HiLog()140 HiLog() 141 { 142 std::string str = Log::GetComponentStr(component); 143 stream_ << str; 144 } ~HiLog()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> operator <<(type input)163 std::ostream &operator <<(type input) 164 { 165 stream_ << input; 166 return stream_; 167 } 168 169 private: 170 std::ostringstream stream_; 171 }; 172 #elif defined(ENABLE_ANLOG) // ENABLE_ANLOG 173 template<Level level> 174 class PUBLIC_API AndroidLog { 175 public: AndroidLog()176 AndroidLog() 177 { 178 std::string str = "[default] "; 179 stream_ << str; 180 } 181 ~AndroidLog(); 182 183 template<class type> operator <<(type input)184 std::ostream &operator <<(type input) 185 { 186 stream_ << input; 187 return stream_; 188 } 189 190 private: 191 std::ostringstream stream_; 192 }; 193 #else 194 template<Level level, Component component> 195 class StdLog { 196 public: StdLog()197 StdLog() 198 { 199 std::string str = Log::GetComponentStr(component); 200 stream_ << str; 201 } ~StdLog()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> operator <<(type input)216 std::ostream &operator <<(type input) 217 { 218 stream_ << input; 219 return stream_; 220 } 221 222 private: 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