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 "ecmascript/js_runtime_options.h"
17#include "ecmascript/log.h"
18#include "generated/base_options.h"
19
20#ifdef ENABLE_ANLOG
21#include <android/log.h>
22#endif
23
24namespace panda::ecmascript {
25#ifdef ENABLE_HILOG
26namespace {
27Level ConvertToLevel(LogLevel hilogLevel)
28{
29    Level level = Level::ERROR;
30    std::string logLevel;
31    switch (hilogLevel) {
32        case LogLevel::LOG_INFO:
33            level = Level::INFO;
34            break;
35        case LogLevel::LOG_WARN:
36            level = Level::WARN;
37            break;
38        case LogLevel::LOG_ERROR:
39            level = Level::ERROR;
40            break;
41        case LogLevel::LOG_FATAL:
42        case LogLevel::LOG_LEVEL_MAX:
43            level = Level::FATAL;
44            break;
45        case LogLevel::LOG_DEBUG:
46        default:
47            level = Level::DEBUG;
48            break;
49    }
50
51    return level;
52}
53
54LogLevel GetHiLogLevel()
55{
56    for (int32_t level = LogLevel::LOG_LEVEL_MIN; level <= LogLevel::LOG_LEVEL_MAX; level++) {
57        if (HiLogIsLoggable(LOG_DOMAIN, LOG_TAG, static_cast<LogLevel>(level))) {
58            return static_cast<LogLevel>(level);
59        }
60    }
61    return LogLevel::LOG_LEVEL_MAX;
62}
63}  // namespace
64#endif
65
66Level Log::level_ = Level::ERROR;
67ComponentMark Log::components_ = Component::ALL;
68
69Level Log::ConvertFromRuntime(LOG_LEVEL level)
70{
71    Level logLevel = Level::INFO;
72    switch (level) {
73        case LOG_LEVEL::FOLLOW:
74#ifdef ENABLE_HILOG
75            logLevel = ConvertToLevel(GetHiLogLevel());
76            break;
77#endif
78        case LOG_LEVEL::INFO:
79            logLevel = Level::INFO;
80            break;
81        case LOG_LEVEL::WARN:
82            logLevel = Level::WARN;
83            break;
84        case LOG_LEVEL::ERROR:
85            logLevel = Level::ERROR;
86            break;
87        case LOG_LEVEL::FATAL:
88            logLevel = Level::FATAL;
89            break;
90        case LOG_LEVEL::DEBUG:
91        default:
92            logLevel = Level::DEBUG;
93            break;
94    }
95
96    return logLevel;
97}
98
99std::string Log::LevelToString(Level level)
100{
101    std::string logLevel;
102    switch (level) {
103        case Level::INFO:
104            logLevel = "info";
105            break;
106        case Level::WARN:
107            logLevel = "warning";
108            break;
109        case Level::ERROR:
110            logLevel = "error";
111            break;
112        case Level::FATAL:
113            logLevel = "fatal";
114            break;
115        case Level::DEBUG:
116        default:
117            logLevel = "debug";
118            break;
119    }
120
121    return logLevel;
122}
123
124void Log::SetLogLevelFromString(const std::string& level)
125{
126    if (level == "fatal") {
127        level_ = FATAL;
128    }
129    if (level == "error") {
130        level_ = ERROR;
131    }
132    if (level == "warning") {
133        level_ = WARN;
134    }
135    if (level == "info") {
136        level_ = INFO;
137    }
138    if (level == "debug") {
139        level_ = DEBUG;
140    }
141    if (level == "verbose") {
142        level_ = VERBOSE;
143    }
144}
145
146void Log::SetLogComponentFromString(const std::vector<std::string>& components)
147{
148    components_ = Component::NONE;
149    for (const auto &component : components) {
150        if (component == "all") {
151            components_ = Component::ALL;
152            return;
153        }
154        if (component == "gc") {
155            components_ |= Component::GC;
156            continue;
157        }
158        if (component == "ecmascript") {
159            components_ |= Component::ECMASCRIPT;
160            continue;
161        }
162        if (component == "interpreter") {
163            components_ |= Component::INTERPRETER;
164            continue;
165        }
166        if (component == "debugger") {
167            components_ |= Component::DEBUGGER;
168            continue;
169        }
170        if (component == "compiler") {
171            components_ |= Component::COMPILER;
172            continue;
173        }
174        if (component == "builtins") {
175            components_ |= Component::BUILTINS;
176            continue;
177        }
178        if (component == "jit") {
179            components_ |= Component::JIT;
180            continue;
181        }
182        if (component == "baselinejit") {
183            components_ |= Component::BASELINEJIT;
184            continue;
185        }
186        if (component == "trace") {
187            components_ |= Component::TRACE;
188            continue;
189        }
190        if (component == "sa") {
191            components_ |= Component::SA;
192            continue;
193        }
194    }
195}
196
197int32_t Log::PrintLogger(int32_t, int32_t level, const char *, const char *, const char *message)
198{
199    switch (level) {
200        case Logger::PandaLog2MobileLog::VERBOSE:
201            LOG_ECMA(VERBOSE) << message;
202            break;
203        case Logger::PandaLog2MobileLog::DEBUG:
204            LOG_ECMA(DEBUG) << message;
205            break;
206        case Logger::PandaLog2MobileLog::INFO:
207            LOG_ECMA(INFO) << message;
208            break;
209        case Logger::PandaLog2MobileLog::WARN:
210            LOG_ECMA(WARN) << message;
211            break;
212        case Logger::PandaLog2MobileLog::ERROR:
213            LOG_ECMA(ERROR) << message;
214            break;
215        case Logger::PandaLog2MobileLog::FATAL:
216            LOG_ECMA(FATAL) << message;
217            break;
218        default:
219            LOG_ECMA(DEBUG) << message;
220            break;
221    }
222    return 0;
223}
224
225void Log::Initialize(const JSRuntimeOptions &options)
226{
227    // For ArkTS runtime log
228    if (options.WasSetLogFatal()) {
229        level_ = FATAL;
230        SetLogComponentFromString(options.GetLogFatal());
231    } else if (options.WasSetLogError()) {
232        level_ = ERROR;
233        SetLogComponentFromString(options.GetLogError());
234    } else if (options.WasSetLogWarning()) {
235        level_ = WARN;
236        SetLogComponentFromString(options.GetLogWarning());
237    } else if (options.WasSetLogInfo()) {
238        level_ = INFO;
239        SetLogComponentFromString(options.GetLogInfo());
240    } else if (options.WasSetLogDebug()) {
241        level_ = DEBUG;
242        SetLogComponentFromString(options.GetLogDebug());
243    } else {
244        SetLogLevelFromString(options.GetLogLevel());
245        SetLogComponentFromString(options.GetLogComponents());
246    }
247
248    // For runtime core log
249    base_options::Options baseOptions("");
250    baseOptions.SetLogLevel(options.GetLogLevel());
251    baseOptions.SetLogComponents({ "all" });
252    Logger::Initialize(baseOptions);
253    Logger::SetMobileLogPrintEntryPointByPtr(reinterpret_cast<void *>(Log::PrintLogger));
254}
255
256#ifdef ENABLE_ANLOG
257const char *tag = "ArkCompiler";
258template<>
259PUBLIC_API AndroidLog<VERBOSE>::~AndroidLog()
260{
261    __android_log_write(ANDROID_LOG_VERBOSE, tag, stream_.str().c_str());
262}
263
264template<>
265PUBLIC_API AndroidLog<DEBUG>::~AndroidLog()
266{
267    __android_log_write(ANDROID_LOG_DEBUG, tag, stream_.str().c_str());
268}
269
270template<>
271PUBLIC_API AndroidLog<INFO>::~AndroidLog()
272{
273    __android_log_write(ANDROID_LOG_INFO, tag, stream_.str().c_str());
274}
275
276template<>
277PUBLIC_API AndroidLog<WARN>::~AndroidLog()
278{
279    __android_log_write(ANDROID_LOG_WARN, tag, stream_.str().c_str());
280}
281
282template<>
283PUBLIC_API AndroidLog<ERROR>::~AndroidLog()
284{
285    __android_log_write(ANDROID_LOG_ERROR, tag, stream_.str().c_str());
286}
287
288template<>
289PUBLIC_API AndroidLog<FATAL>::~AndroidLog()
290{
291    __android_log_write(ANDROID_LOG_FATAL, tag, stream_.str().c_str());
292    std::abort();
293}
294#endif
295}  // namespace panda::ecmascript