1# Using hiTraceChain (C/C++) 2 3<!--Kit: Performance Analysis Kit--> 4<!--Subsystem: HiviewDFX--> 5<!--Owner: @qq_437963121--> 6<!--Designer: @MontSaintMichel--> 7<!--Tester: @gcw_KuLfPSbe--> 8<!--Adviser: @foryourself--> 9 10## Available APIs 11 12The APIs for distributed call chain tracing are provided by the HiTraceChain module. For details, see [trace.h](../reference/apis-performance-analysis-kit/capi-trace-h.md). 13 14The following table lists the APIs provided by HiTraceChain for implementing the basic distributed tracing functionality. The corresponding APIs are also available in ArkTS. 15 16| API| Description| 17| -------- | -------- | 18| HiTraceId OH_HiTrace_BeginChain(const char \*name, int flags) | Starts call chain tracing and returns the created **HiTraceId**.| 19| void OH_HiTrace_EndChain() | Stops call chain tracing.| 20| HiTraceId OH_HiTrace_GetId() | Obtains the trace ID in TLS of the calling thread.| 21| void OH_HiTrace_SetId(const HiTraceId \*id) | Sets the trace ID in TLS of the calling thread to **id**.| 22| void OH_HiTrace_ClearId(void) | Clears the trace ID of the current thread.| 23| HiTraceId OH_HiTrace_CreateSpan(void) | Creates a trace span. Specifically, create a **HiTraceId**, use the **chainId** and **spanId** in the Thread-Local Storage (TLS) of the current thread to initialize the **chainId** and **parentSpanId** of the **HiTraceId**, generate a new **spanId** for the **HiTraceId**, and return the **HiTraceId**.| 24| bool OH_HiTrace_IsIdValid(const HiTraceId \*id) | Checks whether the **HiTraceId** is valid.<br>The value **true** indicates that **HiTraceId** is valid, and **false** indicates the opposite.| 25| bool OH_HiTrace_IsFlagEnabled(const HiTraceId \*id, HiTrace_Flag flag) | Checks whether the trace flag specified by **HiTraceId** is enabled.<br>The value **true** indicates that the specified trace flag is enabled, and **false** indicates the opposite.| 26| void OH_HiTrace_EnableFlag(const HiTraceId \*id, HiTrace_Flag flag) | Enables the trace flag specified in **HiTraceId**.| 27| void OH_HiTrace_Tracepoint(HiTrace_Communication_Mode mode, HiTrace_Tracepoint_Type type, const HiTraceId \*id, const char \*fmt, ...) | Adds a trace point for the HiTraceMeter logging.| 28 29The following table describes the APIs provided to extend **HiTraceId**. These APIs are available only in C/C++. 30 31| API| Description| 32| -------- | -------- | 33| void OH_HiTrace_InitId(HiTraceId \*id) | Initializes a **HiTraceId**.| 34| int OH_HiTrace_GetFlags(const HiTraceId \*id) | Obtains the trace flag set in **HiTraceId**.| 35| void OH_HiTrace_SetFlags(HiTraceId \*id, int flags) | Sets the trace flag in **HiTraceId**.| 36| uint64_t OH_HiTrace_GetChainId(const HiTraceId \*id) | Obtains the trace chain ID in **HiTraceId**.| 37| void OH_HiTrace_SetChainId(HiTraceId \*id, uint64_t chainId) | Sets the trace chain ID in **HiTraceId**.| 38| uint64_t OH_HiTrace_GetSpanId(const HiTraceId \*id) | Obtains the span ID in **HiTraceId**.| 39| void OH_HiTrace_SetSpanId(HiTraceId \*id, uint64_t spanId) | Sets the span ID in **HiTraceId**.| 40| uint64_t OH_HiTrace_GetParentSpanId(const HiTraceId \*id) | Obtains the parent span ID in **HiTraceId**.| 41| void OH_HiTrace_SetParentSpanId(HiTraceId \*id, uint64_t parentSpanId) | Sets the parent span ID in **HiTraceId**.| 42| int OH_HiTrace_IdToBytes(const HiTraceId\* id, uint8_t\* pIdArray, int len) | Converts **HiTraceId** into a byte array for cache or communication.| 43| void OH_HiTrace_IdFromBytes(HiTraceId \*id, const uint8_t \*pIdArray, int len) | Creates a **HiTraceId** based on a byte array.| 44 45 46## How to Develop 47 48**std::thread** does not support automatic transfer of **HiTraceId**. The following example shows how to use distributed tracing in this scenario. For details about the common mechanisms that support and do not support HiTraceChain automatic transfer, see [Constraints](hitracechain-intro.md#constraints). 49 501. Create a project in DevEco Studio and select **Native C++**. The project directory structure is as follows: 51 52 ```text 53 ├── entry 54 │ ├── src 55 │ ├── main 56 │ │ ├── cpp 57 │ │ │ ├── CMakeLists.txt 58 │ │ │ ├── napi_init.cpp 59 │ │ │ └── types 60 │ │ │ └── libentry 61 │ │ │ ├── Index.d.ts 62 │ │ │ └── oh-package.json5 63 │ │ ├── ets 64 │ │ │ ├── entryability 65 │ │ │ │ └── EntryAbility.ets 66 │ │ │ ├── entrybackupability 67 │ │ │ │ └── EntryBackupAbility.ets 68 │ │ │ └── pages 69 │ │ │ └── Index.ets 70 ``` 71 722. In the **entry > src > main > cpp > CMakeLists.tx** file, add **libhitrace_ndk.z.so** and **libhilog_ndk.z.so**. The complete file content is as follows: 73 74 ```cmake 75 # Minimum version of CMake. 76 cmake_minimum_required(VERSION 3.5.0) 77 project(HiTraceChainTest03) 78 79 set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 80 81 if(DEFINED PACKAGE_FIND_FILE) 82 include(${PACKAGE_FIND_FILE}) 83 endif() 84 85 include_directories(${NATIVERENDER_ROOT_PATH} 86 ${NATIVERENDER_ROOT_PATH}/include) 87 88 add_library(entry SHARED napi_init.cpp) 89 target_link_libraries(entry PUBLIC libace_napi.z.so libhitrace_ndk.z.so libhilog_ndk.z.so) 90 ``` 91 923. In the **entry > src > main > cpp > napi_init.cpp** file, use HiTraceChain to trace multi-thread tasks. The sample code is as follows: 93 94 ```cpp 95 #include <thread> 96 97 #include "hilog/log.h" 98 #include "hitrace/trace.h" 99 #include "napi/native_api.h" 100 101 #undef LOG_TAG 102 #define LOG_TAG "testTag" 103 104 void Print2(HiTraceId id) 105 { 106 // Set a HiTraceId for the thread. 107 OH_HiTrace_SetId(&id); 108 // Generate a spanId. 109 id = OH_HiTrace_CreateSpan(); 110 // Set a HiTraceId with the spanId for the thread. 111 OH_HiTrace_SetId(&id); 112 OH_LOG_INFO(LogType::LOG_APP, "Print2"); 113 // End the distributed tracing of the thread. This functionality is the same as that of OH_HiTrace_EndChain(). 114 OH_HiTrace_ClearId(); 115 OH_LOG_INFO(LogType::LOG_APP, "Print2, HiTraceChain end"); 116 } 117 118 void Print1(HiTraceId id) 119 { 120 // Set a HiTraceId for the thread. 121 OH_HiTrace_SetId(&id); 122 // Generate a spanId. 123 id = OH_HiTrace_CreateSpan(); 124 // Set a HiTraceId with the spanId for the thread. 125 OH_HiTrace_SetId(&id); 126 OH_LOG_INFO(LogType::LOG_APP, "Print1"); 127 std::thread(Print2, OH_HiTrace_GetId()).detach(); 128 // End the distributed tracing of the thread. 129 OH_HiTrace_EndChain(); 130 OH_LOG_INFO(LogType::LOG_APP, "Print1, HiTraceChain end"); 131 } 132 133 static napi_value Add(napi_env env, napi_callback_info info) 134 { 135 // Start distributed tracing when the task starts. 136 HiTraceId hiTraceId = OH_HiTrace_BeginChain("testTag: hiTraceChain begin", HiTrace_Flag::HITRACE_FLAG_DEFAULT); 137 // Check whether the generated hiTraceId is valid. If yes, a HiLog log is generated. 138 if (OH_HiTrace_IsIdValid(&hiTraceId)) { 139 OH_LOG_INFO(LogType::LOG_APP, "HiTraceId is valid"); 140 } 141 // Enable the HITRACE_FLAG_INCLUDE_ASYNC flag, indicating that HiTraceId is automatically transferred in the asynchronous mechanism supported by the system. 142 OH_HiTrace_EnableFlag(&hiTraceId, HiTrace_Flag::HITRACE_FLAG_INCLUDE_ASYNC); 143 // Check whether the HITRACE_FLAG_INCLUDE_ASYNC flag of HiTraceId is enabled. If yes, set the HiTraceId to the thread TLS. 144 if (OH_HiTrace_IsFlagEnabled(&hiTraceId, HiTrace_Flag::HITRACE_FLAG_INCLUDE_ASYNC)) { 145 OH_HiTrace_SetId(&hiTraceId); 146 OH_LOG_INFO(LogType::LOG_APP, "HITRACE_FLAG_INCLUDE_ASYNC is enabled"); 147 } 148 size_t argc = 2; 149 napi_value args[2] = {nullptr}; 150 151 napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); 152 153 napi_valuetype valuetype0; 154 napi_typeof(env, args[0], &valuetype0); 155 156 napi_valuetype valuetype1; 157 napi_typeof(env, args[1], &valuetype1); 158 159 double value0; 160 napi_get_value_double(env, args[0], &value0); 161 162 double value1; 163 napi_get_value_double(env, args[1], &value1); 164 165 napi_value sum; 166 napi_create_double(env, value0 + value1, &sum); 167 168 // Create a thread to execute the print task and transfer the HiTraceId of the thread. 169 std::thread(Print1, OH_HiTrace_GetId()).detach(); 170 // Stop the distributed tracing when the task is complete. 171 OH_HiTrace_EndChain(); 172 OH_LOG_INFO(LogType::LOG_APP, "Add, HiTraceChain end"); 173 174 return sum; 175 } 176 177 EXTERN_C_START 178 static napi_value Init(napi_env env, napi_value exports) 179 { 180 napi_property_descriptor desc[] = { 181 { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr } 182 }; 183 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 184 return exports; 185 } 186 EXTERN_C_END 187 188 static napi_module demoModule = { 189 .nm_version = 1, 190 .nm_flags = 0, 191 .nm_filename = nullptr, 192 .nm_register_func = Init, 193 .nm_modname = "entry", 194 .nm_priv = ((void*)0), 195 .reserved = { 0 }, 196 }; 197 198 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) 199 { 200 napi_module_register(&demoModule); 201 } 202 ``` 203 204 In the **entry > src > main > ets > pages > Index.ets** file, call the **Add** method in the button click event. The sample code is as follows: 205 206 ```ts 207 import { hilog } from '@kit.PerformanceAnalysisKit'; 208 import testNapi from 'libentry.so'; 209 210 const DOMAIN = 0x0000; 211 212 @Entry 213 @Component 214 struct Index { 215 @State message: string = "clickTime=0"; 216 @State clickTime: number = 0; 217 218 build() { 219 Row() { 220 Column() { 221 Button(this.message) 222 .fontSize(20) 223 .margin(5) 224 .width(350) 225 .height(60) 226 .fontWeight(FontWeight.Bold) 227 .onClick(() => { 228 this.clickTime++; 229 this.message = "clickTime=" + this.clickTime; 230 hilog.info(DOMAIN, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); 231 }) 232 } 233 .width('100%') 234 } 235 .height('100%') 236 } 237 } 238 ``` 239 2404. Click the **Run** button in DevEco Studio to run the project. Then, click **clickTime=0** on the device to trigger the service logic. 241 2425. In the **Log** window of DevEco Studio, view the distributed tracing information. 243 - If **clickTime=1** is displayed on the device screen, the button is clicked once and the service logic is triggered. 244 - All HiLog logs in this example use **testTag**. You can filter logs by the keyword **testTag** to view the HiLog logs printed by the service code. 245 246 ```txt 247 06-05 21:26:01.006 9944-9944 C02D33/com.exa...tion/HiTraceC com.examp...lication I [a92ab19ae90197d 0 0]HiTraceBegin name:testTag: hiTraceChain begin flags:0x00. 248 06-05 21:26:01.006 9944-9944 A00000/com.exa...ation/testTag com.examp...lication I [a92ab19ae90197d 0 0]HiTraceId is valid 249 06-05 21:26:01.006 9944-9944 A00000/com.exa...ation/testTag com.examp...lication I [a92ab19ae90197d 0 0]HITRACE_FLAG_INCLUDE_ASYNC is enabled 250 06-05 21:26:01.007 9944-9944 A00000/com.exa...ation/testTag com.examp...lication I Add, HiTraceChain end 251 06-05 21:26:01.007 9944-9944 A00000/com.exa...ation/testTag com.examp...lication I Test NAPI 2 + 3 = 5 252 06-05 21:26:01.007 9944-13961 A00000/com.exa...ation/testTag com.examp...lication I [a92ab19ae90197d 2544fdb 0]Print1 253 06-05 21:26:01.007 9944-13961 A00000/com.exa...ation/testTag com.examp...lication I Print1, HiTraceChain end 254 06-05 21:26:01.008 9944-13962 A00000/com.exa...ation/testTag com.examp...lication I [a92ab19ae90197d 236699a 2544fdb]Print2 255 06-05 21:26:01.008 9944-13962 A00000/com.exa...ation/testTag com.examp...lication I Print2, HiTraceChain end 256 ``` 257 258 - The **[chainId spanId parentSpanId]** information added before the HiLog log is **HiTraceId** information. For example, **[a92ab19ae90197d 236699a 2544fdb]** indicates that the trace chain ID (**chainId**) is **a92ab19ae90197d**, the span ID (**spanId**) is **236699a**, and the parent span ID (**parentSpanId**) is **2544fdb**. 259 - Transfer the **HiTraceId**, create a **spanId**, and set it to the child thread created by **std::thread**. The HiLog logs of the Print1 and Print2 services running in the child thread also carry the same trace ID **a92ab19ae90197d** as that of the main thread. 260 - After the distributed tracing is ended using **OH_HiTrace_EndChain** or **OH_HiTrace_ClearId**, the HiLog print information does not carry the **HiTraceId** information. 261