Development of Application Event Logging

Overview

A traditional log system aggregates log information generated by all applications running on the entire device, making it difficult to identify key information in the log. Therefore, an effective logging mechanism is needed to evaluate mission-critical information, for example, number of visits, number of daily active users, user operation habits, and key factors that affect application usage.

HiAppEvent is a module that provides the event logging function for applications to log the fault, statistical, security, and user behavior events reported during running. Based on event information, you will be able to analyze the running status of applications.

Basic Concepts

  • Logging

    Logs changes caused by user operations to provide service data for development, product, and O&M analysis.

Event Design Specifications

  • Event domain: identifies the domain of an event. You are advised to set this parameter to the service module name to differentiate service modules.
  • Event name: specifies the name of an event. You are advised to set this parameter to a specific service name to differentiate services.
  • Event type: specifies the type of an event. Four event types are supported:
    • Behavior event: used to record the daily operation behavior of a user, for example, button click and page redirection.
    • Fault event: used to locate and analyze application faults, for example, frame freezing, network disconnection, and call drop.
    • Statistical event: used to collect statistics on key application behaviors, for example, usage duration and number of visits.
    • Security event: used to record events related to application security, for example, password change and user authorization.
  • Event parameter: specifies the parameters of an event. Each event can contain a group of parameters. You are advised to set this parameter to an event attribute or event context to depict the event details.

Available APIs

The following table provides only a brief description of related APIs. For details, see HiAppEvent.

Event Logging APIs

API Description
write(info: AppEventInfo, callback: AsyncCallback<void>): void Logs application events in asynchronous mode. This API uses an asynchronous callback to return the result.
write(info: AppEventInfo): Promise<void> Logs application events in asynchronous mode. This API uses a promise to return the result.

Event Watcher APIs

API Description
addWatcher(watcher: Watcher): AppEventPackageHolder Adds an event watcher to subscribe to expected application events.
removeWatcher(watcher: Watcher): void Adds an event watcher to unsubscribe from expected application events.

Data Processor APIs

API Description
addProcessor(processor: Processor): number Adds a data processor for reporting events.
removeProcessor(id: number): void Removes a data processor.

User ID APIs

API Description
setUserId(name: string, value: string): void Sets a user ID. The data processor can carry the user ID when reporting an event.
getUserId(name: string): string Obtains the user ID that has been set.

User Property APIs

API Description
setUserProperty(name: string, value: string): void Sets user properties. The data processor can carry user properties when reporting events.
getUserProperty(name: string): string Obtains the user properties that have been set.

Event Subscription

Subscribing to Application Events

