• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2024 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 "bytrace_napi_common.h"
22 
23 using namespace OHOS::HiviewDFX;
24 namespace {
25 constexpr int FIRST_ARGC_INDEX = 0;
26 constexpr int SECOND_ARGC_INDEX = 1;
27 constexpr int THIRD_ARGC_INDEX = 2;
28 constexpr int ARGC_NUMBER_TWICE = 2;
29 constexpr int ARGC_NUMBER_TRIPLE = 3;
30 constexpr uint64_t HITRACE_METER_LABEL = 0xD002D33;
31 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HITRACE_METER_LABEL, "HITRACE_METER_JS"};
32 using STR_NUM_PARAM_FUNC = std::function<bool(std::string, napi_value&)>;
33 
ParseParams(napi_env & env,napi_callback_info & info,size_t & argc,napi_value * argv)34 napi_value ParseParams(napi_env& env, napi_callback_info& info, size_t& argc, napi_value* argv)
35 {
36     napi_value thisVar;
37     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
38     return nullptr;
39 }
40 
TypeCheck(const napi_env & env,const napi_value & value,const napi_valuetype expectType)41 bool TypeCheck(const napi_env& env, const napi_value& value, const napi_valuetype expectType)
42 {
43     napi_valuetype valueType;
44     napi_status status = napi_typeof(env, value, &valueType);
45     if (status != napi_ok) {
46         HiLog::Error(LABEL, "Failed to get the type of the argument");
47         return false;
48     }
49     if (valueType != expectType) {
50         HiLog::Error(LABEL, "Type of the parameter is invalid");
51         return false;
52     }
53     return true;
54 }
55 
GetStringParam(const napi_env & env,const napi_value & value,std::string & dest)56 void GetStringParam(const napi_env& env, const napi_value& value, std::string& dest)
57 {
58     // parsing the value of string type into dest
59     constexpr int maxNameSize = 1024;
60     char buf[maxNameSize] = {0};
61     size_t len = 0;
62     napi_get_value_string_utf8(env, value, buf, maxNameSize, &len);
63     dest = std::string {buf};
64 }
65 
ParseStringParam(const napi_env & env,const napi_value & value,std::string & dest)66 bool ParseStringParam(const napi_env& env, const napi_value& value, std::string& dest)
67 {
68     // if it is not a string, convert the corresponding type to a string
69     if (TypeCheck(env, value, napi_string)) {
70         GetStringParam(env, value, dest);
71         return true;
72     }
73     if (TypeCheck(env, value, napi_number)) {
74         int64_t destI64;
75         napi_get_value_int64(env, value, &destI64);
76         dest = std::to_string(destI64);
77         return true;
78     }
79     // if it's napi_null, then handle it as 'null'
80     if (TypeCheck(env, value, napi_null)) {
81         dest = "null";
82         return true;
83     }
84     if (TypeCheck(env, value, napi_undefined)) {
85         dest = "undefined";
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 
ParseDoubleParam(const napi_env & env,const napi_value & value,double & dest)109 bool ParseDoubleParam(const napi_env& env, const napi_value& value, double& dest)
110 {
111     if (!TypeCheck(env, value, napi_number)) {
112         return false;
113     }
114     napi_get_value_double(env, value, &dest);
115     return true;
116 }
117 
ParseUndefinedParam(const napi_env & env,const napi_value & value)118 bool ParseUndefinedParam(const napi_env& env, const napi_value& value)
119 {
120     return TypeCheck(env, value, napi_undefined);
121 }
122 
ParseNullParam(const napi_env & env,const napi_value & value)123 bool ParseNullParam(const napi_env& env, const napi_value& value)
124 {
125     return TypeCheck(env, value, napi_null);
126 }
127 
JsStrNumParamsFunc(napi_env & env,napi_callback_info & info,STR_NUM_PARAM_FUNC nativeCall)128 bool JsStrNumParamsFunc(napi_env& env, napi_callback_info& info, STR_NUM_PARAM_FUNC nativeCall)
129 {
130     size_t argc = ARGC_NUMBER_TWICE;
131     napi_value argv[ARGC_NUMBER_TWICE];
132     ParseParams(env, info, argc, argv);
133     if (argc != ARGC_NUMBER_TWICE) {
134         HiLog::Error(LABEL, "Wrong number of parameters.");
135         return false;
136     }
137     std::string name;
138     if (!ParseStringParam(env, argv[FIRST_ARGC_INDEX], name)) {
139         return false;
140     }
141     if (!nativeCall(name, argv[SECOND_ARGC_INDEX])) {
142         return false;
143     }
144     return true;
145 }
146 }
147 
JSTraceStart(napi_env env,napi_callback_info info)148 static napi_value JSTraceStart(napi_env env, napi_callback_info info)
149 {
150     size_t argc = ARGC_NUMBER_TRIPLE;
151     napi_value argv[ARGC_NUMBER_TRIPLE];
152     ParseParams(env, info, argc, argv);
153     NAPI_ASSERT(env, argc >= ARGC_NUMBER_TWICE, "Wrong number of arguments");
154     if (argc < ARGC_NUMBER_TWICE) {
155         HiLog::Error(LABEL, "Wrong number of parameters.");
156     }
157     std::string name;
158     if (!ParseStringParam(env, argv[FIRST_ARGC_INDEX], name)) {
159         return nullptr;
160     }
161     int taskId = 0;
162     if (!ParseInt32Param(env, argv[SECOND_ARGC_INDEX], taskId)) {
163         return nullptr;
164     }
165     if (argc == ARGC_NUMBER_TWICE) {
166         StartAsyncTrace(HITRACE_TAG_APP, name, taskId);
167     } else {
168         double limit = 0.0;
169         if (!ParseDoubleParam(env, argv[THIRD_ARGC_INDEX], limit) &&
170                 !ParseUndefinedParam(env, argv[THIRD_ARGC_INDEX]) && !ParseNullParam(env, argv[THIRD_ARGC_INDEX])) {
171             HiLog::Error(LABEL, "the third param is not number, not undefined, not null.");
172             return nullptr;
173         }
174         StartAsyncTrace(HITRACE_TAG_APP, name, taskId, limit);
175     }
176     return nullptr;
177 }
178 
JSTraceFinish(napi_env env,napi_callback_info info)179 static napi_value JSTraceFinish(napi_env env, napi_callback_info info)
180 {
181     size_t argc = ARGC_NUMBER_TWICE;
182     napi_value argv[ARGC_NUMBER_TWICE];
183     napi_value thisVar;
184     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
185     NAPI_ASSERT(env, argc >= ARGC_NUMBER_TWICE, "Wrong number of arguments");
186     (void)JsStrNumParamsFunc(env, info, [&env] (std::string name, const napi_value& nValue) -> bool {
187         int taskId = 0;
188         if (!ParseInt32Param(env, nValue, taskId)) {
189             return false;
190         }
191         FinishAsyncTrace(HITRACE_TAG_APP, name, taskId);
192         return true;
193     });
194     return nullptr;
195 }
196 
JSTraceCount(napi_env env,napi_callback_info info)197 static napi_value JSTraceCount(napi_env env, napi_callback_info info)
198 {
199     size_t argc = ARGC_NUMBER_TWICE;
200     napi_value argv[ARGC_NUMBER_TWICE];
201     napi_value thisVar;
202     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
203     NAPI_ASSERT(env, argc == ARGC_NUMBER_TWICE, "Wrong number of arguments");
204     (void)JsStrNumParamsFunc(env, info, [&env] (std::string name, const napi_value& nValue) -> bool {
205         int64_t count = 0;
206         if (!ParseInt64Param(env, nValue, count)) {
207             return false;
208         }
209         CountTrace(HITRACE_TAG_APP, name, count);
210         return true;
211     });
212     return nullptr;
213 }
214 
215 /*
216  * function for module exports
217  */
218 EXTERN_C_START
BytraceInit(napi_env env,napi_value exports)219 static napi_value BytraceInit(napi_env env, napi_value exports)
220 {
221     static napi_property_descriptor desc[] = {
222         DECLARE_NAPI_FUNCTION("startTrace", JSTraceStart),
223         DECLARE_NAPI_FUNCTION("finishTrace", JSTraceFinish),
224         DECLARE_NAPI_FUNCTION("traceByValue", JSTraceCount),
225     };
226     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
227     return exports;
228 }
229 EXTERN_C_END
230 
231 /*
232  * bytrace module definition
233  */
234 static napi_module bytrace_module = {
235     .nm_version = 1,
236     .nm_flags = 0,
237     .nm_filename = "bytrace",
238     .nm_register_func = BytraceInit,
239     .nm_modname = "bytrace",
240     .nm_priv = ((void *)0),
241     .reserved = {0}
242 };
243 
244 /*
245  * Module registration
246  */
RegisterModule(void)247 extern "C" __attribute__((constructor)) void RegisterModule(void)
248 {
249     napi_module_register(&bytrace_module);
250 }
251