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