• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Subscribing to Crash Events (ArkTS)
2<!--Kit: Performance Analysis Kit-->
3<!--Subsystem: HiviewDFX-->
4<!--Owner: @chenshi51-->
5<!--Designer: @Maplestory-->
6<!--Tester: @yufeifei-->
7<!--Adviser: @foryourself-->
8
9## Overview
10
11The following describes how to subscribe to application crash events by using the ArkTS APIs provided by HiAppEvent. For details about how to use the APIs (such as parameter restrictions and value ranges), see [@ohos.hiviewdfx.hiAppEvent (Application Event Logging)](../reference/apis-performance-analysis-kit/js-apis-hiviewdfx-hiappevent.md).
12
13> **NOTE**
14>
15> The ArkTS APIs can be used to subscribe to the **JsError** and **NativeCrash** events.
16
17## Available APIs
18
19| API| Description|
20| -------- | -------- |
21| addWatcher(watcher: Watcher): AppEventPackageHolder | Adds a watcher to listen for application events.|
22| removeWatcher(watcher: Watcher): void | Removes a watcher to unsubscribe from application events.|
23
24## How to Develop
25
26### Adding an Event Watcher
27
28To subscribe to the crash event successfully, you are advised to add an event watcher after the application starts and before the service logic is executed.
29
30The following describes how to subscribe to the crash event triggered by a button click.
31
321. Create a native C++ project in DevEco Studio. In the **entry/src/main/ets/entryability/EntryAbility.ets** file, import the dependent modules. The sample code is as follows:
33
34   ```ts
35   import { BusinessError } from '@kit.BasicServicesKit';
36   import { hiAppEvent, hilog } from '@kit.PerformanceAnalysisKit';
37   import testNapi from 'libentry.so';
38   ```
39
402. In the **entry/src/main/ets/entryability/EntryAbility.ets** file, set the [custom parameters of the crash event](hiappevent-watcher-crash-events.md#customizing-crash-event-parameters) and [custom parameters of the crash log specifications](hiappevent-watcher-crash-events.md#customizing-crash-log-specifications) in **onCreate()**.
41
42   ```ts
43    // Build custom parameters for the crash event.
44    let params: Record<string, hiAppEvent.ParamType> = {
45      "test_data": 100,
46    };
47    // Set custom parameters for the crash event.
48    hiAppEvent.setEventParam(params, hiAppEvent.domain.OS, hiAppEvent.event.APP_CRASH).then(() => {
49      hilog.info(0x0000, 'testTag', `HiAppEvent success to set event param`);
50    }).catch((err: BusinessError) => {
51      hilog.error(0x0000, 'testTag', `HiAppEvent code: ${err.code}, message: ${err.message}`);
52    });
53
54    // Build custom parameters for crash log specifications.
55    let configParams: Record<string, hiAppEvent.ParamType> = {
56      "extend_pc_lr_printing": true, // Enable the functionality of printing the memory values near the PC and LR.
57      "log_file_cutoff_sz_bytes": 102400, // Truncate the crash log to 100 KB.
58      "simplify_vma_printing": true // Enable simplified printing of maps.
59    };
60
61    // Set the crash log configuration parameters.
62    hiAppEvent.setEventConfig(hiAppEvent.event.APP_CRASH, configParams).then(() => {
63      hilog.info(0x0000, 'testTag', `HiAppEvent success to set event config.`);
64    }).catch((err: BusinessError) => {
65      hilog.error(0x0000, 'testTag', `HiAppEvent code: ${err.code}, message: ${err.message}`);
66    });
67   ```
68
693. In the **entry/src/main/ets/entryability/EntryAbility.ets** file of the project, add the system event subscription to **onCreate()**. The sample code is as follows:
70
71   ```ts
72    let watcher: hiAppEvent.Watcher = {
73      // Set the watcher name. The system identifies different watchers based on their names.
74      name: "watcher",
75      // Add the system events to watch, for example, crash events.
76      appEventFilters: [
77        {
78          domain: hiAppEvent.domain.OS,
79          names: [hiAppEvent.event.APP_CRASH]
80        }
81      ],
82      // Implement a callback for the registered system event so that you can apply custom processing to the event data obtained.
83      onReceive: (domain: string, appEventGroups: Array<hiAppEvent.AppEventGroup>) => {
84        hilog.info(0x0000, 'testTag', `HiAppEvent onReceive: domain=${domain}`);
85        for (const eventGroup of appEventGroups) {
86          // The event name uniquely identifies a system event.
87          hilog.info(0x0000, 'testTag', `HiAppEvent eventName=${eventGroup.name}`);
88          for (const eventInfo of eventGroup.appEventInfos) {
89            // Apply custom processing to the event data obtained, for example, print the event data in the log.
90            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.domain=${eventInfo.domain}`);
91            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.name=${eventInfo.name}`);
92            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.eventType=${eventInfo.eventType}`);
93            // Obtain the timestamp of the crash event.
94            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}`);
95            // Obtain the type of the crash event.
96            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.crash_type=${eventInfo.params['crash_type']}`);
97            // Obtain the foreground and background status of the crashed application.
98            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}`);
99            // Obtain the version information of the crashed application.
100            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}`);
101            // Obtain the bundle name of the crashed application.
102            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}`);
103            // Obtain the process ID of the crashed application.
104            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.pid=${eventInfo.params['pid']}`);
105            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uid=${eventInfo.params['uid']}`);
106            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uuid=${eventInfo.params['uuid']}`);
107            // Obtain the exception type, cause, and call stack of the crash event.
108            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}`);
109            // Obtain the log information about the crash event.
110            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}`);
111            // Obtain the crash log file about the crash event.
112            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.external_log=${JSON.stringify(eventInfo.params['external_log'])}`);
113            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.log_over_limit=${eventInfo.params['log_over_limit']}`);
114            // Obtain the custom test_data of the crash event.
115            hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.test_data=${eventInfo.params['test_data']}`);
116          }
117        }
118      }
119    };
120    hiAppEvent.addWatcher(watcher);
121   ```
122
1234. Construct a crash scenario.
124
125    - Construct a **NativeCrash**
126
127      In the **entry/src/main/cpp/napi_init.cpp** file, add the following code to the **Add** method:
128
129      ```cpp
130      int *p = nullptr;
131      int a = *p; // Null pointer dereference. The program crashes.
132      ```
133
134       In the **entry/src/main/ets/pages/index.ets** file, add the **appCrash** button and construct a scenario for triggering a crash event in **onClick()**. The sample code is as follows:
135
136      ```ts
137      Button("NativeCrash").onClick(()=>{
138        // In the onClick() function, call the Add method of napi_init.cpp to trigger the NativeCrash event.
139        testNapi.add(2, 3);
140      })
141      ```
142
143    - Construct a **JsError**
144
145      In the **entry/src/main/ets/pages/index.ets** file, add the **appCrash** button and construct a scenario for triggering a crash event in **onClick()**. The sample code is as follows:
146
147      ```ts
148      Button("JsError").onClick(()=>{
149        // Construct a JsError in the button click function to trigger an application crash event.
150        let result: object = JSON.parse("");
151      })
152      ```
153
1545. In DevEco Studio, click the **Run** button to run the project. Tap the **NativeCrash** or **JsError** button on the application screen to trigger a crash event. The system generates logs based on the crash type and triggers the callback.
155
156> **NOTE**
157>
158> **JsError** collects fault information in process and triggers the callback almost instantly. **NativeCrash** collects it out of process, taking roughly 2s on average; the exact time depends on the number of service threads and IPC overhead. The collected fault information is reported asynchronously, which does not block the current service.
159
160### Checking Whether a Watcher Subscribes to Crash Events
161
162Depending on whether an application proactively captures crash events, callbacks are triggered for the crash events at different times. You need to check whether crash events are subscribed to at different times.
163
164**Application not proactively captures crash events**
165
166If the application does not proactively capture the crash exception, the application will exit after the system handles the crash. When the application restarts, HiAppEvent reports the crash event to the registered watcher to complete the callback.
167
168**Application proactively captures crash events**
169
170If an application proactively captures the crash event, a callback is triggered before the application exits. The following are examples:
171
1721. The application does not exit during exception handling.
173
174   When [errorManager.on](../reference/apis-ability-kit/js-apis-app-ability-errorManager.md#errormanageronerror) is used to capture the **JsError** event, a callback is triggered before the application exits. If the application registers the [crash signal](cppcrash-guidelines.md#crash-signals) processing function but does not exit, the **NativeCrash** event triggers a callback before the application exits.
175
1762. If the exception handling takes a long time, the application exits with a delay.
177
178In the development and debugging phase, after HiAppEvent reports a crash event and completes the callback, you can view the **JsError** event information in the **HiLog** window of DevEco Studio. The content of the **NativeCrash** event is different. For details, see [Event Fields](hiappevent-watcher-crash-events.md#fields). The following is an example of a **JsError** event:
179
180```text
181HiAppEvent onReceive: domain=OS
182HiAppEvent eventName=APP_CRASH
183HiAppEvent eventInfo.domain=OS
184HiAppEvent eventInfo.name=APP_CRASH
185HiAppEvent eventInfo.eventType=1
186HiAppEvent eventInfo.params.time=1711440614001
187HiAppEvent eventInfo.params.crash_type=JsError
188HiAppEvent eventInfo.params.foreground=true
189HiAppEvent eventInfo.params.bundle_version=1.0.0
190HiAppEvent eventInfo.params.bundle_name=com.example.myapplication
191HiAppEvent eventInfo.params.pid=2043
192HiAppEvent eventInfo.params.uid=20010043
193HiAppEvent eventInfo.params.uuid=b1e953ba0022c112e4502e28e8b3ad6d95cf3c87bae74068038f03b38ce7f66a
194HiAppEvent eventInfo.params.exception={"message":"Unexpected Text in JSON","name":"SyntaxError","stack":"at anonymous (entry/src/main/ets/pages/Index.ets:55:34)"}
195HiAppEvent eventInfo.params.hilog.size=90
196HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_CRASH_1711440614112_2043.log"]
197HiAppEvent eventInfo.params.log_over_limit=false
198HiAppEvent eventInfo.params.test_data=100
199```
200
201### Removing an Event Watcher
202
203```ts
204// Remove the event watcher to unsubscribe from events.
205hiAppEvent.removeWatcher(watcher);
206```
207<!--RP1-->
208<!--RP1End-->
209