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<void>): void | Unregisters an observer in callback mode. The number is the SN of the registered observer.| 26| off(type: "error", observerId: number): Promise<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