• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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