• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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