1# Using HiCollie (C/C++) 2 3HiCollie provides APIs for detecting service thread stuck and jank events and reporting service thread stuck events. 4 5## Available APIs 6| API | Description | 7| ------------------------------- | --------------------------------- | 8| OH_HiCollie_Init_StuckDetection | Registers a callback to periodically detect service thread stuck events. | 9| OH_HiCollie_Init_JankDetection | Registers a callback to detect service thread jank events. To monitor service thread jank events, you can implement two callbacks as instrumentation functions, placing them before and after the service thread processes the event. | 10| OH_HiCollie_Report | Reports service thread stuck events and generates timeout logs to help locate application timeout events. This API is used together with **OH_HiCollie_Init_StuckDetection()**, which initializes the stuck event detection at first, and then **OH_HiCollie_Report()** reports the stuck event when it occurs. | 11 12 13For details about how to use the APIs (such as parameter usage restrictions and value ranges), see [HiCollie](../reference/apis-performance-analysis-kit/_hi_hicollie.md). 14 15## How to Develop 16The following describes how to add a button in the application and click the button to call the HiCollie APIs. 17 181. Create a native C++ project and import the **jsoncpp** file to the project. The directory structure is as follows: 19 20 ```yml 21 entry: 22 src: 23 main: 24 cpp: 25 - types: 26 libentry: 27 - index.d.ts 28 - CMakeLists.txt 29 - napi_init.cpp 30 ets: 31 - entryability: 32 - EntryAbility.ts 33 - pages: 34 - Index.ets 35 ``` 36 372. In the **CMakeLists.txt** file, add the source file and dynamic libraries. 38 39 ```cmake 40 # Add libhilog_ndk.z.so (log output). 41 target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libohhicollie.so) 42 ``` 43 443. Import the dependencies to the **napi_init.cpp** file, and define **LOG_TAG** and the test method. 45 46 ```c++ 47 # include "napi/native_api.h" 48 # include "hilog/log.h" 49 # include "hicollie/hicollie.h" 50 # include <thread> 51 # include <string> 52 # include <unistd.h> 53 # include <atomic> 54 55 # undef LOG_TAG 56 # define LOG_TAG "testTag" 57 58 static OH_HiCollie_BeginFunc beginFunc_; // Define the callback object used before the processing event. 59 static OH_HiCollie_EndFunc endFunc_; // Define the callback object used after the processing event. 60 HiCollie_DetectionParam param {.sampleStackTriggerTime = 150, .reserved = 0}; // Define the struct. 61 int64_t lastWatchTime = 0; // Record the last detection time. 62 const int64_t CHECK_INTERNAL_TIME = 3000; // Set the detection interval. 63 std::shared_ptr<std::atomic<bool>> isReport = std::make_shared<std::atomic<bool>>(false); // Set the flag for reporting stuck events. 64 int count = 0; // Record the first initialization. 65 bool needReport = false; // Set whether to report the stuck events. 66 67 // Define the callback. 68 void InitBeginFunc(const char* eventName) 69 { 70 std::string str(eventName); 71 OH_LOG_INFO(LogType::LOG_APP, "InitBeginFunc eventName: %{public}s", str.c_str()); 72 } 73 void InitEndFunc(const char* eventName) 74 { 75 std::string str(eventName); 76 OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_EndFunc eventName: %{public}s", str.c_str()); 77 } 78 // Define the callback of the subthread. 79 void TestJankDetection() 80 { 81 beginFunc_ = InitBeginFunc; // Initialize the callback. 82 endFunc_ = InitEndFunc; 83 int initResult = OH_HiCollie_Init_JankDetection(&beginFunc_, &endFunc_, param); // Initialize the function for detecting thread jank events. 84 OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Init_JankDetection: %{public}d", initResult); // Display the success result 0. 85 int count = 0; 86 while (count < 2) { 87 beginFunc_("TestBegin"); // Set the callback used to record the start time of the processing event. 88 usleep(350 * 1000); // Simulate a thread stuck event by putting the thread to sleep for 350 ms. 89 endFunc_("TestEnd"); // Set the callback used to record the end time of the processing event. 90 count++; 91 } 92 } 93 94 static napi_value TestHiCollieJankNdk(napi_env env, napi_callback_info info) 95 { 96 std::thread threadObj(TestJankDetection); // Create a subthread. 97 threadObj.join(); // Execute the callback. 98 return 0; 99 } 100 101 int64_t GetCurrentTime() 102 { 103 return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono:: 104 system_clock::now().time_since_epoch()).count(); 105 } 106 107 bool ReportEvent() 108 { 109 if ((GetCurrentTime() - lastWatchTime) > CHECK_INTERNAL_TIME) { 110 return true; 111 } 112 return false; 113 } 114 115 void TestTask() 116 { 117 if (needReport && ReportEvent()) { 118 bool temp = isReport->load(); 119 int reportResult = OH_HiCollie_Report(&temp); 120 OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Report: %{public}d", reportResult); // Return 0 if the function is initialized successfully. 121 OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Report isReport: %{public}d", temp); 122 needReport = false; 123 } 124 int64_t now = GetCurrentTime(); 125 if ((now - lastWatchTime) >= (CHECK_INTERNAL_TIME / 2)) { 126 lastWatchTime = now; 127 } 128 } 129 130 // Define the callback of the subthread. 131 void TestStuckDetection() 132 { 133 int initResult = -1; 134 if(count == 0) { 135 initResult = OH_HiCollie_Init_StuckDetection(TestTask); // Initialize the function for detecting thread stuck events. 136 OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Init_StuckDetection: %{public}d", initResult); // Display the success result 0. 137 count++; 138 } 139 } 140 static napi_value TestHiCollieStuckNdk(napi_env env, napi_callback_info info) 141 { 142 std::thread threadObj(TestStuckDetection); // Create a subthread. 143 threadObj.join(); // Execute the callback. 144 return 0; 145 } 146 ``` 147 1484. Register **TestHiCollieNdk** as an ArkTS API. 149 150 In the **napi_init.cpp** file, register **TestHiCollieNdk** as an ArkTS API. 151 152 ```c++ 153 static napi_value Init(napi_env env, napi_value exports) 154 { 155 napi_property_descriptor desc[] = { 156 { "testHiCollieJankNdk", nullptr, TestHiCollieJankNdk, nullptr, nullptr, nullptr, napi_default, nullptr }, 157 { "testHiCollieStuckNdk", nullptr, TestHiCollieStuckNdk, nullptr, nullptr, nullptr, napi_default, nullptr }}; 158 }; 159 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 160 return exports; 161 } 162 ``` 163 164 In the **index.d.ts** file, define the ArkTS API. 165 166 ```typescript 167 export const testHiCollieJankNdk: () => void; 168 export const testHiCollieStuckNdk: () => void; 169 ``` 170 1715. Edit the **Index.ets** file. 172 173 ```ts 174 import testNapi from 'libentry.so' 175 176 @Entry 177 @Component 178 struct Index { 179 @State message: string = 'Hello World' 180 181 build() { 182 Row() { 183 Column() { 184 Button("testHiCollieJankNdk") 185 .fontSize(50) 186 .fontWeight(FontWeight.Bold) 187 .onClick(testNapi.testHiCollieJankNdk);// Add a click event to trigger testHiCollieJankNdk(). 188 Button("testHiCollieStuckNdk") 189 .fontSize(50) 190 .fontWeight(FontWeight.Bold) 191 .onClick(testNapi.testHiCollieStuckNdk);// Add a click event to trigger testHiCollieStuckNdk(). 192 } 193 .width('100%') 194 } 195 .height('100%') 196 } 197 } 198 ``` 199 2006. Click the **Run** button in DevEco Studio to run the project. 201 2027. At the bottom of DevEco Studio, switch to the **Log** tab and set the filter criteria to **testTag**. 203 204 (1) Click the **testHiCollieJankNdk** button after the thread processed the event for 10s. 205 The thread timeout information of the sampling stack obtained through **OH_HiCollie_Init_JankDetection()** is displayed. 206 The path of the sampling stack: **/data/app/el2/100/log/application bundle name/watchdog/BUSSINESS_THREAD_JANK_XXX.txt.** 207 208 (2) Click the **testHiCollieStuckNdk** button. 209 The callback used for detecting stuck event is initialized through **OH_HiCollie_Init_StuckDetection()**. You can define the detection function for stuck events as required. 210 211<!--no_check-->