How to instrument a web application

The JavaScript Agent is the central component in UEM for web applications. It collects user experience data in the browser and sends it to a web or application server, where an Agent forwards the data to an AppMon server.

The JavaScript Agent is a script that automatically injects into web pages (of mime type text/html) using either Java or Web Server Agents, or manually at design time if not otherwise possible.

Agent injection

Injecting Agents is what instruments a web site. Injection consists of:

  • Initialization code. It is an inline <script> tag. It must be injected as the very first script and consists of essential instrumentation parts of the JavaScript Agent.
  • Injecting a tag with a src-attribute. For the best capturing experience, the it should be injected right after the inline tag, before any other JavaScript.

Refer to the JavaScript Agent injection page for more information about JavaScript Agent injection.

Agent Configuration

Injected Agents use configuration settings in the System Profile - User Experience item, generically:

<script type="text/javascript" src="/dtagent_<featurehash>_<version>.js"></script>

  • <featurehash>: A set of characters that identifies which Agent modules to include and activate. When only the basic Agent is activated, the feature hash is empty resulting in two adjacent underscores in dtagent__<version>.js. The following modules are delivered with AppMon:

  • Ajax (XHR) detection modules:

    • ActiveX XHR Detection (v)1
    • Angular JS (g)
    • Basic XHR Detection (x)
    • Dojo (d)
    • ExtJS (e)2
    • ICEfaces (i)
    • jQuery (j)
    • MooTools (m)
    • Prototype (o)
  • Additional packs:

    • JavaScript Errors (q)
    • Perceived render time (p)
    • Speed Index (S)
    • Streaming (s)
    • Timed Action Support (t)
    • User Timings (T)
    • Visually Complete (V)
  • Community packs (debug mode only):

    • Gomez page and group IDs (z)
    • JS agent async core module
    • JS agent initconfig module
    • Windchill (1)

1 ActiveXObject support (required by IE 6, supported by IE 7 and later) is split from the basic XMLHttpRequest module to reduce file size and performance overhead. The ActiveXObject support module is only needed if the instrumented application utilizes ActiveXObjects to send requests from the JavaScript side that have to be captured. Every AppMon supported browser supports XMLHttpRequests, so most applications only need basic XMLHttpRequest detection. If uncertain whether you need ActiveXObjects support, both modules can be enabled.
2 Some ExtJs-Functions use deferred callbacks when they send XHRs. AppMon does not capture these requests because it can't create a link to a user action. Activate the Timed Action support To avoid this, activate the Timed Action support. It extends user actions to track deferred functions. Ext.FormPanel is a known ExtJs function that must have Timed Action (t) support.
3 The resource timings modules takes advantage of the W3C Resource Timing API. However, not all browsers currently support it, thus the JavaScript Agent performs timing checks based on instrumented html tags and gathers information about load times of external resources. This approach can cause some overhead, so be sure to set resource timing limits within your application configuration.

The following shows a configuration example with activated Dojo and jQuery JavaScript packs:

<script type="text/javascript" src="/dtagent_dj_700000000 GABuildNotYetKnown.js"></script>

How does it work?

After UEM configuration changes, the initialization code is created containing all necessary information about the current configuration for each application. It can then be retrieved using the REST API.

If a page is injected with the JavaScript Agent initialization code, it checks if the browser already stored some application information and creates the JavaScript Agent script tag. It is then injected directly after the initialization tag and starts working immediately.

Performance notes

  • Overhead: Since the initialization tag is inlined into a page, there's no additional request that has to be made by the browser. The configuration updates are retrieved as soon as an action is sent.
  • Caching: Since the JavaScript Agent is cached for about a week, there is a chance that the initialization tag loads it with outdated settings. In this case the first page load is tracked using the old settings. A beacon is sent and in response the app / web server Agent provides new configurations which are then stored in the browser's local storage. Upon the next page load these settings are loaded and the initialization code is capable of creating an updated JavaScript Agent tag.
  • Filesize: Depending on the application configuration the obfuscated initialization code's size is about 6.65kb.
  • Browser support: Internet Explorer 6 and 7 have no implementation of Local or Session Storage and therefore do not automatically update upon configuration changes. However, as soon as the cached page ages, the initialization code updates to the latest configuration revision.

