1 /*
2 * Copyright (c) 2025 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 <array>
17 #include <iostream>
18 #include "hilog/log.h"
19 #include "hitraceid.h"
20 #include "hitracechain.h"
21 #include "hitrace_chain_ani.h"
22 #include "hitrace_chain_ani_util.h"
23 #include "hitrace_chain_ani_parameter_name.h"
24
25 using namespace OHOS::HiviewDFX;
26 #undef LOG_DOMAIN
27 #define LOG_DOMAIN 0xD002D33
28
29 #undef LOG_TAG
30 #define LOG_TAG "HitraceChainAni"
31
Begin(ani_env * env,ani_string nameAni,ani_object flagAni)32 ani_object HiTraceChainAni::Begin(ani_env* env, ani_string nameAni, ani_object flagAni)
33 {
34 HiTraceId traceId;
35 std::string name;
36 ani_object val = {};
37 HiTraceChainAniUtil::ParseStringValue(env, nameAni, name);
38 if (HiTraceChainAniUtil::ParseStringValue(env, nameAni, name) != ANI_OK) {
39 HILOG_ERROR(LOG_CORE, "name type must be string.");
40 return val;
41 }
42 int flag = HiTraceFlag::HITRACE_FLAG_DEFAULT;
43 if (!HiTraceChainAniUtil::IsRefUndefined(env, static_cast<ani_ref>(flagAni))) {
44 flag = HiTraceChainAniUtil::ParseNumberValueInt32(env, flagAni);
45 }
46 traceId = HiTraceChain::Begin(name, flag);
47 val = HiTraceChainAni::Result(env, traceId);
48 return val;
49 };
50
51
SetChainId(ani_env * env,HiTraceId & traceId,ani_object & hiTrace_object,ani_class cls)52 static ani_status SetChainId(ani_env* env, HiTraceId& traceId, ani_object& hiTrace_object, ani_class cls)
53 {
54 uint64_t chainId = traceId.GetChainId();
55 ani_object bigint_ctor = HiTraceChainAniUtil::CreateBigInt(env, chainId);
56 ani_method chainIdSetter;
57 if (env->Class_FindMethod(cls, "<set>chainId", nullptr, &chainIdSetter) != ANI_OK) {
58 HILOG_ERROR(LOG_CORE, "find method %{public}s failed", CLASS_NAME_HITRACEID_CHAINID);
59 return ANI_ERROR;
60 }
61 if (env->Object_CallMethod_Void(hiTrace_object, chainIdSetter, bigint_ctor) != ANI_OK) {
62 HILOG_ERROR(LOG_CORE, "call method %{public}s failed", CLASS_NAME_HITRACEID_CHAINID);
63 return ANI_ERROR;
64 }
65 return ANI_OK;
66 }
67
SetSpanId(ani_env * env,HiTraceId & traceId,ani_object & hiTrace_object,ani_class cls)68 static ani_status SetSpanId(ani_env* env, HiTraceId& traceId, ani_object& hiTrace_object, ani_class cls)
69 {
70 ani_method parentSpanIdSetter;
71 if (env->Class_FindMethod(cls, "<set>parentSpanId", nullptr, &parentSpanIdSetter) != ANI_OK) {
72 HILOG_ERROR(LOG_CORE, "find method %{public}s failed", CLASS_NAME_HITRACEID_PARENTSSPANID);
73 return ANI_ERROR;
74 }
75 uint64_t parentSpanId = traceId.GetParentSpanId();
76 ani_object parentSpanId_ctor = HiTraceChainAniUtil::CreateDoubleUint64(env, parentSpanId);
77 if (env->Object_CallMethod_Void(hiTrace_object, parentSpanIdSetter, parentSpanId_ctor) != ANI_OK) {
78 HILOG_ERROR(LOG_CORE, "call method %{public}s failed", CLASS_NAME_HITRACEID_PARENTSSPANID);
79 return ANI_ERROR;
80 }
81 return ANI_OK;
82 }
83
SetParentSpanId(ani_env * env,HiTraceId & traceId,ani_object & hiTrace_object,ani_class cls)84 static ani_status SetParentSpanId(ani_env* env, HiTraceId& traceId, ani_object& hiTrace_object, ani_class cls)
85 {
86 ani_method spanIdSetter;
87 if (env->Class_FindMethod(cls, "<set>spanId", nullptr, &spanIdSetter) != ANI_OK) {
88 HILOG_ERROR(LOG_CORE, "find method %{public}s failed", CLASS_NAME_HITRACEID_SPANID);
89 return ANI_ERROR;
90 }
91 uint64_t spanId = traceId.GetSpanId();
92 ani_object spanId_ctor = HiTraceChainAniUtil::CreateDoubleUint64(env, spanId);
93 if (env->Object_CallMethod_Void(hiTrace_object, spanIdSetter, spanId_ctor) != ANI_OK) {
94 HILOG_ERROR(LOG_CORE, "call method %{public}s failed", CLASS_NAME_HITRACEID_SPANID);
95 return ANI_ERROR;
96 }
97 return ANI_OK;
98 }
99
SetFlags(ani_env * env,HiTraceId & traceId,ani_object & hiTrace_object,ani_class cls)100 static ani_status SetFlags(ani_env* env, HiTraceId& traceId, ani_object& hiTrace_object, ani_class cls)
101 {
102 ani_method flagsSetter;
103 if (env->Class_FindMethod(cls, "<set>flags", nullptr, &flagsSetter) != ANI_OK) {
104 HILOG_ERROR(LOG_CORE, "find method %{public}s failed", CLASS_NAME_HITRACEID_FLAGS);
105 return ANI_ERROR;
106 }
107 int flags = traceId.GetFlags();
108 ani_object flags_ctor = HiTraceChainAniUtil::CreateDoubleInt(env, flags);
109 if (env->Object_CallMethod_Void(hiTrace_object, flagsSetter, flags_ctor) != ANI_OK) {
110 HILOG_ERROR(LOG_CORE, "call method %{public}s failed", CLASS_NAME_HITRACEID_FLAGS);
111 return ANI_ERROR;
112 }
113 return ANI_OK;
114 }
115
Result(ani_env * env,HiTraceId & traceId)116 ani_object HiTraceChainAni::Result(ani_env* env, HiTraceId& traceId)
117 {
118 ani_object hiTrace_object = nullptr;
119 ani_class cls;
120 if (env->FindClass(CLASS_NAME_HITRACEID, &cls) != ANI_OK) {
121 HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_HITRACEID);
122 return hiTrace_object;
123 }
124 ani_method ctor;
125 if (env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor) != ANI_OK) {
126 HILOG_ERROR(LOG_CORE, "find method %{public}s failed", CLASS_NAME_HITRACEID);
127 return hiTrace_object;
128 }
129 if (env->Object_New(cls, ctor, &hiTrace_object) != ANI_OK) {
130 HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_HITRACEID);
131 return hiTrace_object;
132 }
133
134 if (SetChainId(env, traceId, hiTrace_object, cls) != ANI_OK) {
135 HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_HITRACEID);
136 return hiTrace_object;
137 }
138 if (SetSpanId(env, traceId, hiTrace_object, cls) != ANI_OK) {
139 HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_HITRACEID);
140 return hiTrace_object;
141 }
142 if (SetParentSpanId(env, traceId, hiTrace_object, cls) != ANI_OK) {
143 HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_HITRACEID);
144 return hiTrace_object;
145 }
146 if (SetFlags(env, traceId, hiTrace_object, cls) != ANI_OK) {
147 HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_HITRACEID);
148 return hiTrace_object;
149 }
150 return hiTrace_object;
151 }
152
ParseHiTraceId(ani_env * env,ani_object HiTraceIdAni,HiTraceId & traceId)153 static void ParseHiTraceId(ani_env* env, ani_object HiTraceIdAni, HiTraceId& traceId)
154 {
155 ani_ref chainIdRef {};
156 if (env->Object_GetPropertyByName_Ref(HiTraceIdAni, "chainId", &chainIdRef) != ANI_OK) {
157 HILOG_ERROR(LOG_CORE, "get chainId %{public}s failed", CLASS_NAME_HITRACEID);
158 return;
159 }
160 uint64_t chainId = UINT64_T_PRO_DEFAULT_VALUE;
161 chainId = HiTraceChainAniUtil::ParseBigIntValue(env, chainIdRef);
162 if (chainId == INVALID_CHAIN_ID) {
163 return;
164 }
165 traceId.SetChainId(chainId);
166
167 ani_ref spanIdRef {};
168 if (env->Object_GetPropertyByName_Ref(HiTraceIdAni, "spanId", &spanIdRef) != ANI_OK) {
169 HILOG_ERROR(LOG_CORE, "get spanId %{public}s failed", CLASS_NAME_HITRACEID);
170 return;
171 }
172 uint64_t spanId = UINT64_T_PRO_DEFAULT_VALUE;
173 if (!HiTraceChainAniUtil::IsRefUndefined(env, spanIdRef)) {
174 spanId = static_cast<uint64_t>(HiTraceChainAniUtil::ParseNumberValueInt64(env, spanIdRef));
175 traceId.SetSpanId(spanId);
176 }
177
178 ani_ref parentSpanIdRef {};
179 if (env->Object_GetPropertyByName_Ref(HiTraceIdAni, "parentSpanId", &parentSpanIdRef) != ANI_OK) {
180 HILOG_ERROR(LOG_CORE, "get parentSpanId %{public}s failed", CLASS_NAME_HITRACEID);
181 return;
182 }
183 uint64_t parentSpanId = UINT64_T_PRO_DEFAULT_VALUE;
184 if (!HiTraceChainAniUtil::IsRefUndefined(env, parentSpanIdRef)) {
185 parentSpanId = static_cast<uint64_t>(HiTraceChainAniUtil::ParseNumberValueInt64(env, parentSpanIdRef));
186 traceId.SetParentSpanId(parentSpanId);
187 }
188
189 ani_ref flagsRef {};
190 if (env->Object_GetPropertyByName_Ref(HiTraceIdAni, "flags", &flagsRef) != ANI_OK) {
191 HILOG_ERROR(LOG_CORE, "get flags %{public}s failed", CLASS_NAME_HITRACEID);
192 return;
193 }
194 uint32_t flags = UINT32_T_PRO_DEFAULT_VALUE;
195 if (!HiTraceChainAniUtil::IsRefUndefined(env, flagsRef)) {
196 flags = static_cast<uint32_t>(HiTraceChainAniUtil::ParseNumberValueInt32(env, flagsRef));
197 traceId.SetFlags(flags);
198 }
199 }
200
End(ani_env * env,ani_object HiTraceIdAni)201 void HiTraceChainAni::End(ani_env* env, ani_object HiTraceIdAni)
202 {
203 HiTraceId traceId;
204 ParseHiTraceId(env, HiTraceIdAni, traceId);
205 HiTraceChain::End(traceId);
206 }
207
SetId(ani_env * env,ani_object HiTraceIdAni)208 void HiTraceChainAni::SetId(ani_env* env, ani_object HiTraceIdAni)
209 {
210 HiTraceId traceId;
211 ParseHiTraceId(env, HiTraceIdAni, traceId);
212 HiTraceChain::SetId(traceId);
213 }
214
GetId(ani_env * env)215 ani_object HiTraceChainAni::GetId(ani_env* env)
216 {
217 HiTraceId traceId = HiTraceChain::GetId();
218 return HiTraceChainAni::Result(env, traceId);
219 }
220
ClearId(ani_env * env)221 void HiTraceChainAni::ClearId(ani_env* env)
222 {
223 HiTraceChain::ClearId();
224 }
225
CreateSpan(ani_env * env)226 ani_object HiTraceChainAni::CreateSpan(ani_env* env)
227 {
228 HiTraceId traceId = HiTraceChain::CreateSpan();
229 return HiTraceChainAni::Result(env, traceId);
230 }
231
Tracepoint(ani_env * env,ani_enum_item modeAni,ani_enum_item typeAni,ani_object HiTraceIdAni,ani_string msgAni)232 void HiTraceChainAni::Tracepoint(ani_env* env, ani_enum_item modeAni,
233 ani_enum_item typeAni, ani_object HiTraceIdAni, ani_string msgAni)
234 {
235 int communicationModeInt = 0;
236 if (HiTraceChainAniUtil::EnumGetValueInt32(env, modeAni, communicationModeInt) != ANI_OK) {
237 return;
238 }
239 HiTraceCommunicationMode communicationMode = HiTraceCommunicationMode(communicationModeInt);
240 int tracePointTypeInt = 0;
241 if (HiTraceChainAniUtil::EnumGetValueInt32(env, typeAni, tracePointTypeInt) != ANI_OK) {
242 return;
243 }
244 HiTraceTracepointType tracePointType = HiTraceTracepointType(tracePointTypeInt);
245 HiTraceId traceId;
246 ParseHiTraceId(env, HiTraceIdAni, traceId);
247 std::string description;
248 HiTraceChainAniUtil::ParseStringValue(env, msgAni, description);
249 HiTraceChain::Tracepoint(communicationMode, tracePointType, traceId, "%s", description.c_str());
250 }
251
IsValid(ani_env * env,ani_object HiTraceIdAni)252 ani_boolean HiTraceChainAni::IsValid(ani_env* env, ani_object HiTraceIdAni)
253 {
254 bool isValid = false;
255 HiTraceId traceId;
256 ParseHiTraceId(env, HiTraceIdAni, traceId);
257 isValid = traceId.IsValid();
258 return static_cast<ani_boolean>(isValid);
259 }
260
IsFlagEnabled(ani_env * env,ani_object HiTraceIdAni,ani_enum_item flagAni)261 ani_boolean HiTraceChainAni::IsFlagEnabled(ani_env* env, ani_object HiTraceIdAni,
262 ani_enum_item flagAni)
263 {
264 bool isFalgEnabled = false;
265 HiTraceId traceId;
266 ParseHiTraceId(env, HiTraceIdAni, traceId);
267 int traceFlagInt = 0;
268 if (HiTraceChainAniUtil::EnumGetValueInt32(env, flagAni, traceFlagInt) != ANI_OK) {
269 return isFalgEnabled;
270 }
271 HiTraceFlag traceFlag = HiTraceFlag(traceFlagInt);
272 isFalgEnabled = traceId.IsFlagEnabled(traceFlag);
273 return static_cast<ani_boolean>(isFalgEnabled);
274 }
275
EnableFlag(ani_env * env,ani_object HiTraceIdAni,ani_enum_item flagAni)276 void HiTraceChainAni::EnableFlag(ani_env* env, ani_object HiTraceIdAni,
277 ani_enum_item flagAni)
278 {
279 HiTraceId traceId;
280 ParseHiTraceId(env, HiTraceIdAni, traceId);
281 int traceFlagInt = 0;
282 if (HiTraceChainAniUtil::EnumGetValueInt32(env, flagAni, traceFlagInt) != ANI_OK) {
283 return;
284 }
285 HiTraceFlag traceFlag = HiTraceFlag(traceFlagInt);
286 traceId.EnableFlag(traceFlag);
287 ani_object flagsObj = HiTraceChainAniUtil::CreateDoubleInt(env, traceId.GetFlags());
288 ani_status status = env->Object_SetPropertyByName_Ref(HiTraceIdAni, "flags", static_cast<ani_ref>(flagsObj));
289 if (status != ANI_OK) {
290 HILOG_ERROR(LOG_CORE, "create object failed");
291 }
292 }
293
ANI_Constructor(ani_vm * vm,uint32_t * result)294 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
295 {
296 ani_env* env;
297 if (vm->GetEnv(ANI_VERSION_1, &env) != ANI_OK) {
298 return ANI_ERROR;
299 }
300 ani_namespace ns {};
301 if (env->FindNamespace(CLASS_NAME_HITRACECHAIN, &ns) != ANI_OK) {
302 return ANI_ERROR;
303 }
304 std::array methods = {
305 ani_native_function {"begin", nullptr, reinterpret_cast<void *>(HiTraceChainAni::Begin)},
306 ani_native_function {"end", nullptr, reinterpret_cast<void *>(HiTraceChainAni::End)},
307 ani_native_function {"setId", nullptr, reinterpret_cast<void *>(HiTraceChainAni::SetId)},
308 ani_native_function {"getId", nullptr, reinterpret_cast<void *>(HiTraceChainAni::GetId)},
309 ani_native_function {"clearId", nullptr, reinterpret_cast<void *>(HiTraceChainAni::ClearId)},
310 ani_native_function {"createSpan", nullptr, reinterpret_cast<void *>(HiTraceChainAni::CreateSpan)},
311 ani_native_function {"tracepoint", nullptr, reinterpret_cast<void *>(HiTraceChainAni::Tracepoint)},
312 ani_native_function {"isValid", nullptr, reinterpret_cast<void *>(HiTraceChainAni::IsValid)},
313 ani_native_function {"isFlagEnabled", nullptr, reinterpret_cast<void *>(HiTraceChainAni::IsFlagEnabled)},
314 ani_native_function {"enableFlag", nullptr, reinterpret_cast<void *>(HiTraceChainAni::EnableFlag)},
315 };
316 if (env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size()) != ANI_OK) {
317 return ANI_ERROR;
318 };
319 *result = ANI_VERSION_1;
320 return ANI_OK;
321 }
322