The following example illustrates how to log and subscribe to button touch events of users.

  1. Create an ArkTS application project. In the displayed Project window, choose entry > src > main > ets > entryability > EntryAbility.ts, and double-click EntryAbility.ets. Then, add an event watcher to onCreate to subscribe to button touch events. The complete sample code is as follows:

    import AbilityConstant from '@ohos.app.ability.AbilityConstant';
    import hiAppEvent from '@ohos.hiviewdfx.hiAppEvent';
    import hilog from '@ohos.hilog';
    import UIAbility from '@ohos.app.ability.UIAbility';
    import Want from '@ohos.app.ability.Want';
    import window from '@ohos.window';
    
    export default class EntryAbility extends UIAbility {
      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
    
        hiAppEvent.addWatcher({
          // Add a watcher. You can customize the watcher name. The system identifies different watchers based on their names.
          name: "watcher1",
          // Subscribe to application events you are interested in, for example, button touch events.
          appEventFilters: [{ domain: "button" }],
          // Set the subscription callback trigger condition. In this example, a callback is triggered if one event is logged.
          triggerCondition: { row: 1 },
          // Implement the subscription callback function to apply custom processing to the event logging data obtained through subscription.
          onTrigger: (curRow: number, curSize: number, holder: hiAppEvent.AppEventPackageHolder) => {
            // If the watcher incurs an error while it is working, return a null holder object after recording the error in the log.
            if (holder == null) {
              hilog.error(0x0000, 'testTag', "HiAppEvent holder is null");
              return;
            }
            hilog.info(0x0000, 'testTag', `HiAppEvent onTrigger: curRow=%{public}d, curSize=%{public}d`, curRow, curSize);
            let eventPkg: hiAppEvent.AppEventPackage | null = null;
            // Fetch the subscription event package based on the specified threshold (512 KB by default) until all subscription event data is fetched.
            // If all subscription event data is fetched, return a null event package object. The subscription callback process is ended.
            while ((eventPkg = holder.takeNext()) != null) {
              // Apply custom processing to the event logging data in the event package, for example, print the event logging data in the log.
              hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.packageId=%{public}d`, eventPkg.packageId);
              hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.row=%{public}d`, eventPkg.row);
              hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.size=%{public}d`, eventPkg.size);
              for (const eventInfo of eventPkg.data) {
                hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.info=%{public}s`, eventInfo);
              }
            }
          }
        });
      }
    }
    
    
  2. Choose entry > src > main > ets > pages > index.ets, and double-click index.ets. Then, add a button, and enable logging of button touch events in its onClick function. The complete sample code is as follows:

      Button("writeTest").onClick(()=>{
        // Enable event logging in the onClick function to log button touch events.
        let eventParams: Record<string, number> = { 'click_time': 100 };
        let eventInfo: hiAppEvent.AppEventInfo = {
          // Define the event domain.
          domain: "button",
          // Define the event name.
          name: "click",
          // Define the event type.
          eventType: hiAppEvent.EventType.BEHAVIOR,
          // Define event parameters.
          params: eventParams,
        };
        hiAppEvent.write(eventInfo).then(() => {
          hilog.info(0x0000, 'testTag', `HiAppEvent success to write event`)
        }).catch((err: BusinessError) => {
          hilog.error(0x0000, 'testTag', `HiAppEvent err.code: ${err.code}, err.message: ${err.message}`)
        });
      })
    
  3. Touch the run button on the IDE to run the project. Then, touch the writeTest button on the application UI to trigger logging of the button touch event.

  4. View the information printed in the Log window. If logging of the button touch event is successful, you will see a message indicating successful event logging as well as the log information specific to processing of the event logging data in the subscription callback.

    HiAppEvent success to write event
    HiAppEvent eventPkg.packageId=0
    HiAppEvent eventPkg.row=1
    HiAppEvent eventPkg.size=124
    HiAppEvent eventPkg.info={"domain_":"button","name_":"click","type_":4,"time_":1670268234523,"tz_":"+0800","pid_":3295,"tid_":3309,"click_time":100}
    

Subscribing to System Events (Crash Events)

The following describes the attributes in the crash event.

params attributes

Name Type Description
time number Event triggering time, in milliseconds.
crash_type string Crash type. The value can be JsError or NativeCrash.
foreground boolean Whether the application is in the foreground.
bundle_version string Application version.
bundle_name string Application name.
pid number Process ID of the application.
uid number User ID of the application.
uuid string User ID.
exception object Exception information. For details about JsError events, see the description of exception attributes (JsError). For details about NativeCrash events, see the description of exception attributes (NativeCrash).
hilog string[] Log information.
threads object[] Full thread call stack. For details, see the description of thread attributes. This field applies only to NativeCrash events.

exception attributes (JsError)

Name Type Description
name string Exception type.
message string Exception cause.
stack string Abnormal call stack.

exception attributes (NativeCrash)

Name Type Description
message string Exception cause.
signal object Signal information. For details, see the description of signal attributes.
thread_name string Thread name.
tid number Thread ID.
frames object[] Thread call stack. For details, see the description of frame attributes.

signal attributes

Name Type Description
signo number Signal value.
code number Signal error code.

thread attributes

Name Type Description
thread_name string Thread name.
tid number Thread ID.
frames object[] Thread call stack. For details, see the description of frame attributes.

frame attributes

Name Type Description
symbol string Function name.
file string File name.
buildId string Unique file ID.
pc string PC register address.
offset number Function offset.