Scenarios

There are various ways the initialization code is executed, depending on the visitor.

  • New visitor: First, the initialization code is loaded, which loads the JavaScript Agent depending on the current configuration.
  • Recurring visitor: The full page is loaded from cache. The initialization code checks the browser's local storage for configuration entries. If there are none, it takes the last known configuration and loads the JavaScript Agent from cache. Any new settings sent with the beacon get stored in the local storage.
  • Recurring visitor with changed settings: The full page is loaded from cache. The initialization code checks the browser's local storage for configuration entries. If there are any, it checks if they are newer than the ones contained in the initialization code and takes the latest settings to create the JavaScript Agent tag. If feature hash and version are the same, the JavaScript Agent is loaded from cache.
  • Recurring visitor which shouldn't be tracked: If a visit should not be tracked due to visit percentage settings, the JavaScript Agent still initially injects using the initialization code and sends a beacon containing a load action. The application / web server Agents receive this beacon and decide if the visit should be tracked or not. If not, the beacon is ignored and the response contains a flag. Should the JavaScript Agent receive such a flag, every communication shuts down and no more beacons are sent until the browser session ends.

Monitor signal behavior

The JavaScript Agent sends the gathered information in the form of POST requests. This behavior is recommended for most servers and requires that POST requests are allowed on dynaTraceMonitor*.

In most cases signals are sent as soon as actions are finished. This action starts with a user input that triggers a request and ends as soon as all of the request's callbacks are finished. The load-action occurs on each iframe and full page load and is sent on every page, if user inputs exist or not.

These actions trigger signals to be sent immediately after the actions are finished, in contrast to medium priority signals. These are triggered by timeless and lesser important actions. These medium priority actions are bandwidth, streaming, and resource information, as well as reported values like errors or custom strings. If a signal is queued, this information is appended and doesn't create a separate request.

If multiple actions happen in a small time frame, such as a user action during page load, all of those actions are sent in a single signal.

For longer actions, a preview signal is sent as medium priority signal. Actions are sent only if all of their children and siblings are finished. If, for example, an action is opened and a second one is opened (which automatically is a child of the first one), the first one won't be sent until the second one is finished.

Support for cross-origin resource sharing (CORS)

Reporting from a non-instrumented host

AppMon enables injection of the JavaScript Agent on web servers that are not instrumented. If a website is hosted on a web server where UEM is not active, the JavaScript Agent has to report to a different domain, which can cause cross domain problems. If you use a CDN and don't want to send the monitor signal back through the CDN, you can send the monitor signal using CORS (Cross Origin Resource Sharing).

To enable support for CORS, start the AppMon Client and select the Send AppMon monitoring request to foreign domain in [System Profile] > User Experience vertical tab > [application] horizontal tab > Advanced configuration section.

Be sure to set the Monitor request path configuration to a location (use an absolute path that starts with http) that is UEM-enabled (for example by a Java Agent).

Monitoring CORS requests

Web requests can only be linked to user actions if cookies are available. In case of CORS requests, cookies aren't sent per default. Therefore correlation between user actions and CORS web requests can only be achieved by using the withCredentials property of the XMLHttpRequest object. This applies for an environment like this:

Restrictions

Due to access-control-restrictions it is not possible to capture OPTIONS requests like those sent as CORS preflight requests. Capturing those requests would require sending a AppMon cookie to the receiver of the request, which is not allowed. This could result in User Action PurePaths that have the correct timing values, but are missing the time the OPTIONS request took before the real CORS request fires. See MDN for more information about CORS preflight requests.