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_util.h"
17 
18 #include "hilog/log.h"
19 
20 namespace OHOS {
21 namespace HiviewDFX {
22 namespace {
23 #undef LOG_DOMAIN
24 #define LOG_DOMAIN 0xD002D33
25 #undef LOG_TAG
26 #define LOG_TAG "HITRACE_UTIL_NAPI"
27 
28 constexpr uint32_t UINT32_T_PRO_DEFAULT_VALUE = 0;
29 constexpr uint64_t UINT64_T_PRO_DEFAULT_VALUE = 0;
30 constexpr uint64_t INVALID_CHAIN_ID = 0;
31 constexpr char CHAIN_ID_ATTR[] = "chainId";
32 constexpr char SPAN_ID_ATTR[] = "spanId";
33 constexpr char PARENT_SPAN_ID_ATTR[] = "parentSpanId";
34 constexpr char FLAGS_ATTR[] = "flags";
35 
CreateInt32Value(const napi_env env,int32_t value)36 napi_value CreateInt32Value(const napi_env env, int32_t value)
37 {
38     napi_value result = nullptr;
39     NAPI_CALL(env, napi_create_int32(env, value, &result));
40     return result;
41 }
42 
CreateInt64Value(const napi_env env,int64_t value)43 napi_value CreateInt64Value(const napi_env env, int64_t value)
44 {
45     napi_value result = nullptr;
46     NAPI_CALL(env, napi_create_int64(env, value, &result));
47     return result;
48 }
49 
CreateBigInt64Value(const napi_env env,uint64_t value)50 napi_value CreateBigInt64Value(const napi_env env, uint64_t value)
51 {
52     napi_value result = nullptr;
53     NAPI_CALL(env, napi_create_bigint_uint64(env, value, &result));
54     return result;
55 }
56 
SetNamedProperty(const napi_env env,napi_value & object,const std::string & propertyName,napi_value & propertyValue)57 napi_status SetNamedProperty(const napi_env env, napi_value& object,
58     const std::string& propertyName, napi_value& propertyValue)
59 {
60     napi_status status = napi_set_named_property(env, object, propertyName.c_str(), propertyValue);
61     if (status != napi_ok) {
62         HILOG_ERROR(LOG_CORE, "set property %{public}s failed.", propertyName.c_str());
63     }
64     return status;
65 }
66 
GetPropertyByName(const napi_env env,const napi_value & object,const std::string & propertyName)67 napi_value GetPropertyByName(const napi_env env, const napi_value& object,
68     const std::string& propertyName)
69 {
70     napi_value result = nullptr;
71     NAPI_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &result));
72     return result;
73 }
74 }
75 
CheckValueTypeValidity(const napi_env env,const napi_value & jsObj,const napi_valuetype typeName)76 bool NapiHitraceUtil::CheckValueTypeValidity(const napi_env env, const napi_value& jsObj,
77     const napi_valuetype typeName)
78 {
79     napi_valuetype valueType = napi_undefined;
80     napi_status ret = napi_typeof(env, jsObj, &valueType);
81     if (ret != napi_ok) {
82         HILOG_ERROR(LOG_CORE, "failed to parse the type of napi value.");
83         return false;
84     }
85     if (valueType != typeName) {
86         HILOG_ERROR(LOG_CORE, "you have called a function with parameters of wrong type.");
87         return false;
88     }
89     return true;
90 }
91 
CreateHiTraceIdJsObject(const napi_env env,HiTraceId & traceId,napi_value & valueObject)92 void NapiHitraceUtil::CreateHiTraceIdJsObject(const napi_env env, HiTraceId& traceId,
93     napi_value& valueObject)
94 {
95     napi_create_object(env, &valueObject);
96     NapiHitraceUtil::SetPropertyBigInt64(env, valueObject, CHAIN_ID_ATTR,
97         traceId.GetChainId());
98     HILOG_DEBUG(LOG_CORE, "Native2Js: chainId is %{public}llx.",
99         static_cast<unsigned long long>(traceId.GetChainId()));
100     NapiHitraceUtil::SetPropertyInt64(env, valueObject, SPAN_ID_ATTR, traceId.GetSpanId());
101     HILOG_DEBUG(LOG_CORE, "Native2Js: spanId is %{public}llx.",
102         static_cast<unsigned long long>(traceId.GetSpanId()));
103     NapiHitraceUtil::SetPropertyInt64(env, valueObject, PARENT_SPAN_ID_ATTR,
104         traceId.GetParentSpanId());
105     HILOG_DEBUG(LOG_CORE, "Native2Js: parentSpanId is %{public}llx.",
106         static_cast<unsigned long long>(traceId.GetParentSpanId()));
107     NapiHitraceUtil::SetPropertyInt32(env, valueObject, FLAGS_ATTR,
108         traceId.GetFlags());
109     HILOG_DEBUG(LOG_CORE, "Native2Js: flags is %{public}d.", traceId.GetFlags());
110 }
111 
TransHiTraceIdJsObjectToNative(const napi_env env,HiTraceId & traceId,const napi_value & valueObject)112 void NapiHitraceUtil::TransHiTraceIdJsObjectToNative(const napi_env env, HiTraceId& traceId,
113     const napi_value& valueObject)
114 {
115     uint64_t chainId = NapiHitraceUtil::GetPropertyBigInt64(env, valueObject, CHAIN_ID_ATTR);
116     HILOG_DEBUG(LOG_CORE, "Js2Native: chainId is %{public}llx.",
117         static_cast<unsigned long long>(chainId));
118     if (chainId == INVALID_CHAIN_ID) {
119         return;
120     }
121     traceId.SetChainId(chainId);
122     uint64_t spanId = NapiHitraceUtil::GetPropertyInt64(env, valueObject, SPAN_ID_ATTR);
123     HILOG_DEBUG(LOG_CORE, "Js2Native: spanId is %{public}llx.",
124         static_cast<unsigned long long>(spanId));
125     traceId.SetSpanId(spanId);
126     uint64_t parentSpanId = NapiHitraceUtil::GetPropertyInt64(env, valueObject,
127         PARENT_SPAN_ID_ATTR);
128     HILOG_DEBUG(LOG_CORE, "Js2Native: parentSpanId is %{public}llx.",
129         static_cast<unsigned long long>(parentSpanId));
130     traceId.SetParentSpanId(parentSpanId);
131     uint32_t flags = NapiHitraceUtil::GetPropertyInt32(env, valueObject, FLAGS_ATTR);
132     HILOG_DEBUG(LOG_CORE, "Js2Native: flags is %{public}d.", flags);
133     traceId.SetFlags(flags);
134 }
135 
EnableTraceIdObjectFlag(const napi_env env,HiTraceId & traceId,napi_value & traceIdObject)136 void NapiHitraceUtil::EnableTraceIdObjectFlag(const napi_env env, HiTraceId& traceId,
137     napi_value& traceIdObject)
138 {
139     NapiHitraceUtil::SetPropertyInt32(env, traceIdObject, FLAGS_ATTR, traceId.GetFlags());
140 }
141 
SetPropertyInt32(const napi_env env,napi_value & object,const std::string & propertyName,uint32_t value)142 void NapiHitraceUtil::SetPropertyInt32(const napi_env env, napi_value& object,
143     const std::string& propertyName, uint32_t value)
144 {
145     napi_value peropertyValue = CreateInt32Value(env, value);
146     SetNamedProperty(env, object, propertyName, peropertyValue);
147 }
148 
SetPropertyInt64(const napi_env env,napi_value & object,const std::string & propertyName,uint64_t value)149 void NapiHitraceUtil::SetPropertyInt64(const napi_env env, napi_value& object,
150     const std::string& propertyName, uint64_t value)
151 {
152     napi_value peropertyValue = CreateInt64Value(env, value);
153     SetNamedProperty(env, object, propertyName, peropertyValue);
154 }
155 
SetPropertyBigInt64(const napi_env env,napi_value & object,const std::string & propertyName,uint64_t value)156 void NapiHitraceUtil::SetPropertyBigInt64(const napi_env env, napi_value& object,
157     const std::string& propertyName, uint64_t value)
158 {
159     napi_value peropertyValue = CreateBigInt64Value(env, value);
160     SetNamedProperty(env, object, propertyName, peropertyValue);
161 }
162 
GetPropertyInt32(const napi_env env,const napi_value & object,const std::string & propertyName)163 uint32_t NapiHitraceUtil::GetPropertyInt32(const napi_env env, const napi_value& object,
164     const std::string& propertyName)
165 {
166     napi_value propertyValue = GetPropertyByName(env, object, propertyName);
167     napi_valuetype type;
168     napi_status status = napi_typeof(env, propertyValue, &type);
169     if (status != napi_ok) {
170         HILOG_ERROR(LOG_CORE, "failed to get %{public}s from HiTraceId Js Object.",
171             propertyName.c_str());
172         return UINT32_T_PRO_DEFAULT_VALUE;
173     }
174     if (type != napi_valuetype::napi_number) {
175         HILOG_ERROR(LOG_CORE, "type is not napi_number property.");
176         return UINT32_T_PRO_DEFAULT_VALUE;
177     }
178     int32_t numberValue = 0;
179     status = napi_get_value_int32(env, propertyValue, &numberValue);
180     if (status == napi_ok) {
181         return numberValue;
182     }
183     HILOG_ERROR(LOG_CORE, "failed to get napi_number property from HiTraceId Js Object.");
184     return UINT32_T_PRO_DEFAULT_VALUE;
185 }
186 
GetPropertyInt64(const napi_env env,const napi_value & object,const std::string & propertyName)187 uint64_t NapiHitraceUtil::GetPropertyInt64(const napi_env env, const napi_value& object,
188     const std::string& propertyName)
189 {
190     napi_value propertyValue = GetPropertyByName(env, object, propertyName);
191     napi_valuetype type;
192     napi_status status = napi_typeof(env, propertyValue, &type);
193     if (status != napi_ok) {
194         HILOG_ERROR(LOG_CORE, "failed to get %{public}s from HiTraceId Js Object.",
195             propertyName.c_str());
196         return UINT64_T_PRO_DEFAULT_VALUE;
197     }
198     if (type != napi_valuetype::napi_number) {
199         HILOG_ERROR(LOG_CORE, "type is not napi_number property.");
200         return UINT64_T_PRO_DEFAULT_VALUE;
201     }
202     int64_t numberValue = 0;
203     status = napi_get_value_int64(env, propertyValue, &numberValue);
204     if (status == napi_ok) {
205         return numberValue;
206     }
207     HILOG_ERROR(LOG_CORE, "failed to get napi_number property from HiTraceId Js Object.");
208     return UINT64_T_PRO_DEFAULT_VALUE;
209 }
210 
GetPropertyBigInt64(const napi_env env,const napi_value & object,const std::string & propertyName)211 uint64_t NapiHitraceUtil::GetPropertyBigInt64(const napi_env env, const napi_value& object,
212     const std::string& propertyName)
213 {
214     napi_value propertyValue = GetPropertyByName(env, object, propertyName);
215     napi_valuetype type;
216     napi_status status = napi_typeof(env, propertyValue, &type);
217     if (status != napi_ok) {
218         HILOG_ERROR(LOG_CORE, "failed to get %{public}s from HiTraceId Js Object.",
219             propertyName.c_str());
220         return UINT64_T_PRO_DEFAULT_VALUE;
221     }
222     uint64_t bigInt64Value = 0;
223     bool lossless = true;
224     napi_get_value_bigint_uint64(env, propertyValue, &bigInt64Value, &lossless);
225     return bigInt64Value;
226 }
227 } // namespace HiviewDFX
228 } // namespace OHOS
229