Přeskočit na hlavní obsah

Telemetry

Telemetry

We present on this page information about the AsolTelemetryService, which is part of the @asol-platform/services. In this service, we use Microsoft application insights for app control. Our setup should currently track click events, error events, and routing events.

For this to work, you must have library @asol-platform/services in version 14.3.23. For migration, you might need to update some dependencies. If they are not directly used in your project, you can even remove them from the package.json.

  • "@microsoft/applicationinsights-angularplugin-js": "^14.0.1",
  • "@microsoft/applicationinsights-clickanalytics-js": "^3.0.7",
  • "@microsoft/applicationinsights-web": "^3.0.7"

What can be updated and set up is the data, that is collected while tracking user interactions. With each click on the <button>, <a>, <img> or other collectable element the data is collected:

{
"baseType": "EventData",
"baseData": {
"ver": 2,
"name": "Ok",
"properties": {
"baseTypeSource": "ClickEvent",
"uri": "http://localhost:4200/app/tenant/current/information",
"properties": "{\"pageTags\":{\"metaTags\":{\"viewport\":\"width=device-width, initial-scale=1\",\"msapplication-TileColor\":\"#da532c\",\"theme-color\":\"#ffffff\",\"asol:version\":\"1.0\"}}}",
"actionType": "CL",
"clickCoordinates": "1372X761",
"content": "[{\"contentName\":\"Ok\",\"new-gr-c-s-check-loaded\":\"14.1150.0\"}]",
"refUri": "http://localhost:4200/signin-oidc",
"pageName": "Portal",
"parentId": "not_specified",
"SDKName": "Angular"
},
"measurements": {
"timeToAction": 22505
}
}
}

This data snippet represents base data collected automatically. However, the name: "OK" might not be enough, as there may be many "OK" elements (in this case buttons) in one application. We have a small set of rules, on how this name is tracked.

  1. Element can have property data-id. If this is present, it is used.
  2. If data-id is not present, the default content of the element is used:
    1. For a clicked HTML <a> element, the plugin attempts to collect the value of its innerText (text) attribute. If the plugin can't find this attribute, it attempts to collect the value of its innerHtml attribute.
    2. For a clicked HTML <img> or <area> element, the plugin collects the value of its alt attribute.
    3. For all other clicked HTML elements, contentName is populated based on the following rules, which are listed in order of precedence:
      1. The value of the value attribute for the element
      2. The value of the name attribute for the element
      3. The value of the alt attribute for the element
      4. The value of the innerText attribute for the element
      5. The value of the id attribute for the element

For the parent-id the check is very similar. The rules are this:

  1. Firstly we look for the data-parentid. If it is present on the element, it is used.
  2. Secondly we look for the first parent in the HTML tree, where:
    1. data-id is defined.
    2. data-group is defined. For some elements, data-id may not be needed, in that case, you can use data-group (for example form element).
  3. If no parent is present, "not_specified" will be filled.

Other data are collected automatically. The content shows information, that is present on the element, which the user interacts with. However, you can call the method of the AsolTelemetryService:

addTelemetryProperties(properties: ApplicationInsightCustomProperties)
interface ApplicationInsightCustomProperties {
data?: { [key: string]: string };
tags?: { [key: string]: string };
}

With this method, you can add some data and tags to the collected data object. When you want to track some other events and data, which are not collected automatically (errors, click, routing, etc. ) you can use other methods of the AsolTelemetryService.

  • trackTrace()
  • trackEvent()
  • trackMetric()

Automatically collected data examples

Here we present different types of automatically collected data. There are events of the click, routing, API requests, and error handling shown.

Click events