The following describes how to subscribe to the crash event generated when a user clicks the button to trigger an application crash.

  1. In the Project window, choose entry > src > main > ets > entryability > EntryAbility.ets, and double-click EntryAbility.ts. Then, add an event watcher to onCreate to subscribe to system events. The complete sample code is as follows:

     hiAppEvent.addWatcher({
       // Add a watcher. You can customize the watcher name. The system identifies different watchers based on their names.
       name: "watcher2",
       // Subscribe to application events you are interested in, for example, crash events.
       appEventFilters: [
         {
           domain: hiAppEvent.domain.OS,
           names: [hiAppEvent.event.APP_CRASH]
         }
       ],
       // Implement a real-time subscription callback on your own so that you can apply custom processing to the events obtained through subscription.
       onReceive: (domain: string, appEventGroups: Array<hiAppEvent.AppEventGroup>) => {
         hilog.info(0x0000, 'testTag', `HiAppEvent onReceive: domain=${domain}`);
         for (const eventGroup of appEventGroups) {
           // Distinguish system events based on the event names in the event set.
           hilog.info(0x0000, 'testTag', `HiAppEvent eventName=${eventGroup.name}`);
           for (const eventInfo of eventGroup.appEventInfos) {
             // Apply custom processing to the event data in the event set, for example, print the event data in the log.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.domain=${eventInfo.domain}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.name=${eventInfo.name}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.eventType=${eventInfo.eventType}`);
             // Obtain the timestamp of the crash event.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}`);
             // Obtain the crash type of the crash event.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.crash_type=${eventInfo.params['crash_type']}`);
             // Obtain the foreground and background status of the crashed application.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}`);
             // Obtain the version information of the crashed application.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}`);
             // Obtain the bundle name of the crashed application.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}`);
             // Obtain the process ID of the crashed application.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.pid=${eventInfo.params['pid']}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uid=${eventInfo.params['uid']}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uuid=${eventInfo.params['uuid']}`);
             // Obtain the exception type, cause, and call stack of the crash event.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}`);
             // Obtain the log information about the crash event.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}`);
           }
         }
       }
     });
    
  2. Choose entry > src > main > ets > pages > index.ets, and double-click index.ets. Then, add a button, and construct a crash scenario in its onClick function for triggering a crash event. The complete sample code is as follows:

     Button("appCrash").onClick(()=>{
       // Construct a crash scenario in the onClick function for triggering a crash event.
       let result: object = JSON.parse("");
     })
    
  3. Touch the run button on the IDE to run the project. Then, touch the appCrash button to trigger an application crash. The application breaks down and exits.

  4. After you run the application again, view the system event processing log in the Log window.

    HiAppEvent onReceive: domain=OS
    HiAppEvent eventName=APP_CRASH
    HiAppEvent eventInfo.domain=OS
    HiAppEvent eventInfo.name=APP_CRASH
    HiAppEvent eventInfo.eventType=1
    HiAppEvent eventInfo.params.time=1701836127566
    HiAppEvent eventInfo.params.crash_type=JsError
    HiAppEvent eventInfo.params.foreground=true
    HiAppEvent eventInfo.params.bundle_version=1.0.0
    HiAppEvent eventInfo.params.bundle_name=com.example.myapplication
    HiAppEvent eventInfo.params.pid=2027
    HiAppEvent eventInfo.params.uid=20010043
    HiAppEvent eventInfo.params.uuid=...
    HiAppEvent eventInfo.params.exception={"message":"Unexpected Text in JSON\\n","name":"SyntaxError\\n","stack":"\\n    at anonymous (entry/src/main/ets/pages/Index.ets:60:34)\\n"}
    HiAppEvent eventInfo.params.hilog.size=100
    

Subscribing to System Events (Freeze Events)

The following describes the attributes in the freeze event.

params attributes

Name Type Description
time number Event triggering time, in milliseconds.
foreground boolean Whether the application is in the foreground.
bundle_version string Application version.
bundle_name string Application name.
process_name string Process name of the application.
pid number Process ID of the application.
uid number User ID of the application.
uuid string User ID.
exception object Exception information. For details, see the description of exception attributes.
hilog string[] Log information.
event_handler string[] Number of events not yet handled by the main thread.
event_handler_size_3s string Number of tasks in the task stack when the THREAD_BLOCK event lasts for 3s.
event_handler_size_6s string Number of tasks in the task stack when the THREAD_BLOCK event lasts for 6s.
peer_binder string[] Binder call information.
threads object[] Full thread call stack. For details, see the description of thread attributes.
memory object Memory information. For details, see the description of memory attributes.

exception attributes

Name Type Description
name string Exception type.
message string Exception cause.

thread attributes

Name Type Description
thread_name string Thread name.
tid number Thread ID.
frames object[] Thread call stack. For details, see the description of frame attributes.

frame attributes

Name Type Description
symbol string Function name.
file string File name.
buildId string Unique file ID.
pc string PC register address.
offset number Function offset.

memory attributes:

Name Type Description
rss number Size of the memory actually occupied by a process, in KB.
vss number Size of the virtual memory applied by a process from the system, in KB.
pss number Size of the physical memory actually used by a process, in KB.
sys_free_mem number Size of free memory, in MB.
sys_avail_mem number Size of available memory, in KB.
sys_total_mem number Total memory size, in KB.

