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 #include "common_components/log/log.h"
17
18 #include "generated/base_options.h"
19 #include "libpandabase/utils/logger.h"
20
21 #ifdef ENABLE_ANLOG
22 #include <android/log.h>
23 #endif
24
25 namespace common {
26 #ifdef ENABLE_HILOG
ConvertToLevel(LogLevel hilogLevel)27 Level ConvertToLevel(LogLevel hilogLevel)
28 {
29 Level level = Level::ERROR;
30 std::string logLevel;
31 switch (hilogLevel) { //LCOV_EXCL_BR_LINE
32 case LogLevel::LOG_INFO: //LCOV_EXCL_BR_LINE
33 level = Level::INFO;
34 break;
35 case LogLevel::LOG_WARN: //LCOV_EXCL_BR_LINE
36 level = Level::WARN;
37 break;
38 case LogLevel::LOG_ERROR: //LCOV_EXCL_BR_LINE
39 level = Level::ERROR;
40 break;
41 case LogLevel::LOG_FATAL: //LCOV_EXCL_BR_LINE
42 case LogLevel::LOG_LEVEL_MAX: //LCOV_EXCL_BR_LINE
43 level = Level::FATAL;
44 break;
45 case LogLevel::LOG_DEBUG: //LCOV_EXCL_BR_LINE
46 default: //LCOV_EXCL_BR_LINE
47 level = Level::DEBUG;
48 break;
49 }
50
51 return level;
52 }
53
GetHiLogLevel()54 LogLevel GetHiLogLevel()
55 {
56 for (int32_t level = LogLevel::LOG_LEVEL_MIN; level <= LogLevel::LOG_LEVEL_MAX; level++) { //LCOV_EXCL_BR_LINE
57 if (HiLogIsLoggable(LOG_DOMAIN, LOG_TAG, static_cast<LogLevel>(level))) { //LCOV_EXCL_BR_LINE
58 return static_cast<LogLevel>(level);
59 }
60 }
61 return LogLevel::LOG_LEVEL_MAX;
62 }
63 #endif
64
65 Level Log::level_ = Level::ERROR;
66 ComponentMark Log::components_ = static_cast<ComponentMark>(Component::ALL);
67
ConvertFromRuntime(LOG_LEVEL level)68 Level Log::ConvertFromRuntime(LOG_LEVEL level)
69 {
70 Level logLevel = Level::INFO;
71 switch (level) { //LCOV_EXCL_BR_LINE
72 case LOG_LEVEL::FOLLOW: //LCOV_EXCL_BR_LINE
73 #ifdef ENABLE_HILOG
74 logLevel = ConvertToLevel(GetHiLogLevel());
75 break;
76 #endif
77 case LOG_LEVEL::INFO: //LCOV_EXCL_BR_LINE
78 logLevel = Level::INFO;
79 break;
80 case LOG_LEVEL::WARN: //LCOV_EXCL_BR_LINE
81 logLevel = Level::WARN;
82 break;
83 case LOG_LEVEL::ERROR: //LCOV_EXCL_BR_LINE
84 logLevel = Level::ERROR;
85 break;
86 case LOG_LEVEL::FATAL: //LCOV_EXCL_BR_LINE
87 logLevel = Level::FATAL;
88 break;
89 case LOG_LEVEL::DEBUG: //LCOV_EXCL_BR_LINE
90 default: //LCOV_EXCL_BR_LINE
91 logLevel = Level::DEBUG;
92 break;
93 }
94
95 return logLevel;
96 }
97
LevelToString(Level level)98 std::string Log::LevelToString(Level level)
99 {
100 std::string logLevel;
101 switch (level) { //LCOV_EXCL_BR_LINE
102 case Level::INFO: //LCOV_EXCL_BR_LINE
103 logLevel = "info";
104 break;
105 case Level::WARN: //LCOV_EXCL_BR_LINE
106 logLevel = "warning";
107 break;
108 case Level::ERROR: //LCOV_EXCL_BR_LINE
109 logLevel = "error";
110 break;
111 case Level::FATAL: //LCOV_EXCL_BR_LINE
112 logLevel = "fatal";
113 break;
114 case Level::DEBUG: //LCOV_EXCL_BR_LINE
115 default: //LCOV_EXCL_BR_LINE
116 logLevel = "debug";
117 break;
118 }
119
120 return logLevel;
121 }
122
PrintLogger(int32_t,int32_t level,const char *,const char *,const char * message)123 int32_t Log::PrintLogger(int32_t, int32_t level, const char *, const char *, const char *message)
124 {
125 switch (level) { //LCOV_EXCL_BR_LINE
126 case panda::Logger::PandaLog2MobileLog::VERBOSE: //LCOV_EXCL_BR_LINE
127 LOG_COMMON(VERBOSE) << message;
128 break;
129 case panda::Logger::PandaLog2MobileLog::DEBUG: //LCOV_EXCL_BR_LINE
130 LOG_COMMON(DEBUG) << message;
131 break;
132 case panda::Logger::PandaLog2MobileLog::INFO: //LCOV_EXCL_BR_LINE
133 LOG_COMMON(INFO) << message;
134 break;
135 case panda::Logger::PandaLog2MobileLog::WARN: //LCOV_EXCL_BR_LINE
136 LOG_COMMON(WARN) << message;
137 break;
138 case panda::Logger::PandaLog2MobileLog::ERROR: //LCOV_EXCL_BR_LINE
139 LOG_COMMON(ERROR) << message;
140 break;
141 case panda::Logger::PandaLog2MobileLog::FATAL: //LCOV_EXCL_BR_LINE
142 LOG_COMMON(FATAL) << message;
143 break;
144 default: //LCOV_EXCL_BR_LINE
145 LOG_COMMON(DEBUG) << message;
146 break;
147 }
148 return 0;
149 }
150
Initialize(const LogOptions & options)151 void Log::Initialize(const LogOptions &options)
152 {
153 // For ArkTS runtime log
154 level_ = options.level;
155 components_ = options.component;
156
157 // For runtime core log
158 panda::base_options::Options baseOptions("");
159 baseOptions.SetLogLevel(LevelToString(level_));
160 baseOptions.SetLogComponents({ "all" });
161 panda::Logger::Initialize(baseOptions);
162 panda::Logger::SetMobileLogPrintEntryPointByPtr(reinterpret_cast<void *>(Log::PrintLogger));
163 }
164
165 #ifdef ENABLE_ANLOG
166 const char *tag = "ArkCompiler";
167 template<>
~AndroidLog()168 PUBLIC_API AndroidLog<Level::VERBOSE>::~AndroidLog()
169 {
170 __android_log_write(ANDROID_LOG_VERBOSE, tag, stream_.str().c_str());
171 }
172
173 template<>
~AndroidLog()174 PUBLIC_API AndroidLog<Level::DEBUG>::~AndroidLog()
175 {
176 __android_log_write(ANDROID_LOG_DEBUG, tag, stream_.str().c_str());
177 }
178
179 template<>
~AndroidLog()180 PUBLIC_API AndroidLog<Level::INFO>::~AndroidLog()
181 {
182 __android_log_write(ANDROID_LOG_INFO, tag, stream_.str().c_str());
183 }
184
185 template<>
~AndroidLog()186 PUBLIC_API AndroidLog<Level::WARN>::~AndroidLog()
187 {
188 __android_log_write(ANDROID_LOG_WARN, tag, stream_.str().c_str());
189 }
190
191 template<>
~AndroidLog()192 PUBLIC_API AndroidLog<Level::ERROR>::~AndroidLog()
193 {
194 __android_log_write(ANDROID_LOG_ERROR, tag, stream_.str().c_str());
195 }
196
197 template<>
~AndroidLog()198 PUBLIC_API AndroidLog<Level::FATAL>::~AndroidLog()
199 {
200 __android_log_write(ANDROID_LOG_FATAL, tag, stream_.str().c_str());
201 std::abort();
202 }
203 #endif
204
205 // Orders of magnitudes. Note: The upperbound of uint64_t is 16E (16 * (1024 ^ 6))
206 const char* g_orderOfMagnitude[] = { "", "K", "M", "G", "T", "P", "E" };
207
208 // Orders of magnitudes. Note: The upperbound of uint64_t is 16E (16 * (1024 ^ 6))
209 const char* g_orderOfMagnitudeFromNano[] = { "n", "u", "m", nullptr };
210
211 // number of digits in a pretty format segment (100,000,000 each has three digits)
212 constexpr int NUM_DIGITS_PER_SEGMENT = 3;
213
Pretty(uint64_t number)214 std::string Pretty(uint64_t number) noexcept
215 {
216 std::string orig = std::to_string(number);
217 int pos = static_cast<int>(orig.length()) - NUM_DIGITS_PER_SEGMENT;
218 while (pos > 0) {
219 orig.insert(pos, ",");
220 pos -= NUM_DIGITS_PER_SEGMENT;
221 }
222 return orig;
223 }
224
225 // Useful for informatic units, such as KiB, MiB, GiB, ...
PrettyOrderInfo(uint64_t number,const char * unit)226 std::string PrettyOrderInfo(uint64_t number, const char* unit)
227 {
228 size_t order = 0;
229 const uint64_t factor = 1024;
230
231 while (number > factor) {
232 number /= factor;
233 order += 1;
234 }
235
236 const char* prefix = g_orderOfMagnitude[order];
237 const char* infix = order > 0 ? "i" : ""; // 1KiB = 1024B, but there is no "1iB"
238
239 return std::to_string(number) + prefix + infix + unit;
240 }
241
242 // Useful for scientific units where number is in nanos: ns, us, ms, s
PrettyOrderMathNano(uint64_t number,const char * unit)243 std::string PrettyOrderMathNano(uint64_t number, const char* unit)
244 {
245 size_t order = 0;
246 const uint64_t factor = 1000; // show in us if under 10ms
247
248 while (number > factor && g_orderOfMagnitudeFromNano[order] != nullptr) {
249 number /= factor;
250 order += 1;
251 }
252
253 const char* prefix = g_orderOfMagnitudeFromNano[order];
254 if (prefix == nullptr) {
255 prefix = "";
256 }
257
258 return std::to_string(number) + prefix + unit;
259 }
260
261 constexpr size_t LOG_BUFFER_SIZE = 1024;
262
FormatLogMessage(const char * format,va_list agrs)263 std::string FormatLogMessage(const char* format, va_list agrs) noexcept
264 {
265 char buf[LOG_BUFFER_SIZE];
266 int ret = vsprintf_s(buf, sizeof(buf), format, agrs);
267 if (ret < 0) {
268 return std::string("Log format error: ") + strerror(errno);
269 }
270 return std::string(buf, ret);
271 }
272
FormatLog(const char * format,...)273 std::string FormatLog(const char* format, ...) noexcept
274 {
275 va_list args;
276 va_start(args, format);
277 auto msg = FormatLogMessage(format, args);
278 va_end(args);
279 return "[CMC GC] " + msg;
280 }
281 } // namespace common