{
"time": "2024-01-24T08:33:09.535Z",
"iKey": "00000000-0000-0000-0000-000000000000",
"name": "Microsoft.ApplicationInsights.00000000000000000000000000000000.Event",
"tags": {
"ai.user.id": "4Qs/32Y1iYVgNiC5Fcqxtb",
"ai.session.id": "wtKM9HpEOwuBShvDyHz/is",
"ai.device.id": "browser",
"ai.device.type": "Browser",
"ai.operation.name": "/app/tenant/current/information",
"ai.operation.id": "a906f3a57655479a85c309b0b6409e77",
"ai.internal.sdkVersion": "javascript:3.0.7_ClickPlugin3.0.7",
"ai.cloud.role": "Portal"
},
"data": {
"baseType": "EventData",
"baseData": {
"ver": 2,
"name": "cancel-changes",
"properties": {
"baseTypeSource": "ClickEvent",
"uri": "http://localhost:4200/app/tenant/current/information",
"properties": "{\"pageTags\":{\"metaTags\":{\"viewport\":\"width=device-width, initial-scale=1\",\"msapplication-TileColor\":\"#da532c\",\"theme-color\":\"#ffffff\",\"asol:version\":\"1.0\"}}}",
"actionType": "CL",
"clickCoordinates": "2189X716",
"content": "[{\"contentName\":\"Zrušit změny\"}]",
"refUri": "http://localhost:4200/app/tenant/current/information",
"pageName": "Portal",
"parentId": "section-buttons",
"SDKName": "Angular"
},
"measurements": {
"timeToAction": 8097
}
}
}
}

Routing events

{
"time": "2024-01-24T08:33:05.105Z",
"iKey": "00000000-0000-0000-0000-000000000000",
"name": "Microsoft.ApplicationInsights.00000000000000000000000000000000.Pageview",
"tags": {
"ai.user.id": "4Qs/32Y1iYVgNiC5Fcqxtb",
"ai.session.id": "wtKM9HpEOwuBShvDyHz/is",
"ai.device.id": "browser",
"ai.device.type": "Browser",
"ai.operation.name": "/app/tenant/current/information",
"ai.operation.id": "a906f3a57655479a85c309b0b6409e77",
"ai.internal.sdkVersion": "javascript:3.0.7_ClickPlugin3.0.7",
"ai.internal.snippet": "-",
"ai.cloud.role": "Portal"
},
"data": {
"baseType": "PageviewData",
"baseData": {
"ver": 2,
"name": "Portal",
"url": "http://localhost:4200/app/tenant/current/information",
"duration": "00:00:00.000",
"properties": {
"refUri": "http://localhost:4200/app/tenant/current/information",
"SDKName": "Angular"
},
"measurements": {
"duration": 0
},
"id": "a906f3a57655479a85c309b0b6409e77"
}
}
}

API request event

{
"time": "2024-01-24T09:12:08.279Z",
"iKey": "00000000-0000-0000-0000-000000000000",
"name": "Microsoft.ApplicationInsights.00000000000000000000000000000000.RemoteDependency",
"tags": {
"ai.user.id": "4Qs/32Y1iYVgNiC5Fcqxtb",
"ai.session.id": "wtKM9HpEOwuBShvDyHz/is",
"ai.device.id": "browser",
"ai.device.type": "Browser",
"ai.operation.name": "/app/tenant/current/information",
"ai.operation.id": "a906f3a57655479a85c309b0b6409e77",
"ai.internal.sdkVersion": "javascript:3.0.7_ClickPlugin3.0.7",
"ai.cloud.role": "Portal"
},
"data": {
"baseType": "RemoteDependencyData",
"baseData": {
"id": "|a906f3a57655479a85c309b0b6409e77.ceeaae0dce04418f.",
"ver": 2,
"name": "POST https://nqa.avaplace.com/api/asol/idp/connect/token",
"resultCode": "200",
"duration": "00:00:00.443",
"success": true,
"data": "POST https://nqa.avaplace.com/api/asol/idp/connect/token",
"target": "nqa.avaplace.com",
"type": "Ajax",
"properties": {
"HttpMethod": "POST",
"SDKName": "Angular"
},
"measurements": {}
}
}
}

Exception event