The following describes how to subscribe to the freeze event generated when a user clicks the button to trigger an application freeze.

  1. In the Project window, choose entry > src > main > ets > entryability > EntryAbility.ets, and double-click EntryAbility.ts. Then, add an event watcher to onCreate to subscribe to system events. The complete sample code is as follows:

     hiAppEvent.addWatcher({
       // Add a watcher. You can customize the watcher name. The system identifies different watchers based on their names.
       name: "watcher3",
       // Subscribe to application events you are interested in, for example, freeze events.
       appEventFilters: [
         {
           domain: hiAppEvent.domain.OS,
           names: [hiAppEvent.event.APP_FREEZE]
         }
       ],
       // Implement a real-time subscription callback on your own so that you can apply custom processing to the events obtained through subscription.
       onReceive: (domain: string, appEventGroups: Array<hiAppEvent.AppEventGroup>) => {
         hilog.info(0x0000, 'testTag', `HiAppEvent onReceive: domain=${domain}`);
         for (const eventGroup of appEventGroups) {
           // Distinguish system events based on the event names in the event set.
           hilog.info(0x0000, 'testTag', `HiAppEvent eventName=${eventGroup.name}`);
           for (const eventInfo of eventGroup.appEventInfos) {
             // Apply custom processing to the event data in the event set, for example, print the event data in the log.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.domain=${eventInfo.domain}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.name=${eventInfo.name}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.eventType=${eventInfo.eventType}`);
             // Obtain the timestamp of the freeze event.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}`);
             // Obtain the foreground and background status of the freeze application.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}`);
             // Obtain the version information of the freeze application.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}`);
             // Obtain the bundle name of the freeze application.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}`);
             // Obtain the process name of the freeze application.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.process_name=${eventInfo.params['process_name']}`);
             // Obtain the process ID of the freeze application.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.pid=${eventInfo.params['pid']}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uid=${eventInfo.params['uid']}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uuid=${eventInfo.params['uuid']}`);
             // Obtain the exception type and cause of the freeze event.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}`);
             // Obtain the log information about the freeze event.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}`);
             // Obtain the number of messages that are not yet processed by the main thread when the freeze event occurs.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.event_handler.size=${eventInfo.params['event_handler'].length}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.event_handler_size_3s=${eventInfo.params['event_handler_size_3s']}`);
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.event_handler_size_6s=${eventInfo.params['event_handler_size_6s']}`);
             // Obtain the synchronous binder call information logged when the freeze event occurs.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.peer_binder.size=${eventInfo.params['peer_binder'].length}`);
             // Obtain the full thread call stack logged when the freeze event occurs.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.threads.size=${eventInfo.params['threads'].length}`);
             // Obtain the memory information logged when the freeze event occurs.
             hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.memory=${JSON.stringify(eventInfo.params['memory'])}`);
           }
         }
       }
     });
    
  2. Choose entry > src > main > ets > pages > index.ets, and double-click index.ets. Then, add a button, and construct a freeze scenario in its onClick function for triggering a freeze event. The complete sample code is as follows:

     Button("appFreeze").onClick(()=>{
       // Construct a freeze scenario in the onClick function for triggering a freeze event.
       setTimeout(() => {
         while (true) {}
       }, 1000)
     })
    
  3. Touch the run button on the IDE to run the project. Then, touch the appFreeze button to trigger an application freeze.

  4. After the application recovers, view the system event processing log in the Log window.

    HiAppEvent onReceive: domain=OS
    HiAppEvent eventName=APP_FREEZE
    HiAppEvent eventInfo.domain=OS
    HiAppEvent eventInfo.name=APP_FREEZE
    HiAppEvent eventInfo.eventType=1
    HiAppEvent eventInfo.params.time=1702553728887
    HiAppEvent eventInfo.params.foreground=true
    HiAppEvent eventInfo.params.bundle_version=1.0.0
    HiAppEvent eventInfo.params.bundle_name=com.example.myapplication
    HiAppEvent eventInfo.params.process_name=com.example.myapplication
    HiAppEvent eventInfo.params.pid=2978
    HiAppEvent eventInfo.params.uid=20010043
    HiAppEvent eventInfo.params.uuid=...
    HiAppEvent eventInfo.params.exception={"message":"App main thread is not response!","name":"THREAD_BLOCK_6S"}
    HiAppEvent eventInfo.params.hilog.size=7
    HiAppEvent eventInfo.params.event_handler.size=3
    HiAppEvent eventInfo.params.event_handler_size_3s=2
    HiAppEvent eventInfo.params.event_handler_size_6s=3
    HiAppEvent eventInfo.params.peer_binder.size=0
    HiAppEvent eventInfo.params.threads.size=22
    HiAppEvent eventInfo.params.memory={"pss":0,"rss":0,"sys_avail_mem":947700,"sys_free_mem":441064,"sys_total_mem":1992724,"vss":0}
    

Event Reporting

The following describes how to log a user click event and enable the data processor to report the event.

  1. Choose entry > src > main > ets > pages > index.ets, and double-click index.ets. Then, add a button, and enable addition of a data processor in its onClick function. analytics_demo is the data processor library preset in the device. For details, see HiAppEvent Data Processor Library. The complete sample code is as follows:

    import { BusinessError } from '@ohos.base'
    import hiAppEvent from '@ohos.hiviewdfx.hiAppEvent'
    import hilog from '@ohos.hilog'
    
    @Entry
    @Component
    struct Index {
      @State message: string = 'Hello World'
    
      processorId: number = -1
    
      build() {
        Row() {
          Column() {
            Text(this.message)
              .fontSize(50)
              .fontWeight(FontWeight.Bold)
    
            Button("addProcessorTest").onClick(()=>{
              // Enable addition of a data processor in the onClick function.
              let eventConfig: hiAppEvent.AppEventReportConfig = {
                domain: 'button',
                name: 'click',
                isRealTime: true
              };
              let processor: hiAppEvent.Processor = {
                name: 'analytics_demo',
                debugMode: true,
                routeInfo: 'CN',
                onStartReport: true,
                onBackgroundReport: true,
                periodReport: 10,
                batchReport: 5,
                userIds: ['testUserIdName'],
                userProperties: ['testUserPropertyName'],
                eventConfigs: [eventConfig]
              };
              this.processorId = hiAppEvent.addProcessor(processor);
            })
          }
          .width('100%')
        }
        .height('100%')
      }
    }
    
  2. Choose entry > src > main > ets > pages > index.ets, and double-click index.ets. Then, add a button, and enable addition and viewing of user IDs to its onClick function. The complete sample code is as follows:

      Button("userIdTest").onClick(()=>{
        // Set the user ID in the onClick function.
        hiAppEvent.setUserId('testUserIdName', '123456');
    
        // Obtain the user ID set in the onClick function.
        let userId = hiAppEvent.getUserId('testUserIdName');
        hilog.info(0x0000, 'testTag', `userId: ${userId}`)
      })
    
  3. Choose entry > src > main > ets > pages > index.ets, and double-click index.ets. Then, add a button, and enable addition and viewing of user properties to its onClick function. The complete sample code is as follows:

      Button("userPropertyTest").onClick(()=>{
        // Set the user ID in the onClick function.
        hiAppEvent.setUserProperty('testUserPropertyName', '123456');
    
        // Obtain the user ID set in the onClick function.
        let userProperty = hiAppEvent.getUserProperty('testUserPropertyName');
        hilog.info(0x0000, 'testTag', `userProperty: ${userProperty}`)
      })
    
  4. Choose entry > src > main > ets > pages > index.ets, and double-click index.ets. Then, add a button, and enable logging of button touch events in its onClick function. The complete sample code is as follows:

      Button("writeTest").onClick(()=>{
        // Enable event logging in the onClick function to log button touch events.
        let eventParams: Record<string, number> = { 'click_time': 100 };
        let eventInfo: hiAppEvent.AppEventInfo = {
          // Define the event domain.
          domain: "button",
          // Define the event name.
          name: "click",
          // Define the event type.
          eventType: hiAppEvent.EventType.BEHAVIOR,
          // Define event parameters.
          params: eventParams,
        };
        hiAppEvent.write(eventInfo).then(() => {
          hilog.info(0x0000, 'testTag', `HiAppEvent success to write event`)
        }).catch((err: BusinessError) => {
          hilog.error(0x0000, 'testTag', `HiAppEvent err.code: ${err.code}, err.message: ${err.message}`)
        });
      })
    
  5. Choose entry > src > main > ets > pages > index.ets, and double-click index.ets. Then, add a button, and enable removal of the data processor (the one created in step 2) in its onClick function. The complete sample code is as follows:

      Button("removeProcessorTest").onClick(()=>{
        // Enable removal of the data processor in the onClick function.
        hiAppEvent.removeProcessor(this.processorId);
      })
    
  6. Touch the run button on the IDE to run the project. Then, touch the addProcessorTest, userIdTest, userPropertyTest, writeTest, and removeProcessorTest buttons respectively to trigger event reporting.

    Once the event handler receives the event data, you can view the user click event log information in the Log window.

    HiAppEvent success to write event