First Overview, Ideas, Concept, etc.

 

1. Injecting the JavaScript file into the web application

The aim is to make that the JavaScript file run in background while the end user is operating. Therefore, a <script>-tag must be injected into the .html files. In addition, the JavaScript-file has to be made available by deploying it within the web application

 

 

Approach
no.
descriptionproscons
1

A configuration GUI for end user experience is provided as illustrated below.
The user must specify the path to the project where all HTML-headers of all .html files in the source code
are modified by injecting a script tag (realized by a Java app). Afterwards, the JS-file which is generated dynamcially
according to the user configs is placed into a folder the application server has access to. 

+ works in all server environments

+ not too complicated

 

  • extra Java program
  • code invasive
  • all .html files ? xhtml too ?
2.A new inspectIT agent injects a new servlet instance automatically which modifies the HTML headers dynamically. The servlet can then operate for receiving the monitored data and trace-IDs. The JavaScript file could be injected as proposed in approach 1. + user does not need to specify the location of the project
  • more complicated
  • only works with JavaEE application servers
  • how does this work exactly ? Every time, a html file is requested ?

 

 

EUE configuration file
projectLocation = [path_to_project]
sendingStrategy = time-based  || size-based
maxStringLengthForDOMPath = 100
extendedInfo = true || false
...
...
 
 

 

 

2. Communication between application server - client in regard to EUE-data

 

Approach
no.
descriptionproscons
1.

client-side just manipulates each HTTP request-header and inserts the trace-ID. The captured data are sent directly to the CMR. See step 4.

+ no additional servlet needed 
2.additional servlet processes all EUE-data and sends them to the CMR afterwards.
 

+ the config options of the JavaScript
file can be changed during runtime (really necessary?)

  • servlet serves as a proxy server
  • one unnecessary coomunication point

 

 

 

3. Tracing meaningful data with JavaScript

The following code block shows a first draft of how a result string which is generated by the JavaScript file should look like.

 

traced data from a request
{
    "requestID": 123,
    "sessionID": 12356789,
    "timestampStart": 1400149357,
    "timings": {
        "connectionTime": 5,
        "requestTime": 23,
        "responseTime": 3,
        "renderingTime": 103
    },
    "requestData": {
        "initiatorType": " xmlhttprequest | link | script | img | css",
        "loadedResource": "http://localhost:8080/dvdstore/screen.css"
    },
    "previuoslyMadeInteractions": {
        "interaction1": {
            "typeOfEvent": "scroll | click | key | move(mouseover/mouseout)",
            "value": "Typed text",
            "eventSource": "<button class='gbqfba' aria-label='Google-Suche' id='gbqfba' name='btnK'><span id='gbqfsa'>Google-Suche</span></button>",
            "calledJSFunctions": {
                "FunctionName1": 23,
                "FunctionName2": "34 + FunctionName1",
                "FunctionName3": "133 + FunctionName1"
            },
            "errors": {
                "error1": {
                    "timestamp": 123455656321,
                    "inFunction": "Functionname",
                    "stacktrace": "DBX.Utils.stackTrace@http://localhost:49573/assets/js/scripts.js:44"
                }
            }
        },
        "interaction2": {
            "typeOfEvent": "scroll|click|key|move(mouseover/mouseout)",
            "value": "",
            "eventSource": "<buttonclass='gbqfba'aria-label='Google-Suche'id='gbqfba'name='btnK'><spanid='gbqfsa'>Google-Suche</span></button>",
            "calledJSFunctions": {}
        }
    },
    "memory": {
        "jsHeapSizeLimit": 793000000,
        "totalJSHeapSize": 20500000,
        "usedJSHeapSize": 11200000
    }
}

 

We can also trace the first page load times (How long does it take, to load the page? Domain-Lookup, connection time, request time, response time, DOM loading time). We can use this for registering this session in the CMR, so it will expect further data containing this session-ID.

FixedInformations
{
    "sessionID": 12356789,
    "timestamp": 1400149357,
    "pageLoadTimes": {
        "connectionTime": 5,
        "requestTime": 23,
        "responseTime": 3,
        "DOMLoading": 45,
        "loadEventTime": 4
    },
    "browseragent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0",
    "geolocation": {
        "Latitude": 48.698007,
        "Longitude": 9.140742999999999
    }
}

 

 

 

 Open Questions/prolems:

  • How to generate the requestID ? Simply increasing numbers ?
  • DomPathToSource: Screenshot more valuable but more complex ? overhead ?
  • JavaScript functions and variables often are obfuscated because of optimization reasons
  • many functions are anonymous
  • Consider user think time ?
  • "JavaScript "un-optimization", problem understanding the JS optimized code " ?
  • Not every JS-Function is traced but only those which are triggered by an user interaction
  • JavaScript invocation sequences (including execution timings) are very hard to trace
  • correlation: event-called function also not easy to track
  • timeout-Functions which are invoked by web frameworks multiple times each second

 

 

 

4. Sending data from the client (browser) to the CMR

There are limitations due to the single origin policiy (SOP)  in JavaScript prohibiting communication with any other server than the original one. However, there are two common approaches to solve the problem. 


4.1 JSONP (JSON with Padding)

Fortunately, SOP does not apply to script-tags. That is why you can write the following jQuery inclusion without concerns:

jQuery inclusion
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script> 

 

So, you reach another server and load data from it. The other way around is possible,too. You can create a script tag dynamically and inject it into the DOM. The script you are injecting can have URL parameters (via GET-method of HTTP). In these parameters, we can send our EUE-data. For example:

 

JSONP example
<script src="[urlToCMR]/jsonp?time=" +now.getTime()+"&callback=callback";"></script> 

JSONP works in all browsers and does not require any additional resource.

Limitations:

  • maximal URL-Length = 2048
  • only GET-method 
  • bad exception handling

 

4.1 CORS (Cross-origin resource sharing)

 

The CORS standard works by adding new HTTP headers which allow servers to serve resources to permitted origin domains. Browsers support these headers and respect the restrictions they establish. Therefore, normal AJAX calls are possible to other servers. In consequence, HTTP POST requests are possible, too. 

  

CORS example
 Access-Control-Allow-Origin: [urlToCMR]


Unfortunately, a small number of browsers does not support CORS. See http://caniuse.com/cors for more information. Especially IE versions until 8.0 are shaky candidates (smile)

 

 

5. Correlation between server trace-ID and client trace-ID


I suggest generating the invocation-ID on the client which is then sent to the application server within every request in the request header. This id should be used on the server-side when monitoring methods.

 

 

 

 

6. Illustration in the inspectIT GUI