1 /*
2 * Copyright (c) 2021 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 "properties.h"
17 #include "hilog_common.h"
18 #include "hilog/log.h"
19 #include "hilog/log_c.h"
20 #include "hilog_napi_base.h"
21 #include "napi/native_api.h"
22 #include "napi/native_node_api.h"
23 #include "n_func_arg.h"
24 #include "n_class.h"
25 #include "securec.h"
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 namespace OHOS {
31 namespace HiviewDFX {
32 using namespace std;
33 const HiLogLabel LABEL = { LOG_CORE, 0xD002D00, "Hilog_JS" };
34 static constexpr int MIN_NUMBER = 3;
35 static constexpr int MAX_NUMBER = 100;
36 static constexpr int PUBLIC_LEN = 6;
37 static constexpr int PRIVATE_LEN = 7;
38 static constexpr int PROPERTY_POS = 2;
39 static const string PRIV_STR = "<private>";
40
ParseLogContent(string & formatStr,vector<napiParam> & params,string & logContent)41 void ParseLogContent(string& formatStr, vector<napiParam>& params, string& logContent)
42 {
43 string& ret = logContent;
44 if (params.empty()) {
45 ret += formatStr;
46 return;
47 }
48 auto size = params.size();
49 auto len = formatStr.size();
50 uint32_t pos = 0;
51 uint32_t count = 0;
52 bool debug = true;
53 #if not (defined(__WINDOWS__) || defined(__MAC__) || defined(__LINUX__))
54 debug = IsDebugOn();
55 #endif
56 bool priv = (!debug) && IsPrivateSwitchOn();
57 for (; pos < len; ++pos) {
58 bool showPriv = true;
59 if (count >= size) {
60 break;
61 }
62 if (formatStr[pos] != '%') {
63 ret += formatStr[pos];
64 continue;
65 }
66
67 if (((pos + PUBLIC_LEN + PROPERTY_POS) < len) &&
68 formatStr.substr(pos + PROPERTY_POS, PUBLIC_LEN) == "public") {
69 pos += (PUBLIC_LEN + PROPERTY_POS);
70 showPriv = false;
71 } else if (((pos + PRIVATE_LEN + PROPERTY_POS) < len) &&
72 formatStr.substr(pos + PROPERTY_POS, PRIVATE_LEN) == "private") {
73 pos += (PRIVATE_LEN + PROPERTY_POS);
74 }
75
76 if (pos + 1 >= len) {
77 break;
78 }
79 switch (formatStr[pos + 1]) {
80 case 'd':
81 case 'i':
82 if (params[count].type == napi_number || params[count].type == napi_bigint) {
83 ret += (priv && showPriv) ? PRIV_STR : params[count].val;
84 }
85 count++;
86 ++pos;
87 break;
88 case 's':
89 if (params[count].type == napi_string || params[count].type == napi_undefined ||
90 params[count].type == napi_boolean || params[count].type == napi_null) {
91 ret += (priv && showPriv) ? PRIV_STR : params[count].val;
92 }
93 count++;
94 ++pos;
95 break;
96 case 'O':
97 case 'o':
98 if (params[count].type == napi_object) {
99 ret += (priv && showPriv) ? PRIV_STR : params[count].val;
100 }
101 count++;
102 ++pos;
103 break;
104 case '%':
105 ret += formatStr[pos];
106 ++pos;
107 break;
108 default:
109 ret += formatStr[pos];
110 break;
111 }
112 }
113 if (pos < len) {
114 ret += formatStr.substr(pos, len - pos);
115 }
116 return;
117 }
118
IsLoggable(napi_env env,napi_callback_info info)119 napi_value HilogNapiBase::IsLoggable(napi_env env, napi_callback_info info)
120 {
121 NFuncArg funcArg(env, info);
122
123 if (!funcArg.InitArgs(NARG_CNT::THREE)) {
124 return nullptr;
125 }
126 bool succ = false;
127 int32_t domain;
128 tie(succ, domain) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
129 if (!succ) {
130 return nullptr;
131 }
132 if ((domain < static_cast<int32_t>(DOMAIN_APP_MIN)) || (domain > static_cast<int32_t>(DOMAIN_APP_MAX))) {
133 return NVal::CreateBool(env, false).val_;
134 }
135 int32_t level;
136 tie(succ, level) = NVal(env, funcArg[NARG_POS::THIRD]).ToInt32();
137 if (!succ) {
138 return nullptr;
139 }
140 unique_ptr<char[]> tag;
141 tie(succ, tag, ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String();
142 if (!succ) {
143 return nullptr;
144 }
145 bool res = HiLogIsLoggable(domain, tag.get(), static_cast<LogLevel>(level));
146 return NVal::CreateBool(env, res).val_;
147 }
148
SetMinLogLevel(napi_env env,napi_callback_info info)149 napi_value HilogNapiBase::SetMinLogLevel(napi_env env, napi_callback_info info)
150 {
151 NFuncArg funcArg(env, info);
152 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
153 return nullptr;
154 }
155 bool succ = false;
156 int32_t level = LOG_LEVEL_MIN;
157 tie(succ, level) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
158 if (!succ) {
159 return nullptr;
160 }
161 HiLogSetAppMinLogLevel(static_cast<LogLevel>(level));
162 return nullptr;
163 }
164
Debug(napi_env env,napi_callback_info info)165 napi_value HilogNapiBase::Debug(napi_env env, napi_callback_info info)
166 {
167 return HilogImpl(env, info, LOG_DEBUG, true);
168 }
169
Info(napi_env env,napi_callback_info info)170 napi_value HilogNapiBase::Info(napi_env env, napi_callback_info info)
171 {
172 return HilogImpl(env, info, LOG_INFO, true);
173 }
174
Warn(napi_env env,napi_callback_info info)175 napi_value HilogNapiBase::Warn(napi_env env, napi_callback_info info)
176 {
177 return HilogImpl(env, info, LOG_WARN, true);
178 }
179
Error(napi_env env,napi_callback_info info)180 napi_value HilogNapiBase::Error(napi_env env, napi_callback_info info)
181 {
182 return HilogImpl(env, info, LOG_ERROR, true);
183 }
184
Fatal(napi_env env,napi_callback_info info)185 napi_value HilogNapiBase::Fatal(napi_env env, napi_callback_info info)
186 {
187 return HilogImpl(env, info, LOG_FATAL, true);
188 }
189
SysLogDebug(napi_env env,napi_callback_info info)190 napi_value HilogNapiBase::SysLogDebug(napi_env env, napi_callback_info info)
191 {
192 return HilogImpl(env, info, LOG_DEBUG, false);
193 }
194
SysLogInfo(napi_env env,napi_callback_info info)195 napi_value HilogNapiBase::SysLogInfo(napi_env env, napi_callback_info info)
196 {
197 return HilogImpl(env, info, LOG_INFO, false);
198 }
199
SysLogWarn(napi_env env,napi_callback_info info)200 napi_value HilogNapiBase::SysLogWarn(napi_env env, napi_callback_info info)
201 {
202 return HilogImpl(env, info, LOG_WARN, false);
203 }
204
SysLogError(napi_env env,napi_callback_info info)205 napi_value HilogNapiBase::SysLogError(napi_env env, napi_callback_info info)
206 {
207 return HilogImpl(env, info, LOG_ERROR, false);
208 }
209
SysLogFatal(napi_env env,napi_callback_info info)210 napi_value HilogNapiBase::SysLogFatal(napi_env env, napi_callback_info info)
211 {
212 return HilogImpl(env, info, LOG_FATAL, false);
213 }
214
parseNapiValue(napi_env env,napi_callback_info info,napi_value element,vector<napiParam> & params)215 napi_value HilogNapiBase::parseNapiValue(napi_env env, napi_callback_info info,
216 napi_value element, vector<napiParam>& params)
217 {
218 bool succ = false;
219 napi_valuetype type;
220 napiParam res = {napi_null, ""};
221 napi_status typeStatus = napi_typeof(env, element, &type);
222 unique_ptr<char[]> name;
223 if (typeStatus != napi_ok) {
224 return nullptr;
225 }
226 if (type == napi_number || type == napi_bigint || type == napi_object ||
227 type == napi_undefined || type == napi_boolean || type == napi_null) {
228 napi_value elmString;
229 napi_status objectStatus = napi_coerce_to_string(env, element, &elmString);
230 if (objectStatus != napi_ok) {
231 return nullptr;
232 }
233 tie(succ, name, ignore) = NVal(env, elmString).ToUTF8String();
234 if (!succ) {
235 return nullptr;
236 }
237 } else if (type == napi_string) {
238 tie(succ, name, ignore) = NVal(env, element).ToUTF8String();
239 if (!succ) {
240 return nullptr;
241 }
242 } else {
243 HiLog::Info(LABEL, "%{public}s", "type mismatch");
244 }
245 res.type = type;
246 if (name != nullptr) {
247 res.val = name.get();
248 }
249 params.emplace_back(res);
250 return nullptr;
251 }
252
HilogImpl(napi_env env,napi_callback_info info,int level,bool isAppLog)253 napi_value HilogNapiBase::HilogImpl(napi_env env, napi_callback_info info, int level, bool isAppLog)
254 {
255 NFuncArg funcArg(env, info);
256 funcArg.InitArgs(MIN_NUMBER, MAX_NUMBER);
257 bool succ = false;
258 int32_t domain;
259 tie(succ, domain) = NVal(env, funcArg[NARG_POS::FIRST]).ToInt32();
260 if (!succ) {
261 HiLog::Info(LABEL, "%{public}s", "domain mismatch");
262 return nullptr;
263 }
264 unique_ptr<char[]> tag;
265 tie(succ, tag, ignore) = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String();
266 if (!succ) {
267 HiLog::Info(LABEL, "%{public}s", "tag mismatch");
268 return nullptr;
269 }
270 unique_ptr<char[]> fmt;
271 tie(succ, fmt, ignore) = NVal(env, funcArg[NARG_POS::THIRD]).ToUTF8String();
272 if (!succ) {
273 HiLog::Info(LABEL, "%{public}s", "Format mismatch");
274 return nullptr;
275 }
276 string fmtString = fmt.get();
277 bool res = false;
278 napi_value array = funcArg[NARG_POS::FOURTH];
279 napi_is_array(env, array, &res);
280 string logContent;
281 vector<napiParam> params;
282 if (!res) {
283 for (size_t i = MIN_NUMBER; i < funcArg.GetArgc(); i++) {
284 napi_value argsVal = funcArg[i];
285 (void)parseNapiValue(env, info, argsVal, params);
286 }
287 } else {
288 if (funcArg.GetArgc() != MIN_NUMBER + 1) {
289 NAPI_ASSERT(env, false, "Argc mismatch");
290 HiLog::Info(LABEL, "%{public}s", "Argc mismatch");
291 return nullptr;
292 }
293 uint32_t length;
294 napi_status lengthStatus = napi_get_array_length(env, array, &length);
295 if (lengthStatus != napi_ok) {
296 return nullptr;
297 }
298 uint32_t i;
299 for (i = 0; i < length; i++) {
300 napi_value element;
301 napi_status eleStatus = napi_get_element(env, array, i, &element);
302 if (eleStatus != napi_ok) {
303 return nullptr;
304 }
305 (void)parseNapiValue(env, info, element, params);
306 }
307 }
308 ParseLogContent(fmtString, params, logContent);
309 HiLogPrint((isAppLog ? LOG_APP : LOG_CORE),
310 static_cast<LogLevel>(level), domain, tag.get(), "%{public}s", logContent.c_str());
311 return nullptr;
312 }
313 } // namespace HiviewDFX
314 } // namespace OHOS
315
316 #ifdef __cplusplus
317 }
318 #endif
319