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