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