• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Development of Error Manager
2
3<!--Kit: Performance Analysis Kit-->
4<!--Subsystem: HiviewDFX-->
5<!--Owner: @rr_cn-->
6<!--Designer: @peterhuangyu-->
7<!--Tester: @gcw_KuLfPSbe-->
8<!--Adviser: @foryourself-->
9
10## Overview
11
12If coding specification issues or errors exist in the code of an application, the application may encounter unexpected errors, for example, uncaught exceptions, while it is running. In such a case, the application may exit unexpectedly. Error logs, however, are usually stored on users' local storage devices, making it inconvenient to locate faults. With the APIs provided by the errorManager module, the related errors and logs will be reported to your service platform for fault locating before application exits.
13
14After the errorManager APIs are used to listen for exceptions and errors, the application does not exit. You are advised to add the synchronous exit operation after the callback is executed. If you only want to obtain error logs, you are advised to use [HiAppEvent](hiappevent-intro.md) to subscribe to events.
15
16## Available APIs
17
18The errorManager APIs are provided by the [@ohos.app.ability.errorManager (Error Observation Management)](../reference/apis-ability-kit/js-apis-app-ability-errorManager.md) module. You can import the APIs by referring to [How to Develop](#how-to-develop).
19
20**errorManager APIs**
21
22| API| Description|
23| -------- | -------- |
24| on(type: "error", observer: ErrorObserver): number | Registers an observer for application errors. A callback will be invoked when an application error is detected. This API works in a synchronous manner. The return value is the serial number (SN) of the registered observer.|
25| off(type: "error", observerId: number, callback: AsyncCallback&lt;void>): void | Unregisters an observer in callback mode. The number is the SN of the registered observer.|
26| off(type: "error", observerId: number): Promise&lt;void> | Unregisters an observer in promise mode. The number is the SN of the registered observer.|
27| on(type: 'globalErrorOccurred', observer: GlobalObserver): void | Registers a global observer for process errors. This is a synchronous API. When the system detects an application exception, the observer is called. (**Recommended**)<br>Note: This API is supported since API version 18.|
28| off(type: 'globalErrorOccurred', observer?: GlobalObserver): void | Unregisters an observer in callback mode. (**Recommended**)<br>Note: This API is supported since API version 18.|
29| on(type: 'globalUnhandledRejectionDetected', observer: GlobalObserver): void | Registers a global observer for process errors. This is a synchronous API. When the system detects an application promise exception, the observer is called. (**Recommended**)<br>Note: This API is supported since API version 18.|
30| off(type: 'globalUnhandledRejectionDetected', observer?: GlobalObserver): void | Unregisters an observer in callback mode. (**Recommended**)<br>Note: This API is supported since API version 18.|
31| on(type: 'loopObserver', timeout: number, observer: LoopObserver): void | Registers an observer for the message processing duration of the main thread. A callback will be invoked if a main thread jank event occurs.<br>This API can be called only in the main thread. A new observer will overwrite the previous one.|
32| off(type: 'loopObserver', observer?: LoopObserver): void | Unregisters an observer for the message processing duration of the main thread in LoopObserver mode.|
33| on(type: 'freeze', observer: FreezeObserver): void | Registers an observer for the main thread freeze event of the application. This API can be called only in the main thread. A new observer will overwrite the previous one.|
34| off(type: 'freeze', observer?: FreezeObserver): void | Unregisters an observer for the message processing duration of the main thread in FreezeObserver mode.<br>Note: This API is supported since API version 18.|
35
36When an asynchronous callback is used, the return value can be processed directly in the callback.
37When a promise is used, the return value can also be processed in the promise. For details about the result codes, see [Result Codes for Unregistering an Observer](#result-codes-for-unregistering-an-observer).
38
39**ErrorObserver APIs**
40
41| API| Description|
42| -------- | -------- |
43| onUnhandledException(errMsg: string): void | Called when an uncaught exception is reported after the application is registered.|
44| onException?(errObject: Error): void | Called when an application exception is reported to the JavaScript layer after the application is registered.|
45
46**LoopObserver APIs**
47
48| API| Description|
49| -------- | -------- |
50| onLoopTimeOut?(timeout: number): void | Called when the message processing of the main thread times out.|
51
52### Result Codes for Unregistering an Observer
53
54| Result Code| Description|
55| -------- | -------- |
56| 0 | Normal.|
57| -1 | Input **number** not exist.|
58| -2 | Invalid parameter.|
59
60## How to Develop
61
62> **NOTE**
63>
64> You are advised to add a synchronous exit operation at the end of the exception callback to prevent multiple exception callbacks.
65
66### Listening for a Single Thread
67
68```ts
69import { AbilityConstant, errorManager, UIAbility, Want } from '@kit.AbilityKit';
70import { window } from '@kit.ArkUI';
71import { process } from '@kit.ArkTS';
72
73let registerId = -1;
74let callback: errorManager.ErrorObserver = {
75    onUnhandledException: (errMsg) => {
76        console.info(errMsg);
77    },
78    onException: (errorObj) => {
79        console.info('onException, name: ', errorObj.name);
80        console.info('onException, message: ', errorObj.message);
81        if (typeof(errorObj.stack) == 'string') {
82            console.info('onException, stack: ', errorObj.stack);
83        }
84        // After the callback is executed, exit the process synchronously to avoid multiple exceptions.
85        let pro = new process.ProcessManager();
86        pro.exit(0);
87    }
88}
89
90let abilityWant: Want;
91
92export default class EntryAbility extends UIAbility {
93    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
94        console.info("[Demo] EntryAbility onCreate");
95        registerId = errorManager.on("error", callback);
96        abilityWant = want;
97    }
98
99    onDestroy() {
100        console.info("[Demo] EntryAbility onDestroy");
101        errorManager.off("error", registerId, (result) => {
102            console.info("[Demo] result " + result.code + ";" + result.message);
103        });
104    }
105
106    onWindowStageCreate(windowStage: window.WindowStage) {
107        // Set the main page for the created main window.
108        console.info("[Demo] EntryAbility onWindowStageCreate");
109
110        windowStage.loadContent("pages/index", (err) => {
111            if (err.code) {
112                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
113                return;
114            }
115        });
116    }
117
118    onWindowStageDestroy() {
119        // Destroy the main window and release related UI resources.
120        console.info("[Demo] EntryAbility onWindowStageDestroy");
121    }
122
123    onForeground() {
124        // Switch to the foreground.
125        console.info("[Demo] EntryAbility onForeground");
126    }
127
128    onBackground() {
129        // Switch to the background.
130        console.info("[Demo] EntryAbility onBackground");
131    }
132};
133```
134
135### Listening for Process Exceptions
136
137```ts
138import { AbilityConstant, errorManager, UIAbility, Want } from '@kit.AbilityKit';
139import { window } from '@kit.ArkUI';
140import { process } from '@kit.ArkTS';
141
142function errorFunc(observer: errorManager.GlobalError) {
143    console.info("[Demo] result name :" + observer.name);
144    console.info("[Demo] result message :" + observer.message);
145    console.info("[Demo] result stack :" + observer.stack);
146    console.info("[Demo] result instanceName :" + observer.instanceName);
147    console.info("[Demo] result instanceType :" + observer.instanceType);
148    // After the callback is executed, exit the process synchronously to avoid multiple exceptions.
149    let pro = new process.ProcessManager();
150    pro.exit(0);
151}
152
153let abilityWant: Want;
154
155export default class EntryAbility extends UIAbility {
156    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
157        console.info("[Demo] EntryAbility onCreate");
158        errorManager.on("globalErrorOccurred", errorFunc);
159        abilityWant = want;
160    }
161
162    onDestroy() {
163        console.info("[Demo] EntryAbility onDestroy");
164        errorManager.off("globalErrorOccurred", errorFunc);
165    }
166
167    onWindowStageCreate(windowStage: window.WindowStage) {
168        // Set the main page for the created main window.
169        console.info("[Demo] EntryAbility onWindowStageCreate");
170
171        windowStage.loadContent("pages/index", (err) => {
172            if (err.code) {
173                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
174                return;
175            }
176        });
177    }
178
179    onWindowStageDestroy() {
180        // Destroy the main window and release related UI resources.
181        console.info("[Demo] EntryAbility onWindowStageDestroy");
182    }
183
184    onForeground() {
185        // Switch to the foreground.
186        console.info("[Demo] EntryAbility onForeground");
187    }
188
189    onBackground() {
190        // Switch to the background.
191        console.info("[Demo] EntryAbility onBackground");
192    }
193};
194```
195
196### Listening for Process Promise Exceptions
197
198```ts
199import { AbilityConstant, errorManager, UIAbility, Want } from '@kit.AbilityKit';
200import { window } from '@kit.ArkUI';
201import { process } from '@kit.ArkTS';
202
203function promiseFunc(observer: errorManager.GlobalError) {
204    console.info("[Demo] result name :" + observer.name);
205    console.info("[Demo] result message :" + observer.message);
206    console.info("[Demo] result stack :" + observer.stack);
207    console.info("[Demo] result instanceName :" + observer.instanceName);
208    console.info("[Demo] result instanceType :" + observer.instanceType);
209    // After the callback is executed, exit the process synchronously to avoid multiple exceptions.
210    let pro = new process.ProcessManager();
211    pro.exit(0);
212}
213
214
215let abilityWant: Want;
216
217export default class EntryAbility extends UIAbility {
218    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
219        console.info("[Demo] EntryAbility onCreate");
220        errorManager.on("globalUnhandledRejectionDetected", promiseFunc);
221        abilityWant = want;
222    }
223
224    onDestroy() {
225        console.info("[Demo] EntryAbility onDestroy");
226        errorManager.off("globalUnhandledRejectionDetected", promiseFunc);
227    }
228
229    onWindowStageCreate(windowStage: window.WindowStage) {
230        // Set the main page for the created main window.
231        console.info("[Demo] EntryAbility onWindowStageCreate");
232
233        windowStage.loadContent("pages/index", (err) => {
234            if (err.code) {
235                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
236                return;
237            }
238        });
239    }
240
241    onWindowStageDestroy() {
242        // Destroy the main window and release related UI resources.
243        console.info("[Demo] EntryAbility onWindowStageDestroy");
244    }
245
246    onForeground() {
247        // Switch to the foreground.
248        console.info("[Demo] EntryAbility onForeground");
249    }
250
251    onBackground() {
252        // Switch to the background.
253        console.info("[Demo] EntryAbility onBackground");
254    }
255};
256```
257
258### Listening for Main Thread Freeze Exceptions
259
260```ts
261import { AbilityConstant, errorManager, UIAbility, Want } from '@kit.AbilityKit';
262import { window } from '@kit.ArkUI';
263import { process } from '@kit.ArkTS';
264
265// Define freezeCallback.
266function freezeCallback() {
267    console.info("freezecallback");
268}
269
270
271let abilityWant: Want;
272
273export default class EntryAbility extends UIAbility {
274    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
275        console.info("[Demo] EntryAbility onCreate");
276        errorManager.on("freeze", freezeCallback);
277        abilityWant = want;
278    }
279
280    onDestroy() {
281        console.info("[Demo] EntryAbility onDestroy");
282        errorManager.off("freeze", freezeCallback);
283    }
284
285    onWindowStageCreate(windowStage: window.WindowStage) {
286        // Set the main page for the created main window.
287        console.info("[Demo] EntryAbility onWindowStageCreate");
288
289        windowStage.loadContent("pages/index", (err) => {
290            if (err.code) {
291                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
292                return;
293            }
294        });
295    }
296
297    onWindowStageDestroy() {
298        // Destroy the main window and release related UI resources.
299        console.info("[Demo] EntryAbility onWindowStageDestroy");
300    }
301
302    onForeground() {
303        // Switch to the foreground.
304        console.info("[Demo] EntryAbility onForeground");
305    }
306
307    onBackground() {
308        // Switch to the background.
309        console.info("[Demo] EntryAbility onBackground");
310    }
311};
312```
313