• 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 <cstdio>
17 #include <functional>
18 #include <hilog/log.h>
19 #include <map>
20 #include <string>
21 
22 #include "hitrace_meter.h"
23 #include "napi_hitrace_meter.h"
24 
25 using namespace OHOS::HiviewDFX;
26 namespace {
27 constexpr int FIRST_ARG_INDEX = 0;
28 constexpr int SECOND_ARG_INDEX = 1;
29 constexpr int ARGC_NUMBER_TWO = 2;
30 constexpr int ARGC_NUMBER_THREE = 3;
31 
32 #ifdef LOG_DOMAIN
33 #undef LOG_DOMAIN
34 #define LOG_DOMAIN 0xD002D33
35 #endif
36 #ifdef LOG_TAG
37 #undef LOG_TAG
38 #define LOG_TAG "HitraceMeterNapi"
39 #endif
40 
41 using STR_NUM_PARAM_FUNC = std::function<bool(std::string, napi_value&)>;
42 std::unordered_map<std::string, uint64_t> g_tagsMap = {
43     {"ohos", HITRACE_TAG_OHOS}, {"ability", HITRACE_TAG_ABILITY_MANAGER}, {"camera", HITRACE_TAG_ZCAMERA},
44     {"media", HITRACE_TAG_ZMEDIA}, {"image", HITRACE_TAG_ZIMAGE}, {"audio", HITRACE_TAG_ZAUDIO},
45     {"distributeddatamgr", HITRACE_TAG_DISTRIBUTEDDATA}, {"graphic", HITRACE_TAG_GRAPHIC_AGP},
46     {"ace", HITRACE_TAG_ACE}, {"notification", HITRACE_TAG_NOTIFICATION}, {"misc", HITRACE_TAG_MISC},
47     {"multimodalinput", HITRACE_TAG_MULTIMODALINPUT}, {"rpc", HITRACE_TAG_RPC}, {"ark", HITRACE_TAG_ARK},
48     {"window", HITRACE_TAG_WINDOW_MANAGER}, {"dscreen", HITRACE_TAG_DISTRIBUTED_SCREEN},
49     {"dcamera", HITRACE_TAG_DISTRIBUTED_CAMERA}, {"dhfwk", HITRACE_TAG_DISTRIBUTED_HARDWARE_FWK},
50     {"gresource", HITRACE_TAG_GLOBAL_RESMGR}, {"devicemanager", HITRACE_TAG_DEVICE_MANAGER},
51     {"samgr", HITRACE_TAG_SAMGR}, {"power", HITRACE_TAG_POWER}, {"dsched", HITRACE_TAG_DISTRIBUTED_SCHEDULE},
52     {"dinput", HITRACE_TAG_DISTRIBUTED_INPUT}, {"bluetooth", HITRACE_TAG_BLUETOOTH}, {"ffrt", HITRACE_TAG_FFRT},
53     {"commonlibrary", HITRACE_TAG_COMMONLIBRARY}, {"hdf", HITRACE_TAG_HDF}, {"net", HITRACE_TAG_NET},
54     {"nweb", HITRACE_TAG_NWEB}, {"daudio", HITRACE_TAG_DISTRIBUTED_AUDIO},
55     {"filemanagement", HITRACE_TAG_FILEMANAGEMENT}, {"app", HITRACE_TAG_APP}
56 };
57 
ParseParams(napi_env & env,napi_callback_info & info,size_t & argc,napi_value * argv)58 napi_value ParseParams(napi_env& env, napi_callback_info& info, size_t& argc, napi_value* argv)
59 {
60     napi_value thisVar;
61     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
62     return nullptr;
63 }
64 
TypeCheck(const napi_env & env,const napi_value & value,const napi_valuetype expectType)65 bool TypeCheck(const napi_env& env, const napi_value& value, const napi_valuetype expectType)
66 {
67     napi_valuetype valueType;
68     napi_status status = napi_typeof(env, value, &valueType);
69     if (status != napi_ok) {
70         HILOG_ERROR(LOG_CORE, "Failed to get the type of the argument.");
71         return false;
72     }
73     if (valueType != expectType) {
74         HILOG_DEBUG(LOG_CORE, "Type of the parameter is invalid.");
75         return false;
76     }
77     return true;
78 }
79 
GetStringParam(const napi_env & env,const napi_value & value,std::string & dest)80 void GetStringParam(const napi_env& env, const napi_value& value, std::string& dest)
81 {
82     constexpr int nameMaxSize = 1024;
83     char buf[nameMaxSize] = {0};
84     size_t len = 0;
85     napi_get_value_string_utf8(env, value, buf, nameMaxSize, &len);
86     dest = std::string {buf};
87 }
88 
ParseStringParam(const napi_env & env,const napi_value & value,std::string & dest)89 bool ParseStringParam(const napi_env& env, const napi_value& value, std::string& dest)
90 {
91     if (TypeCheck(env, value, napi_string)) {
92         GetStringParam(env, value, dest);
93         return true;
94     }
95     if (TypeCheck(env, value, napi_number)) {
96         int64_t destI64;
97         napi_get_value_int64(env, value, &destI64);
98         dest = std::to_string(destI64);
99         return true;
100     }
101     if (TypeCheck(env, value, napi_undefined)) {
102         dest = "undefined";
103         return true;
104     }
105     if (TypeCheck(env, value, napi_null)) {
106         dest = "null";
107         return true;
108     }
109     return false;
110 }
111 
ParseInt32Param(const napi_env & env,const napi_value & value,int & dest)112 bool ParseInt32Param(const napi_env& env, const napi_value& value, int& dest)
113 {
114     if (!TypeCheck(env, value, napi_number)) {
115         return false;
116     }
117     napi_get_value_int32(env, value, &dest);
118     return true;
119 }
120 
ParseInt64Param(const napi_env & env,const napi_value & value,int64_t & dest)121 bool ParseInt64Param(const napi_env& env, const napi_value& value, int64_t& dest)
122 {
123     if (!TypeCheck(env, value, napi_number)) {
124         return false;
125     }
126     napi_get_value_int64(env, value, &dest);
127     return true;
128 }
129 
SetTagsParam(const napi_env & env,const napi_value & value,uint64_t & tags)130 void SetTagsParam(const napi_env& env, const napi_value& value, uint64_t& tags)
131 {
132     uint32_t arrayLength;
133     napi_status status = napi_get_array_length(env, value, &arrayLength);
134     if (status != napi_ok) {
135         HILOG_ERROR(LOG_CORE, "Failed to get the length of the array.");
136         return;
137     }
138 
139     for (uint32_t i = 0; i < arrayLength; i++) {
140         napi_value tag;
141         status = napi_get_element(env, value, i, &tag);
142         if (status != napi_ok) {
143             HILOG_ERROR(LOG_CORE, "Failed to get element.");
144             return;
145         }
146 
147         if (!TypeCheck(env, tag, napi_string)) {
148             HILOG_ERROR(LOG_CORE, "tag is invalid, not a napi_string");
149             return;
150         }
151 
152         std::string tagStr = "";
153         GetStringParam(env, tag, tagStr);
154         if (g_tagsMap.count(tagStr) > 0) {
155             tags |= g_tagsMap[tagStr];
156         }
157     }
158 }
159 
ParseTagsParam(const napi_env & env,const napi_value & value,uint64_t & tags)160 bool ParseTagsParam(const napi_env& env, const napi_value& value, uint64_t& tags)
161 {
162     bool isArray = false;
163     napi_status status = napi_is_array(env, value, &isArray);
164     if (status != napi_ok) {
165         HILOG_ERROR(LOG_CORE, "Failed to get array type.");
166         return false;
167     }
168 
169     if (isArray) {
170         SetTagsParam(env, value, tags);
171         return true;
172     } else {
173         HILOG_ERROR(LOG_CORE, "The argument isn't an array type.");
174         return false;
175     }
176 }
177 
JsStrNumParamsFunc(napi_env & env,napi_callback_info & info,STR_NUM_PARAM_FUNC nativeCall)178 bool JsStrNumParamsFunc(napi_env& env, napi_callback_info& info, STR_NUM_PARAM_FUNC nativeCall)
179 {
180     size_t argc = static_cast<size_t>(ARGC_NUMBER_TWO);
181     napi_value argv[ARGC_NUMBER_TWO];
182     ParseParams(env, info, argc, argv);
183     if (argc != ARGC_NUMBER_TWO) {
184         HILOG_ERROR(LOG_CORE, "Wrong number of parameters.");
185         return false;
186     }
187     std::string name;
188     if (!ParseStringParam(env, argv[FIRST_ARG_INDEX], name)) {
189         return false;
190     }
191     if (!nativeCall(name, argv[SECOND_ARG_INDEX])) {
192         return false;
193     }
194     return true;
195 }
196 }
197 
JSTraceStart(napi_env env,napi_callback_info info)198 static napi_value JSTraceStart(napi_env env, napi_callback_info info)
199 {
200     size_t argc = ARGC_NUMBER_THREE;
201     napi_value argv[ARGC_NUMBER_THREE];
202     ParseParams(env, info, argc, argv);
203     NAPI_ASSERT(env, argc >= ARGC_NUMBER_TWO, "Wrong number of arguments");
204     std::string name;
205     if (!ParseStringParam(env, argv[FIRST_ARG_INDEX], name)) {
206         return nullptr;
207     }
208     if (name == "null" || name == "undefined") {
209         return nullptr;
210     }
211     int taskId = 0;
212     if (!ParseInt32Param(env, argv[SECOND_ARG_INDEX], taskId)) {
213         return nullptr;
214     }
215     StartAsyncTrace(HITRACE_TAG_APP, name, taskId);
216     return nullptr;
217 }
218 
JSTraceFinish(napi_env env,napi_callback_info info)219 static napi_value JSTraceFinish(napi_env env, napi_callback_info info)
220 {
221     size_t argc = ARGC_NUMBER_TWO;
222     napi_value argv[ARGC_NUMBER_TWO];
223     napi_value thisVar;
224     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
225     NAPI_ASSERT(env, argc == ARGC_NUMBER_TWO, "Wrong number of arguments");
226     (void)JsStrNumParamsFunc(env, info, [&env] (std::string name, napi_value& nValue) -> bool {
227         if (name == "null" || name == "undefined") {
228             return false;
229         }
230         int taskId = 0;
231         if (!ParseInt32Param(env, nValue, taskId)) {
232             return false;
233         }
234         FinishAsyncTrace(HITRACE_TAG_APP, name, taskId);
235         return true;
236     });
237     return nullptr;
238 }
239 
JSTraceCount(napi_env env,napi_callback_info info)240 static napi_value JSTraceCount(napi_env env, napi_callback_info info)
241 {
242     size_t argc = ARGC_NUMBER_TWO;
243     napi_value argv[ARGC_NUMBER_TWO];
244     napi_value thisVar;
245     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
246     NAPI_ASSERT(env, argc == ARGC_NUMBER_TWO, "Wrong number of arguments");
247     (void)JsStrNumParamsFunc(env, info, [&env] (std::string name, napi_value& nValue) -> bool {
248         if (name == "null" || name == "undefined") {
249             return false;
250         }
251         int64_t count = 0;
252         if (!ParseInt64Param(env, nValue, count)) {
253             return false;
254         }
255         CountTrace(HITRACE_TAG_APP, name, count);
256         return true;
257     });
258     return nullptr;
259 }
260 
JSStartCaptureAppTrace(napi_env env,napi_callback_info info)261 static napi_value JSStartCaptureAppTrace(napi_env env, napi_callback_info info)
262 {
263     size_t argc = ARGC_NUMBER_THREE;
264     napi_value argv[ARGC_NUMBER_THREE];
265     ParseParams(env, info, argc, argv);
266     NAPI_ASSERT(env, argc >= ARGC_NUMBER_THREE, "Wrong number of arguments");
267 
268     uint64_t tags = HITRACE_TAG_APP;
269     if (!ParseTagsParam(env, argv[FIRST_ARG_INDEX], tags)) {
270         return nullptr;
271     }
272 
273     int64_t flag = 0;
274     if (!ParseInt64Param(env, argv[SECOND_ARG_INDEX], flag)) {
275         return nullptr;
276     }
277 
278     int64_t limitSize = 0;
279     if (!ParseInt64Param(env, argv[ARGC_NUMBER_TWO], limitSize)) {
280         return nullptr;
281     }
282 
283     std::string file = "";
284     if (StartCaptureAppTrace((TraceFlag)flag, tags, limitSize, file) != RET_SUCC) {
285         HILOG_ERROR(LOG_CORE, "StartCaptureAppTrace failed");
286         return nullptr;
287     }
288 
289     napi_value napiFile;
290     napi_status status = napi_create_string_utf8(env, file.c_str(), file.length(), &napiFile);
291     if (status != napi_ok) {
292         HILOG_ERROR(LOG_CORE, "create napi string failed: %{public}d(%{public}s)", errno, strerror(errno));
293         return nullptr;
294     }
295 
296     return napiFile;
297 }
298 
JSStopCaptureAppTrace(napi_env env,napi_callback_info info)299 static napi_value JSStopCaptureAppTrace(napi_env env, napi_callback_info info)
300 {
301     StopCaptureAppTrace();
302     return nullptr;
303 }
304 
305 /*
306  * function for module exports
307  */
308 EXTERN_C_START
HiTraceMeterInit(napi_env env,napi_value exports)309 static napi_value HiTraceMeterInit(napi_env env, napi_value exports)
310 {
311     napi_property_descriptor desc[] = {
312         DECLARE_NAPI_FUNCTION("startTrace", JSTraceStart),
313         DECLARE_NAPI_FUNCTION("finishTrace", JSTraceFinish),
314         DECLARE_NAPI_FUNCTION("traceByValue", JSTraceCount),
315         DECLARE_NAPI_FUNCTION("startCaptureAppTrace", JSStartCaptureAppTrace),
316         DECLARE_NAPI_FUNCTION("stopCaptureAppTrace", JSStopCaptureAppTrace),
317     };
318     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
319     return exports;
320 }
321 EXTERN_C_END
322 
323 /*
324  * hiTraceMeter module definition
325  */
326 static napi_module hitracemeter_module = {
327     .nm_version = 1,
328     .nm_flags = 0,
329     .nm_filename = nullptr,
330     .nm_register_func = HiTraceMeterInit,
331     .nm_modname = "hiTraceMeter",
332     .nm_priv = ((void *)0),
333     .reserved = {0}
334 };
335 
336 /*
337  * Module registration
338  */
RegisterModule(void)339 extern "C" __attribute__((constructor)) void RegisterModule(void)
340 {
341     napi_module_register(&hitracemeter_module);
342 }
343