Download PDF
Download page SPA1 Monitoring.
SPA1 Monitoring
We recommend you use SPA2 Monitoring for all SPA frameworks, especially Angular 1–5 and React.
This page describes how to use SPA1 monitoring for AngularJS 1 applications and manually report events for Ember.js applications. This page also provides information about the AngularJS 1 support for SPA1 monitoring.
SPA Requirements
- IE 10 and Edge is supported. IE >=10 and Edge cannot be in compatibility mode with <=IE 9 browsers.
For non-AngularJS frameworks, the JavaScript Agent >=4.2 is required.
Manual Injection for Angular 1.x Applications
For non-Angular applications, adrum.js
needs to be loaded before any other JavaScript on the page. When you are using AngularJS 1, however, you need to inject adrum.js
after angular.js
, but before angular.js
is bootstrapped.
To learn which Angular versions have monitoring support, see Monitoring Support for AngularJS.
Manual Injection for Ember.js Applications
For Ember.js applications, you manually inject the JavaScript Agent much in the same way you would do for web pages loaded from an HTTP request. To monitor virtual pages, you manually start and end Virtual Page events based on events triggered when pages are dynamically created. You can also monitor virtual pages to report errors for pages.
The following sections will show you how to inject the JavaScript Agent and monitor virtual pages.
Manual Injection of the JavaScript Agent
The file app/index.html
is the HTML skeleton for all dynamics pages in Ember.js. Thus, you can inject the JavaScript Agent in this file so it is included in every page.
<!DOCTYPE html>
<html>
<head>
...
<script charset='UTF-8'>
window['adrum-start-time'] = new Date().getTime();
(function(config){
config.appKey = '<EUM_APP_KEY>';
config.adrumExtUrlHttp = 'http://cdn.appdynamics.com';
config.adrumExtUrlHttps = 'https://cdn.appdynamics.com';
config.beaconUrlHttp = 'http://col.eum-appdynamics.com';
config.beaconUrlHttps = 'https://col.eum-appdynamics.com';
config.xd = {enable : false};
})(window['adrum-config'] || (window['adrum-config'] = {}));
</script>
<script src="//cdn.appdynamics.com/adrum/adrum-latest.js"></script>
</head>
<body>
{{content-for "body"}}
...
</body>
</html>
<!DOCTYPE html>
<html>
<head>
...
<script charset='UTF-8'>
window['adrum-start-time'] = new Date().getTime();
(function(config){
config.appKey = '<EUM_APP_KEY>';
config.adrumExtUrlHttp = 'http://<your-cdn.com>';
config.adrumExtUrlHttps = 'https://<your-cdn.com>';
config.beaconUrlHttp = 'http://col.eum-appdynamics.com';
config.beaconUrlHttps = 'https://col.eum-appdynamics.com';
config.xd = {enable : false};
})(window['adrum-config'] || (window['adrum-config'] = {}));
</script>
<script src="//<your-cdn.com>/adrum/adrum-latest.js"></script>
</head>
<body>
{{content-for "body"}}
...
</body>
</html>
<!DOCTYPE html>
<html>
<head>
...
<script charset='UTF-8'>
window['adrum-start-time'] = new Date().getTime();
(function(config){
config.appKey = '<EUM_APP_KEY>';
config.adrumExtUrlHttp = 'http://cdn.appdynamics.com';
config.adrumExtUrlHttps = 'https://cdn.appdynamics.com';
config.beaconUrlHttp = 'http://col.eum-appdynamics.com';
config.beaconUrlHttps = 'https://col.eum-appdynamics.com';
config.xd = {enable : false};
})(window['adrum-config'] || (window['adrum-config'] = {}));
</script>
<script src="//<your-cdn.com>/adrum/adrum.js"></script>
</head>
<body>
{{content-for "body"}}
...
</body>
</html>
Monitor Virtual Pages
When a user requests a new page, the route handler renders the associated template to form the new content of the virtual page. You can listen for events in the route handler indicating when the handler is started and completed, which in effect mark the lifetime of the virtual page. To monitor the virtual page, you start a Virtual Page Event when the activate
event is triggered, close the Virtual Page when the deactivate
event is triggered, and then report the completed virtual page.
The code snippet below listens to the activate
and deactivate
events and reports the created virtual page event.
import Ember from 'ember';
import config from '.././config/environment';
export default Ember.Route.extend({
beforeEnterAbout: Ember.on('activate', function(){
console.log('hello about');
config.aboutVpView = new ADRUM.events.VPageView();
config.aboutVpView.start();
}),
afterEnterRental: Ember.on('deactivate', function(){
console.log('goodbye about');
config.aboutVpView.end();
ADRUM.report(config.aboutVpView);
})
});
Use Virtual Pages to Capture Errors
You can also create actions in the routing handlers that can be monitored through virtual pages. For example, you might want to monitor Ajax calls. You can create an action that performs the Ajax call and then use a Virtual Page event to capture the results and errors as shown in the code snippet below.
actions: {
makeXhrCall() {
config.xhrVpView = new ADRUM.events.VPageView();
config.xhrVpView.start();
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState === 4) {
console.log(xmlHttp.responseText);
config.xhrVpView.end();
ADRUM.report(config.xhrVpView);
}
};
xmlHttp.open("GET", "http://localhost:3000", true);
xmlHttp.send(null);
}
}
Monitoring Support for AngularJS 1
The JavaScript Agent supports monitoring by default for AngularJS versions 1.x.
Routing Engines
AngularJS 1 applications that have multiple Views use a route to move from one virtual page to another. You can use Browser RUM to instrument any virtual page that uses either of two routing engines, ngRoute
or ui-router.
Metrics
Because virtual pages are constructed in the browser, normal page view metrics must be adjusted. In essence, what a metric for AngularJS 1 must do is correlate the time between various routing events, using their timestamps. Metrics are calculated as follows:
Full Metric Name | Short Metric Name | Calculation |
---|---|---|
End User Response Time (not used for waterfall UI) | PLT | virtualPageStart to virtualPageEnd |
HTML Download Time | DDT | viewChangeStart to viewChangeEnd |
HTML Download and DOM Building Time | DRT | viewChangeStart to viewDOMLoaded |
DOM Building Time | DPT | viewChangeEnd to viewDOMLoaded |
DOM Ready Time (used instead of PLT for waterfall UI) | DOM | viewChangeStart to viewDOMLoaded |
Because the two routing engines function in slightly different ways, what the AppDynamics event consists of differs slightly, based on the engine.
AppDynamic Event Name | ngRoute Equivalent | ui-router Equivalent |
---|---|---|
virtualPageStart |
|
|
viewChangeStart |
|
|
viewChangeEnd |
|
|
viewDOMLoaded |
| (may happen multiple times - timestamp overwritten each time) |
viewFragmentsLoaded | load time of the last HTML fragment | |
xhrRequestsCompleted | response time of the last XHR requests | |
viewResourcesLoaded | load time of the last resources | |
virtualPageEnd | the latest one among viewContentLoaded , xhrRequestsCompleted, and viewResourcesLoaded |
Page Load Process Visualized
Visualized the page load process looks something like this:
Compare these to the standard page metrics, which are shown in Browser RUM Metrics.
Exclude Heartbeats or Background Requests from Timings
You may wish to exclude certain events from your virtual page timings. To do this, you can customize the JavaScript Agent when you inject it.
Add the following snippet before you add the JavaScript Agent file, adrum.js
, to the page:
Option for excluding XHRs
<script type="text/javascript">
(function(config) {
(function(spa) {
(function(angular) {
(function(vp) {
vp.xhr = {
"exclude": {
"urls": {
pattern: '.*/dealActiveUsers'
}
}
};
})(angular.vp || (angular.vp = {}));
})(spa.angular || (spa.angular = {}));
})(config.spa || (config.spa = {}));
})(window["adrum-config"] || (window["adrum-config"] = {}));
</script>
Enable Resource Timing Collection for Virtual Pages
By default, Virtual Pages for AngularJS 1 do not include resource timing metrics. You need to set the Angular virtual page property includeResTimingInEndUserResponseTiming
to true
.
The JavaScript configuration below shows you how to enable resource timing collection for AngularJS 1 virtual pages. The configuration also sets limits for XHR calls per page, the buffer size for resource timings, and sets the flag for clearing resource timing metrics when a beacon is sent.
window['adrum-config'] = {
"xhr": {
"maxPerPageView": 10000
},
"resTiming": {
bufSize: 300,
"clearResTimingOnBeaconSend": true
},
"spa": {
"angular": {
"vp": {
"metrics": {
"includeResTimingInEndUserResponseTiming": true
}
}
}
}
}
View Correlated Server Times
Since there isn't a regular HTML page timing to which correlated server timings can be linked, to view server times you must drill down from the Dashboard or Snapshot virtual page view to the component XHR requests. The server times can be seen there.