{
"time": "2024-01-24T09:15:20.318Z",
"iKey": "00000000-0000-0000-0000-000000000000",
"name": "Microsoft.ApplicationInsights.00000000000000000000000000000000.Exception",
"tags": {
"ai.user.id": "4Qs/32Y1iYVgNiC5Fcqxtb",
"ai.session.id": "wtKM9HpEOwuBShvDyHz/is",
"ai.device.id": "browser",
"ai.device.type": "Browser",
"ai.operation.name": "/app/tenant/current/information",
"ai.operation.id": "7b2bb889448248ecb3e725a4057cdc75",
"ai.internal.sdkVersion": "javascript:3.0.7_ClickPlugin3.0.7",
"ai.cloud.role": "Portal"
},
"data": {
"baseType": "ExceptionData",
"baseData": {
"ver": 2,
"exceptions": [
{
"typeName": "Error",
"message": "Uncaught (in promise): TypeError: Failed to fetch dynamically imported module: https://nqa.avaplace.com/apps/store/remoteEntry.js\nTypeError: Failed to fetch dynamically imported module: https://nqa.avaplace.com/apps/store/remoteEntry.js",
"hasFullStack": true,
"stack": "Error: Uncaught (in promise): TypeError: Failed to fetch dynamically imported module: https://nqa.avaplace.com/apps/store/remoteEntry.js\nTypeError: Failed to fetch dynamically imported module: https://nqa.avaplace.com/apps/store/remoteEntry.js\n at resolvePromise (http://localhost:4200/polyfills.js:9170:19)\n at http://localhost:4200/polyfills.js:9065:9\n at asyncGeneratorStep (http://localhost:4200/default-node_modules_asol-platform_controls_fesm2020_asol-platform-controls_mjs.js:428775:5)\n at _throw (http://localhost:4200/default-node_modules_asol-platform_controls_fesm2020_asol-platform-controls_mjs.js:428798:9)\n at ZoneDelegate.invoke (http://localhost:4200/polyfills.js:8158:158)\n at Object.onInvoke (http://localhost:4200/node_modules_angular_core_fesm2020_core_mjs.js:31743:25)\n at ZoneDelegate.invoke (http://localhost:4200/polyfills.js:8158:46)\n at Zone.run (http://localhost:4200/polyfills.js:7899:35)\n at http://localhost:4200/polyfills.js:9243:28\n at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:8191:171)\n",
"parsedStack": [
{
"level": 0,
"method": "resolvePromise",
"assembly": "at resolvePromise (http://localhost:4200/polyfills.js:9170:19)",
"fileName": "http://localhost:4200/polyfills.js",
"line": 9170
},
{
"level": 1,
"method": "asyncGeneratorStep",
"assembly": "at asyncGeneratorStep (http://localhost:4200/default-node_modules_asol-platform_controls_fesm2020_asol-platform-controls_mjs.js:428775:5)",
"fileName": "http://localhost:4200/default-node_modules_asol-platform_controls_fesm2020_asol-platform-controls_mjs.js",
"line": 428775
},
{
"level": 2,
"method": "_throw",
"assembly": "at _throw (http://localhost:4200/default-node_modules_asol-platform_controls_fesm2020_asol-platform-controls_mjs.js:428798:9)",
"fileName": "http://localhost:4200/default-node_modules_asol-platform_controls_fesm2020_asol-platform-controls_mjs.js",
"line": 428798
},
{
"level": 3,
"method": "ZoneDelegate.invoke",
"assembly": "at ZoneDelegate.invoke (http://localhost:4200/polyfills.js:8158:158)",
"fileName": "http://localhost:4200/polyfills.js",
"line": 8158
},
{
"level": 4,
"method": "Object.onInvoke",
"assembly": "at Object.onInvoke (http://localhost:4200/node_modules_angular_core_fesm2020_core_mjs.js:31743:25)",
"fileName": "http://localhost:4200/node_modules_angular_core_fesm2020_core_mjs.js",
"line": 31743
},
{
"level": 5,
"method": "ZoneDelegate.invoke",
"assembly": "at ZoneDelegate.invoke (http://localhost:4200/polyfills.js:8158:46)",
"fileName": "http://localhost:4200/polyfills.js",
"line": 8158
},
{
"level": 6,
"method": "Zone.run",
"assembly": "at Zone.run (http://localhost:4200/polyfills.js:7899:35)",
"fileName": "http://localhost:4200/polyfills.js",
"line": 7899
},
{
"level": 7,
"method": "ZoneDelegate.invokeTask",
"assembly": "at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:8191:171)",
"fileName": "http://localhost:4200/polyfills.js",
"line": 8191
}
]
}
],
"properties": {
"typeName": "Error",
"SDKName": "Angular"
}
}
}
}