1 /*
2 * Copyright (c) 2021-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 "napi_hitrace_init.h"
17
18 #include "hilog/log.h"
19 #include "napi_hitrace_param.h"
20 #include "napi_hitrace_util.h"
21
22 using namespace OHOS::HiviewDFX;
23
24 namespace {
25 constexpr HiLogLabel LABEL = { LOG_CORE, 0xD002D03, "HITRACE_JS_NAPI" };
26 constexpr uint32_t BUF_SIZE_64 = 64;
27
ParseInt32Param(const napi_env & env,const napi_value & origin,int & dest)28 bool ParseInt32Param(const napi_env& env, const napi_value& origin, int& dest)
29 {
30 if (!NapiHitraceUtil::CheckValueTypeValidity(env, origin, napi_valuetype::napi_number)) {
31 return false;
32 }
33 napi_get_value_int32(env, origin, &dest);
34 return true;
35 }
36
ParseStringParam(const napi_env & env,const napi_value & origin,std::string & dest)37 bool ParseStringParam(const napi_env& env, const napi_value& origin, std::string& dest)
38 {
39 if (!NapiHitraceUtil::CheckValueTypeValidity(env, origin, napi_valuetype::napi_string)) {
40 return false;
41 }
42 char buf[BUF_SIZE_64] = {0};
43 size_t bufLength = 0;
44 napi_get_value_string_utf8(env, origin, buf, BUF_SIZE_64, &bufLength);
45 dest = std::string {buf};
46 return true;
47 }
48
ParseTraceIdObject(const napi_env & env,const napi_value & origin,HiTraceId & traceId)49 bool ParseTraceIdObject(const napi_env& env, const napi_value& origin, HiTraceId& traceId)
50 {
51 if (!NapiHitraceUtil::CheckValueTypeValidity(env, origin, napi_valuetype::napi_object)) {
52 return false;
53 }
54 NapiHitraceUtil::TransHiTraceIdJsObjectToNative(env, traceId, origin);
55 return true;
56 }
57
IsNullOrUndefinedType(const napi_env & env,const napi_value & origin)58 bool IsNullOrUndefinedType(const napi_env& env, const napi_value& origin)
59 {
60 return NapiHitraceUtil::CheckValueTypeValidity(env, origin, napi_valuetype::napi_null) ||
61 NapiHitraceUtil::CheckValueTypeValidity(env, origin, napi_valuetype::napi_undefined);
62 }
63 }
64
Begin(napi_env env,napi_callback_info info)65 static napi_value Begin(napi_env env, napi_callback_info info)
66 {
67 size_t paramNum = ParamNum::TOTAL_TWO;
68 napi_value params[ParamNum::TOTAL_TWO] = {0};
69 napi_value thisArg = nullptr;
70 void* data = nullptr;
71 NAPI_CALL(env, napi_get_cb_info(env, info, ¶mNum, params, &thisArg, &data));
72 HiTraceId traceId;
73 napi_value val = nullptr;
74 NapiHitraceUtil::CreateHiTraceIdJsObject(env, traceId, val);
75 if (paramNum != ParamNum::TOTAL_ONE && paramNum != ParamNum::TOTAL_TWO) {
76 HiLog::Error(LABEL,
77 "failed to begin a new trace, count of parameters is not equal to 1 or 2");
78 return val;
79 }
80 std::string name;
81 if (!ParseStringParam(env, params[ParamIndex::PARAM_FIRST], name)) {
82 HiLog::Error(LABEL, "name type must be string.");
83 return val;
84 }
85 int flag = HiTraceFlag::HITRACE_FLAG_DEFAULT;
86 if (paramNum == ParamNum::TOTAL_TWO &&
87 !ParseInt32Param(env, params[ParamIndex::PARAM_SECOND], flag) &&
88 !IsNullOrUndefinedType(env, params[ParamIndex::PARAM_SECOND])) {
89 HiLog::Error(LABEL, "flag type must be number, null or undefined.");
90 return val;
91 }
92 traceId = HiTraceChain::Begin(name, flag);
93 NapiHitraceUtil::CreateHiTraceIdJsObject(env, traceId, val);
94 return val;
95 }
96
End(napi_env env,napi_callback_info info)97 static napi_value End(napi_env env, napi_callback_info info)
98 {
99 size_t paramNum = ParamNum::TOTAL_ONE;
100 napi_value params[ParamNum::TOTAL_ONE] = {0};
101 napi_value thisArg = nullptr;
102 void* data = nullptr;
103 NAPI_CALL(env, napi_get_cb_info(env, info, ¶mNum, params, &thisArg, &data));
104 if (paramNum != ParamNum::TOTAL_ONE) {
105 HiLog::Error(LABEL,
106 "failed to end trace by trace id, count of parameters is not equal to 1.");
107 return nullptr;
108 }
109 HiTraceId traceId;
110 if (!ParseTraceIdObject(env, params[ParamIndex::PARAM_FIRST], traceId)) {
111 HiLog::Error(LABEL, "hitarce id type must be object.");
112 return nullptr;
113 }
114 HiTraceChain::End(traceId);
115 return nullptr;
116 }
117
GetId(napi_env env,napi_callback_info info)118 static napi_value GetId(napi_env env, napi_callback_info info)
119 {
120 HiTraceId traceId = HiTraceChain::GetId();
121 napi_value val = nullptr;
122 NapiHitraceUtil::CreateHiTraceIdJsObject(env, traceId, val);
123 return val;
124 }
125
SetId(napi_env env,napi_callback_info info)126 static napi_value SetId(napi_env env, napi_callback_info info)
127 {
128 size_t paramNum = ParamNum::TOTAL_ONE;
129 napi_value params[ParamNum::TOTAL_ONE] = {0};
130 napi_value thisArg = nullptr;
131 void* data = nullptr;
132 NAPI_CALL(env, napi_get_cb_info(env, info, ¶mNum, params, &thisArg, &data));
133 if (paramNum != ParamNum::TOTAL_ONE) {
134 HiLog::Error(LABEL,
135 "failed to set a new id for a trace, count of parameters is not equal to 1.");
136 return nullptr;
137 }
138 HiTraceId traceId;
139 if (!ParseTraceIdObject(env, params[ParamIndex::PARAM_FIRST], traceId)) {
140 HiLog::Error(LABEL, "hitarce id type must be object.");
141 return nullptr;
142 }
143 HiTraceChain::SetId(traceId);
144 return nullptr;
145 }
146
ClearId(napi_env env,napi_callback_info info)147 static napi_value ClearId(napi_env env, napi_callback_info info)
148 {
149 HiTraceChain::ClearId();
150 return nullptr;
151 }
152
CreateSpan(napi_env env,napi_callback_info info)153 static napi_value CreateSpan(napi_env env, napi_callback_info info)
154 {
155 HiTraceId traceId = HiTraceChain::CreateSpan();
156 napi_value val = nullptr;
157 NapiHitraceUtil::CreateHiTraceIdJsObject(env, traceId, val);
158 return val;
159 }
160
Tracepoint(napi_env env,napi_callback_info info)161 static napi_value Tracepoint(napi_env env, napi_callback_info info)
162 {
163 size_t paramNum = ParamNum::TOTAL_FOUR;
164 napi_value params[ParamNum::TOTAL_FOUR] = {0};
165 napi_value thisArg = nullptr;
166 void* data = nullptr;
167 NAPI_CALL(env, napi_get_cb_info(env, info, ¶mNum, params, &thisArg, &data));
168 if (paramNum != ParamNum::TOTAL_THREE && paramNum != ParamNum::TOTAL_FOUR) {
169 HiLog::Error(LABEL,
170 "failed to trace point, count of parameters is not equal to 3 or 4.");
171 return nullptr;
172 }
173 int communicationModeInt = 0;
174 if (!ParseInt32Param(env, params[ParamIndex::PARAM_FIRST], communicationModeInt)) {
175 HiLog::Error(LABEL, "HiTraceCommunicationMode type must be number.");
176 return nullptr;
177 }
178 HiTraceCommunicationMode communicationMode = HiTraceCommunicationMode(communicationModeInt);
179 int tracePointTypeInt = 0;
180 if (!ParseInt32Param(env, params[ParamIndex::PARAM_SECOND], tracePointTypeInt)) {
181 HiLog::Error(LABEL, "HiTraceTracePointType type must be number.");
182 return nullptr;
183 }
184 HiTraceTracepointType tracePointType = HiTraceTracepointType(tracePointTypeInt);
185 HiTraceId traceId;
186 if (!ParseTraceIdObject(env, params[ParamIndex::PARAM_THIRD], traceId)) {
187 HiLog::Error(LABEL, "hitarce id type must be object.");
188 return nullptr;
189 }
190 std::string description;
191 if (paramNum == ParamNum::TOTAL_FOUR &&
192 !ParseStringParam(env, params[ParamIndex::PARAM_FORTH], description) &&
193 !IsNullOrUndefinedType(env, params[ParamIndex::PARAM_FORTH])) {
194 HiLog::Error(LABEL, "description type must be string, null or undefined.");
195 return nullptr;
196 }
197 HiTraceChain::Tracepoint(communicationMode, tracePointType, traceId, "%s", description.c_str());
198 return nullptr;
199 }
200
IsValid(napi_env env,napi_callback_info info)201 static napi_value IsValid(napi_env env, napi_callback_info info)
202 {
203 size_t paramNum = ParamNum::TOTAL_ONE;
204 napi_value params[ParamNum::TOTAL_ONE] = {0};
205 napi_value thisArg = nullptr;
206 void* data = nullptr;
207 NAPI_CALL(env, napi_get_cb_info(env, info, ¶mNum, params, &thisArg, &data));
208 bool isValid = false;
209 napi_value val = nullptr;
210 napi_get_boolean(env, isValid, &val);
211 if (paramNum != ParamNum::TOTAL_ONE) {
212 HiLog::Error(LABEL,
213 "failed to check whether a id is valid or not, count of parameters is not equal to 1.");
214 return val;
215 }
216 HiTraceId traceId;
217 if (!ParseTraceIdObject(env, params[ParamIndex::PARAM_FIRST], traceId)) {
218 HiLog::Error(LABEL, "hitarce id type must be object.");
219 return val;
220 }
221 isValid = traceId.IsValid();
222 napi_get_boolean(env, isValid, &val);
223 return val;
224 }
225
IsFlagEnabled(napi_env env,napi_callback_info info)226 static napi_value IsFlagEnabled(napi_env env, napi_callback_info info)
227 {
228 size_t paramNum = ParamNum::TOTAL_TWO;
229 napi_value params[ParamNum::TOTAL_TWO] = {0};
230 napi_value thisArg = nullptr;
231 void* data = nullptr;
232 NAPI_CALL(env, napi_get_cb_info(env, info, ¶mNum, params, &thisArg, &data));
233 bool isFalgEnabled = false;
234 napi_value val = nullptr;
235 napi_get_boolean(env, isFalgEnabled, &val);
236 if (paramNum != ParamNum::TOTAL_TWO) {
237 HiLog::Error(LABEL,
238 "failed to check whether a flag is enabled in a trace id, count of parameters is not equal to 2.");
239 return val;
240 }
241 HiTraceId traceId;
242 if (!ParseTraceIdObject(env, params[ParamIndex::PARAM_FIRST], traceId)) {
243 HiLog::Error(LABEL, "hitarce id type must be object.");
244 return val;
245 }
246 int traceFlagInt = 0;
247 if (!ParseInt32Param(env, params[ParamIndex::PARAM_SECOND], traceFlagInt)) {
248 HiLog::Error(LABEL, "HiTraceFlag type must be number.");
249 return val;
250 }
251 HiTraceFlag traceFlag = HiTraceFlag(traceFlagInt);
252 isFalgEnabled = traceId.IsFlagEnabled(traceFlag);
253 napi_get_boolean(env, isFalgEnabled, &val);
254 return val;
255 }
256
EnableFlag(napi_env env,napi_callback_info info)257 static napi_value EnableFlag(napi_env env, napi_callback_info info)
258 {
259 size_t paramNum = ParamNum::TOTAL_TWO;
260 napi_value params[ParamNum::TOTAL_TWO] = {0};
261 napi_value thisArg = nullptr;
262 void* data = nullptr;
263 NAPI_CALL(env, napi_get_cb_info(env, info, ¶mNum, params, &thisArg, &data));
264 if (paramNum != ParamNum::TOTAL_TWO) {
265 HiLog::Error(LABEL,
266 "failed to enable a flag for a trace id, count of parameters is not equal to 2.");
267 return nullptr;
268 }
269 HiTraceId traceId;
270 if (!ParseTraceIdObject(env, params[ParamIndex::PARAM_FIRST], traceId)) {
271 HiLog::Error(LABEL, "hitarce id type must be object.");
272 return nullptr;
273 }
274 int traceFlagInt = 0;
275 if (!ParseInt32Param(env, params[ParamIndex::PARAM_SECOND], traceFlagInt)) {
276 HiLog::Error(LABEL, "HiTraceFlag type must be number.");
277 return nullptr;
278 }
279 HiTraceFlag traceFlag = HiTraceFlag(traceFlagInt);
280 traceId.EnableFlag(traceFlag);
281 NapiHitraceUtil::EnableTraceIdObjectFlag(env, traceId, params[ParamIndex::PARAM_FIRST]);
282 return nullptr;
283 }
284
285 EXTERN_C_START
TraceNapiInit(napi_env env,napi_value exports)286 static napi_value TraceNapiInit(napi_env env, napi_value exports)
287 {
288 napi_property_descriptor desc[] = {
289 DECLARE_NAPI_FUNCTION("begin", Begin),
290 DECLARE_NAPI_FUNCTION("end", End),
291 DECLARE_NAPI_FUNCTION("getId", GetId),
292 DECLARE_NAPI_FUNCTION("setId", SetId),
293 DECLARE_NAPI_FUNCTION("clearId", ClearId),
294 DECLARE_NAPI_FUNCTION("createSpan", CreateSpan),
295 DECLARE_NAPI_FUNCTION("tracepoint", Tracepoint),
296 DECLARE_NAPI_FUNCTION("isValid", IsValid),
297 DECLARE_NAPI_FUNCTION("isFlagEnabled", IsFlagEnabled),
298 DECLARE_NAPI_FUNCTION("enableFlag", EnableFlag),
299 };
300 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc));
301
302 // init HiTraceFlag class, HiTraceTracePointType class and HiTraceCommunicationMode class
303 InitNapiClass(env, exports);
304 return exports;
305 }
306 EXTERN_C_END
307
308 static napi_module hitrace_module = {
309 .nm_version = 1,
310 .nm_flags = 0,
311 .nm_filename = nullptr,
312 .nm_register_func = TraceNapiInit,
313 .nm_modname = "hiTraceChain",
314 .nm_priv = (reinterpret_cast<void *>(0)),
315 .reserved = {0}
316 };
317
RegisterModule(void)318 extern "C" __attribute__((constructor)) void RegisterModule(void)
319 {
320 napi_module_register(&hitrace_module);
321 }
322