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 <string>
19 #include <hilog/log.h>
20 #include "hitrace_meter.h"
21 #include "napi_hitrace_meter.h"
22
23 using namespace OHOS::HiviewDFX;
24 namespace {
25 constexpr int FIRST_ARG_INDEX = 0;
26 constexpr int SECOND_ARG_INDEX = 1;
27 constexpr int ARGC_NUMBER_TWO = 2;
28 constexpr int ARGC_NUMBER_THREE = 3;
29 #undef LOG_DOMAIN
30 #define LOG_DOMAIN 0xD002D33
31
32 #undef LOG_TAG
33 #define LOG_TAG "HITRACE_METER_JS"
34
35 using STR_NUM_PARAM_FUNC = std::function<bool(std::string, napi_value&)>;
36
ParseParams(napi_env & env,napi_callback_info & info,size_t & argc,napi_value * argv)37 napi_value ParseParams(napi_env& env, napi_callback_info& info, size_t& argc, napi_value* argv)
38 {
39 napi_value thisVar;
40 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
41 return nullptr;
42 }
43
TypeCheck(const napi_env & env,const napi_value & value,const napi_valuetype expectType)44 bool TypeCheck(const napi_env& env, const napi_value& value, const napi_valuetype expectType)
45 {
46 napi_valuetype valueType;
47 napi_status status = napi_typeof(env, value, &valueType);
48 if (status != napi_ok) {
49 HILOG_ERROR(LOG_CORE, "Failed to get the type of the argument.");
50 return false;
51 }
52 if (valueType != expectType) {
53 HILOG_ERROR(LOG_CORE, "Type of the parameter is invalid.");
54 return false;
55 }
56 return true;
57 }
58
GetStringParam(const napi_env & env,const napi_value & value,std::string & dest)59 void GetStringParam(const napi_env& env, const napi_value& value, std::string& dest)
60 {
61 constexpr int nameMaxSize = 1024;
62 char buf[nameMaxSize] = {0};
63 size_t len = 0;
64 napi_get_value_string_utf8(env, value, buf, nameMaxSize, &len);
65 dest = std::string {buf};
66 }
67
ParseStringParam(const napi_env & env,const napi_value & value,std::string & dest)68 bool ParseStringParam(const napi_env& env, const napi_value& value, std::string& dest)
69 {
70 if (TypeCheck(env, value, napi_string)) {
71 GetStringParam(env, value, dest);
72 return true;
73 }
74 if (TypeCheck(env, value, napi_number)) {
75 int64_t destI64;
76 napi_get_value_int64(env, value, &destI64);
77 dest = std::to_string(destI64);
78 return true;
79 }
80 if (TypeCheck(env, value, napi_undefined)) {
81 dest = "undefined";
82 return true;
83 }
84 if (TypeCheck(env, value, napi_null)) {
85 dest = "null";
86 return true;
87 }
88 return false;
89 }
90
ParseInt32Param(const napi_env & env,const napi_value & value,int & dest)91 bool ParseInt32Param(const napi_env& env, const napi_value& value, int& dest)
92 {
93 if (!TypeCheck(env, value, napi_number)) {
94 return false;
95 }
96 napi_get_value_int32(env, value, &dest);
97 return true;
98 }
99
ParseInt64Param(const napi_env & env,const napi_value & value,int64_t & dest)100 bool ParseInt64Param(const napi_env& env, const napi_value& value, int64_t& dest)
101 {
102 if (!TypeCheck(env, value, napi_number)) {
103 return false;
104 }
105 napi_get_value_int64(env, value, &dest);
106 return true;
107 }
108
JsStrNumParamsFunc(napi_env & env,napi_callback_info & info,STR_NUM_PARAM_FUNC nativeCall)109 bool JsStrNumParamsFunc(napi_env& env, napi_callback_info& info, STR_NUM_PARAM_FUNC nativeCall)
110 {
111 size_t argc = ARGC_NUMBER_TWO;
112 napi_value argv[ARGC_NUMBER_TWO];
113 ParseParams(env, info, argc, argv);
114 if (argc != ARGC_NUMBER_TWO) {
115 HILOG_ERROR(LOG_CORE, "Wrong number of parameters.");
116 return false;
117 }
118 std::string name;
119 if (!ParseStringParam(env, argv[FIRST_ARG_INDEX], name)) {
120 return false;
121 }
122 if (!nativeCall(name, argv[SECOND_ARG_INDEX])) {
123 return false;
124 }
125 return true;
126 }
127 }
128
JSTraceStart(napi_env env,napi_callback_info info)129 static napi_value JSTraceStart(napi_env env, napi_callback_info info)
130 {
131 size_t argc = ARGC_NUMBER_THREE;
132 napi_value argv[ARGC_NUMBER_THREE];
133 ParseParams(env, info, argc, argv);
134 NAPI_ASSERT(env, argc >= ARGC_NUMBER_TWO, "Wrong number of arguments");
135 if (argc < ARGC_NUMBER_TWO) {
136 HILOG_ERROR(LOG_CORE, "Wrong number of parameters.");
137 }
138 std::string name;
139 if (!ParseStringParam(env, argv[FIRST_ARG_INDEX], name)) {
140 return nullptr;
141 }
142 int taskId = 0;
143 if (!ParseInt32Param(env, argv[SECOND_ARG_INDEX], taskId)) {
144 return nullptr;
145 }
146 StartAsyncTrace(HITRACE_TAG_APP, name, taskId);
147 return nullptr;
148 }
149
JSTraceFinish(napi_env env,napi_callback_info info)150 static napi_value JSTraceFinish(napi_env env, napi_callback_info info)
151 {
152 size_t argc = ARGC_NUMBER_TWO;
153 napi_value argv[ARGC_NUMBER_TWO];
154 napi_value thisVar;
155 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
156 NAPI_ASSERT(env, argc == ARGC_NUMBER_TWO, "Wrong number of arguments");
157 (void)JsStrNumParamsFunc(env, info, [&env] (std::string name, napi_value& nValue) -> bool {
158 int taskId = 0;
159 if (!ParseInt32Param(env, nValue, taskId)) {
160 return false;
161 }
162 FinishAsyncTrace(HITRACE_TAG_APP, name, taskId);
163 return true;
164 });
165 return nullptr;
166 }
167
JSTraceCount(napi_env env,napi_callback_info info)168 static napi_value JSTraceCount(napi_env env, napi_callback_info info)
169 {
170 size_t argc = ARGC_NUMBER_TWO;
171 napi_value argv[ARGC_NUMBER_TWO];
172 napi_value thisVar;
173 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
174 NAPI_ASSERT(env, argc == ARGC_NUMBER_TWO, "Wrong number of arguments");
175 (void)JsStrNumParamsFunc(env, info, [&env] (std::string name, napi_value& nValue) -> bool {
176 int64_t count = 0;
177 if (!ParseInt64Param(env, nValue, count)) {
178 return false;
179 }
180 CountTrace(HITRACE_TAG_APP, name, count);
181 return true;
182 });
183 return nullptr;
184 }
185
186 /*
187 * function for module exports
188 */
189 EXTERN_C_START
HiTraceMeterInit(napi_env env,napi_value exports)190 static napi_value HiTraceMeterInit(napi_env env, napi_value exports)
191 {
192 napi_property_descriptor desc[] = {
193 DECLARE_NAPI_FUNCTION("startTrace", JSTraceStart),
194 DECLARE_NAPI_FUNCTION("finishTrace", JSTraceFinish),
195 DECLARE_NAPI_FUNCTION("traceByValue", JSTraceCount),
196 };
197 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
198 return exports;
199 }
200 EXTERN_C_END
201
202 /*
203 * hiTraceMeter module definition
204 */
205 static napi_module hitracemeter_module = {
206 .nm_version = 1,
207 .nm_flags = 0,
208 .nm_filename = nullptr,
209 .nm_register_func = HiTraceMeterInit,
210 .nm_modname = "hiTraceMeter",
211 .nm_priv = ((void *)0),
212 .reserved = {0}
213 };
214
215 /*
216 * Module registration
217 */
RegisterModule(void)218 extern "C" __attribute__((constructor)) void RegisterModule(void)
219 {
220 napi_module_register(&hitracemeter_module);
221 }
222