• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Subscribing to Crash Events (C/C++)
2
3## Available APIs
4
5For details about how to use the APIs (such as parameter usage restrictions and value ranges), see [HiAppEvent](../reference/apis-performance-analysis-kit/_hi_app_event.md#hiappevent).
6
7> **NOTE**
8>
9> The C/C++ APIs can be used to subscribe to JsError and NativeCrash events.
10
11**Subscription APIs**
12
13| API                                                      | Description                                        |
14| ------------------------------------------------------------ | -------------------------------------------- |
15| int OH_HiAppEvent_AddWatcher(HiAppEvent_Watcher \*watcher)   | Adds a watcher to listen for application events.|
16| int OH_HiAppEvent_RemoveWatcher (HiAppEvent_Watcher \*watcher) | Removes a watcher to unsubscribe from application events.|
17
18## How to Develop
19
20The following describes how to subscribe to the crash event triggered by a button click.
21
221. Create a native C++ project and import the **jsoncpp** file to the project. The directory structure is as follows:
23
24   ```yml
25   entry:
26     src:
27       main:
28         cpp:
29           - json:
30               - json.h
31               - json-forwards.h
32           - types:
33               libentry:
34                 - index.d.ts
35           - CMakeLists.txt
36           - napi_init.cpp
37           - jsoncpp.cpp
38         ets:
39           - entryability:
40               - EntryAbility.ets
41           - pages:
42               - Index.ets
43   ```
44
452. In the **CMakeLists.txt** file, add the source file and dynamic libraries.
46
47   ```cmake
48   # Add the jsoncpp.cpp file, which is used to parse the JSON strings in the subscription events.
49   add_library(entry SHARED napi_init.cpp jsoncpp.cpp)
50   # Add libhiappevent_ndk.z.so and libhilog_ndk.z.so (log output).
51   target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libhiappevent_ndk.z.so)
52   ```
53
543. Import the dependency files to the **napi_init.cpp** file, and define **LOG_TAG**.
55
56   ```c++
57   #include "napi/native_api.h"
58   #include "json/json.h"
59   #include "hilog/log.h"
60   #include "hiappevent/hiappevent.h"
61
62   #undef LOG_TAG
63   #define LOG_TAG "testTag"
64   ```
65
664. Subscribe to system events.
67
68   - Watcher of the onReceive type:
69
70     In the **napi_init.cpp** file, define the methods related to the watcher of the onReceive type.
71
72     ```c++
73     // Define a variable to cache the pointer to the created watcher.
74     static HiAppEvent_Watcher *systemEventWatcher;
75
76     static void OnReceive(const char *domain, const struct HiAppEvent_AppEventGroup *appEventGroups, uint32_t groupLen) {
77         for (int i = 0; i < groupLen; ++i) {
78             for (int j = 0; j < appEventGroups[i].infoLen; ++j) {
79                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", appEventGroups[i].appEventInfos[j].domain);
80                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", appEventGroups[i].appEventInfos[j].name);
81                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", appEventGroups[i].appEventInfos[j].type);
82                 if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 &&
83                     strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_APP_CRASH) == 0) {
84                     Json::Value params;
85                     Json::Reader reader(Json::Features::strictMode());
86                     Json::FastWriter writer;
87                     if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) {
88                         auto time = params["time"].asInt64();
89                         auto crashType = params["crash_type"].asString();
90                         auto foreground = params["foreground"].asBool();
91                         auto bundleVersion = params["bundle_version"].asString();
92                         auto bundleName = params["bundle_name"].asString();
93                         auto pid = params["pid"].asInt();
94                         auto uid = params["uid"].asInt();
95                         auto uuid = params["uuid"].asString();
96                         auto exception = writer.write(params["exception"]);
97                         auto hilogSize = params["hilog"].size();
98                         auto externalLog = writer.write(params["external_log"]);
99                         auto logOverLimit = params["log_over_limit"].asBool();
100                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time);
101                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.crash_type=%{public}s", crashType.c_str());
102                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.foreground=%{public}d", foreground);
103                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", bundleVersion.c_str());
104                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str());
105                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid);
106                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid);
107                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uuid=%{public}s", uuid.c_str());
108                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.exception=%{public}s", exception.c_str());
109                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.hilog.size=%{public}d", hilogSize);
110                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", externalLog.c_str());
111                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", logOverLimit);
112                     }
113                 }
114             }
115         }
116     }
117
118     static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
119         // Set the watcher name. The system identifies different watchers based on their names.
120         systemEventWatcher = OH_HiAppEvent_CreateWatcher("onReceiverWatcher");
121         // Set the event to watch to EVENT_APP_CRASH.
122         const char *names[] = {EVENT_APP_CRASH};
123         // Add the events to watch, for example, system events.
124         OH_HiAppEvent_SetAppEventFilter(systemEventWatcher, DOMAIN_OS, 0, names, 1);
125         // Set the implemented callback. After receiving the event, the watcher immediately triggers the OnReceive callback.
126         OH_HiAppEvent_SetWatcherOnReceive(systemEventWatcher, OnReceive);
127         // Add a watcher to listen for the specified event.
128         OH_HiAppEvent_AddWatcher(systemEventWatcher);
129         return {};
130     }
131     ```
132
133   - Watcher of the onTrigger type:
134
135     In the **napi_init.cpp** file, define the methods related to the watcher of the OnTrigger type.
136
137     ```c++
138     // Define a variable to cache the pointer to the created watcher.
139     static HiAppEvent_Watcher *systemEventWatcher;
140
141     // Implement the callback function used to return the listened events. The content pointed to by the events pointer is valid only in this function.
142     static void OnTake(const char *const *events, uint32_t eventLen) {
143         Json::Reader reader(Json::Features::strictMode());
144         Json::FastWriter writer;
145         for (int i = 0; i < eventLen; ++i) {
146             Json::Value eventInfo;
147             if (reader.parse(events[i], eventInfo)) {
148                 auto domain =  eventInfo["domain_"].asString();
149                 auto name = eventInfo["name_"].asString();
150                 auto type = eventInfo["type_"].asInt();
151                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", domain.c_str());
152                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", name.c_str());
153                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", type);
154                 if (domain ==  DOMAIN_OS && name == EVENT_APP_CRASH) {
155                     auto time = eventInfo["time"].asInt64();
156                     auto crashType = eventInfo["crash_type"].asString();
157                     auto foreground = eventInfo["foreground"].asBool();
158                     auto bundleVersion = eventInfo["bundle_version"].asString();
159                     auto bundleName = eventInfo["bundle_name"].asString();
160                     auto pid = eventInfo["pid"].asInt();
161                     auto uid = eventInfo["uid"].asInt();
162                     auto uuid = eventInfo["uuid"].asString();
163                     auto exception = writer.write(eventInfo["exception"]);
164                     auto hilogSize = eventInfo["hilog"].size();
165                     auto externalLog = writer.write(eventInfo["external_log"]);
166                     auto logOverLimit = eventInfo["log_over_limit"].asBool();
167                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time);
168                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.crash_type=%{public}s", crashType.c_str());
169                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.foreground=%{public}d", foreground);
170                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", bundleVersion.c_str());
171                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str());
172                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid);
173                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid);
174                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uuid=%{public}s", uuid.c_str());
175                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.exception=%{public}s", exception.c_str());
176                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.hilog.size=%{public}d", hilogSize);
177                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", externalLog.c_str());
178                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", logOverLimit);
179                 }
180             }
181         }
182     }
183
184     // Implement the subscription callback function to apply custom processing to the obtained event logging data.
185     static void OnTrigger(int row, int size) {
186         // After the callback is received, obtain the specified number of received events.
187         OH_HiAppEvent_TakeWatcherData(systemEventWatcher, row, OnTake);
188     }
189
190     static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
191         // Set the watcher name. The system identifies different watchers based on their names.
192         systemEventWatcher = OH_HiAppEvent_CreateWatcher("onTriggerWatcher");
193         // Set the event to watch to EVENT_APP_CRASH.
194         const char *names[] = {EVENT_APP_CRASH};
195         // Add the events to watch, for example, system events.
196         OH_HiAppEvent_SetAppEventFilter(systemEventWatcher, DOMAIN_OS, 0, names, 1);
197         // Set the implemented callback function. The callback function will be triggered when the conditions set by OH_HiAppEvent_SetTriggerCondition are met.
198         OH_HiAppEvent_SetWatcherOnTrigger(systemEventWatcher, OnTrigger);
199         // Set the conditions for triggering the subscription callback. For example, trigger this onTrigger callback when the number of new event logs is 1.
200         OH_HiAppEvent_SetTriggerCondition(systemEventWatcher, 1, 0, 0);
201         // Add a watcher to listen for the specified event.
202         OH_HiAppEvent_AddWatcher(systemEventWatcher);
203         return {};
204     }
205     ```
206
2075. Register **RegisterWatcher** as an ArkTS API.
208
209   In the **napi_init.cpp** file, register **RegisterWatcher** as an ArkTS API.
210
211   ```c++
212   static napi_value Init(napi_env env, napi_value exports)
213   {
214       napi_property_descriptor desc[] = {
215           { "registerWatcher", nullptr, RegisterWatcher, nullptr, nullptr, nullptr, napi_default, nullptr }
216       };
217       napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
218       return exports;
219   }
220   ```
221
222   In the **index.d.ts** file, define ArkTS APIs.
223
224   ```typescript
225   export const registerWatcher: () => void;
226   ```
227
2286. In the **EntryAbility.ets** file, add the following API to **onCreate()**.
229
230   ```typescript
231   // Import the dependent module.
232   import testNapi from 'libentry.so'
233
234   // Add the API to onCreate().
235   // Register the system event watcher at startup.
236   testNapi.registerWatcher();
237   ```
238
2397. In the **Index.ets** file, add a button to trigger the crash event.
240
241   ```typescript
242   Button("appCrash").onClick(() => {
243     JSON.parse("");
244   })
245   ```
246
2478. In DevEco Studio, click the **Run** button to run the project. Then, click the **appCrash** button to trigger a crash event. After a crash occurs, the system uses different stack backtracking methods to generate crash logs based on the crash type (JsError or NativeCrash) and then invokes callback. The NativeCrash stack backtracking takes about 2s. In practice, the duration depends on the number of service threads and the duration of inter-process communication. JsError triggers in-process stack backtracking, and NativeCrash triggers out-of-process stack backtracking. Therefore, NativeCrash stack backtracking is more time-consuming than JsError stack backtracking. You can subscribe to crash events so that the stack backtracking result is asynchronously reported without blocking the current service.
248
2499. If the application does not capture the crash event, the application exits after the system crashes. When the application is restarted, HiAppEvent reports the crash event to the registered watcher.
250<br>If the application captures the crash event. HiAppEvent reports the event before the application exits in the following scenarios:
251<br>&emsp;&emsp;Scenario 1: The application does not exit during exception handling. For example, when [errorManger.on](../reference/apis-ability-kit/js-apis-app-ability-errorManager.md#errormanageronerror) is used to capture JsError, the application registers the NativeCrash signal processing function and does not exit.<br>&emsp;&emsp;Scenario 2: Exception handling takes a long time, and the application exit time is delayed.
252<br>After HiAppEvent reports the event, you can view the processing logs of the system event data in the **Log** window.
253
254   ```text
255   HiAppEvent eventInfo.domain=OS
256   HiAppEvent eventInfo.name=APP_CRASH
257   HiAppEvent eventInfo.eventType=1
258   HiAppEvent eventInfo.params.time=1502032265088
259   HiAppEvent eventInfo.params.crash_type=JsError
260   HiAppEvent eventInfo.params.foreground=1
261   HiAppEvent eventInfo.params.bundle_version=1.0.0
262   HiAppEvent eventInfo.params.bundle_name=com.example.myapplication
263   HiAppEvent eventInfo.params.pid=19237
264   HiAppEvent eventInfo.params.uid=20010043
265   HiAppEvent eventInfo.params.uuid=cc0f062e1b28c1fd2c817fafab5e8ca3207925b4bdd87c43ed23c60029659e01
266   HiAppEvent eventInfo.params.exception={"message":"Unexpected Text in JSON","name":"SyntaxError","stack":"at anonymous (entry/src/main/ets/pages/Index.ets:16:11)"}
267   HiAppEvent eventInfo.params.hilog.size=110
268   HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_CRASH_1502032265211_19237.log"]
269   HiAppEvent eventInfo.params.log_over_limit=0
270   ```
271
27210. Remove the event watcher.
273
274    ```c++
275    static napi_value RemoveWatcher(napi_env env, napi_callback_info info) {
276        // Remove the watcher.
277        OH_HiAppEvent_RemoveWatcher(systemEventWatcher);
278        return {};
279    }
280    ```
281
28211. Destroy the event watcher.
283
284    ```c++
285    static napi_value DestroyWatcher(napi_env env, napi_callback_info info) {
286        // Destroy the created watcher and set systemEventWatcher to nullptr.
287        OH_HiAppEvent_DestroyWatcher(systemEventWatcher);
288        systemEventWatcher = nullptr;
289        return {};
290    }
291    ```
292