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