@microsoft/applicationinsights-analytics-js 2.8.5-nightly.2206-03 → 2.8.5-nightly.2207-01
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser/applicationinsights-analytics-js.integrity.json +9 -9
- package/browser/applicationinsights-analytics-js.js +1416 -1239
- package/browser/applicationinsights-analytics-js.js.map +1 -1
- package/browser/applicationinsights-analytics-js.min.js +2 -2
- package/browser/applicationinsights-analytics-js.min.js.map +1 -1
- package/dist/applicationinsights-analytics-js.api.json +6 -2
- package/dist/applicationinsights-analytics-js.d.ts +1 -1
- package/dist/applicationinsights-analytics-js.js +1416 -1239
- package/dist/applicationinsights-analytics-js.js.map +1 -1
- package/dist/applicationinsights-analytics-js.min.js +2 -2
- package/dist/applicationinsights-analytics-js.min.js.map +1 -1
- package/dist/applicationinsights-analytics-js.rollup.d.ts +1 -1
- package/dist-esm/JavaScriptSDK/AnalyticsPlugin.js +115 -112
- package/dist-esm/JavaScriptSDK/AnalyticsPlugin.js.map +1 -1
- package/dist-esm/JavaScriptSDK/Telemetry/PageViewManager.js +24 -23
- package/dist-esm/JavaScriptSDK/Telemetry/PageViewManager.js.map +1 -1
- package/dist-esm/JavaScriptSDK/Telemetry/PageViewPerformanceManager.js +159 -153
- package/dist-esm/JavaScriptSDK/Telemetry/PageViewPerformanceManager.js.map +1 -1
- package/dist-esm/JavaScriptSDK/Telemetry/PageVisitTimeManager.js +90 -87
- package/dist-esm/JavaScriptSDK/Telemetry/PageVisitTimeManager.js.map +1 -1
- package/dist-esm/JavaScriptSDK/Timing.js +1 -1
- package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryConfig.js +1 -1
- package/dist-esm/__DynamicConstants.js +61 -0
- package/dist-esm/__DynamicConstants.js.map +1 -0
- package/dist-esm/applicationinsights-analytics-js.js +1 -1
- package/package.json +9 -6
- package/src/JavaScriptSDK/AnalyticsPlugin.ts +49 -51
- package/src/JavaScriptSDK/Telemetry/PageViewManager.ts +18 -18
- package/src/JavaScriptSDK/Telemetry/PageViewPerformanceManager.ts +183 -160
- package/src/JavaScriptSDK/Telemetry/PageVisitTimeManager.ts +108 -100
- package/src/__DynamicConstants.ts +59 -0
- package/types/JavaScriptSDK/AnalyticsPlugin.d.ts +5 -5
- package/types/JavaScriptSDK/Telemetry/PageViewManager.d.ts +1 -1
- package/types/JavaScriptSDK/Telemetry/PageViewPerformanceManager.d.ts +1 -8
- package/types/JavaScriptSDK/Telemetry/PageVisitTimeManager.d.ts +0 -20
- package/types/__DynamicConstants.d.ts +47 -0
- package/types/tsdoc-metadata.json +1 -1
|
@@ -1,146 +1,204 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
-
// Licensed under the MIT License.
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import dynamicProto from "@microsoft/dynamicproto-js";
|
|
5
|
+
import { IPageViewPerformanceTelemetryInternal, dateTimeUtilsDuration, msToTimeSpan } from "@microsoft/applicationinsights-common";
|
|
6
|
+
import {
|
|
7
|
+
IAppInsightsCore, IDiagnosticLogger, _eInternalMessageId, _throwInternal, eLoggingSeverity, getNavigator, getPerformance, safeGetLogger
|
|
8
|
+
} from "@microsoft/applicationinsights-core-js";
|
|
9
|
+
|
|
10
|
+
const MAX_DURATION_ALLOWED = 3600000; // 1h
|
|
11
|
+
const botAgentNames = ["googlebot", "adsbot-google", "apis-google", "mediapartners-google"];
|
|
12
|
+
|
|
13
|
+
function _isPerformanceTimingSupported() {
|
|
14
|
+
let perf = getPerformance();
|
|
15
|
+
return perf && !!perf.timing;
|
|
16
|
+
}
|
|
3
17
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
IAppInsightsCore, IDiagnosticLogger, eLoggingSeverity,
|
|
9
|
-
_eInternalMessageId, getNavigator, getPerformance, _throwInternal
|
|
10
|
-
} from "@microsoft/applicationinsights-core-js";
|
|
18
|
+
function _isPerformanceNavigationTimingSupported() {
|
|
19
|
+
let perf = getPerformance();
|
|
20
|
+
return perf && perf.getEntriesByType && perf.getEntriesByType("navigation").length > 0;
|
|
21
|
+
}
|
|
11
22
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
function _isPerformanceTimingDataReady() {
|
|
24
|
+
let perf = getPerformance();
|
|
25
|
+
const timing = perf ? perf.timing : 0;
|
|
26
|
+
|
|
27
|
+
return timing
|
|
28
|
+
&& timing.domainLookupStart > 0
|
|
29
|
+
&& timing.navigationStart > 0
|
|
30
|
+
&& timing.responseStart > 0
|
|
31
|
+
&& timing.requestStart > 0
|
|
32
|
+
&& timing.loadEventEnd > 0
|
|
33
|
+
&& timing.responseEnd > 0
|
|
34
|
+
&& timing.connectEnd > 0
|
|
35
|
+
&& timing.domLoading > 0;
|
|
36
|
+
}
|
|
18
37
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
38
|
+
function _getPerformanceTiming(): PerformanceTiming | null {
|
|
39
|
+
if (_isPerformanceTimingSupported()) {
|
|
40
|
+
return getPerformance().timing;
|
|
41
|
+
}
|
|
23
42
|
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function _getPerformanceNavigationTiming(): PerformanceNavigationTiming | null {
|
|
47
|
+
if (_isPerformanceNavigationTimingSupported()) {
|
|
48
|
+
return getPerformance().getEntriesByType("navigation")[0] as PerformanceNavigationTiming;
|
|
24
49
|
}
|
|
25
50
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/*
|
|
30
|
-
* http://www.w3.org/TR/navigation-timing/#processing-model
|
|
31
|
-
* |-navigationStart
|
|
32
|
-
* | |-connectEnd
|
|
33
|
-
* | ||-requestStart
|
|
34
|
-
* | || |-responseStart
|
|
35
|
-
* | || | |-responseEnd
|
|
36
|
-
* | || | |
|
|
37
|
-
* | || | | |-loadEventEnd
|
|
38
|
-
* |---network---||---request---|---response---|---dom---|
|
|
39
|
-
* |--------------------------total----------------------|
|
|
40
|
-
*
|
|
41
|
-
* total = The difference between the load event of the current document is completed and the first recorded timestamp of the performance entry : https://developer.mozilla.org/en-US/docs/Web/Performance/Navigation_and_resource_timings#duration
|
|
42
|
-
* network = Redirect time + App Cache + DNS lookup time + TCP connection time
|
|
43
|
-
* request = Request time : https://developer.mozilla.org/en-US/docs/Web/Performance/Navigation_and_resource_timings#request_time
|
|
44
|
-
* response = Response time
|
|
45
|
-
* dom = Document load time : https://html.spec.whatwg.org/multipage/dom.html#document-load-timing-info
|
|
46
|
-
* = Document processing time : https://developers.google.com/web/fundamentals/performance/navigation-and-resource-timing/#document_processing
|
|
47
|
-
* + Loading time : https://developers.google.com/web/fundamentals/performance/navigation-and-resource-timing/#loading
|
|
48
|
-
*/
|
|
49
|
-
const navigationTiming = this.getPerformanceNavigationTiming();
|
|
50
|
-
const timing = this.getPerformanceTiming();
|
|
51
|
-
let total = 0;
|
|
52
|
-
let network = 0;
|
|
53
|
-
let request = 0;
|
|
54
|
-
let response = 0;
|
|
55
|
-
let dom = 0;
|
|
56
|
-
|
|
57
|
-
if (navigationTiming || timing) {
|
|
58
|
-
if (navigationTiming) {
|
|
59
|
-
total = navigationTiming.duration;
|
|
60
|
-
/**
|
|
61
|
-
* support both cases:
|
|
62
|
-
* - startTime is always zero: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming
|
|
63
|
-
* - for older browsers where the startTime is not zero
|
|
64
|
-
*/
|
|
65
|
-
network = navigationTiming.startTime === 0 ? navigationTiming.connectEnd : dateTimeUtilsDuration(navigationTiming.startTime, navigationTiming.connectEnd);
|
|
66
|
-
request = dateTimeUtilsDuration(navigationTiming.requestStart, navigationTiming.responseStart);
|
|
67
|
-
response = dateTimeUtilsDuration(navigationTiming.responseStart, navigationTiming.responseEnd);
|
|
68
|
-
dom = dateTimeUtilsDuration(navigationTiming.responseEnd, navigationTiming.loadEventEnd);
|
|
69
|
-
} else {
|
|
70
|
-
total = dateTimeUtilsDuration(timing.navigationStart, timing.loadEventEnd);
|
|
71
|
-
network = dateTimeUtilsDuration(timing.navigationStart, timing.connectEnd);
|
|
72
|
-
request = dateTimeUtilsDuration(timing.requestStart, timing.responseStart);
|
|
73
|
-
response = dateTimeUtilsDuration(timing.responseStart, timing.responseEnd);
|
|
74
|
-
dom = dateTimeUtilsDuration(timing.responseEnd, timing.loadEventEnd);
|
|
75
|
-
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
76
53
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
_eInternalMessageId.InvalidDurationValue,
|
|
90
|
-
"Invalid page load duration value. Browser perf data won't be sent.",
|
|
91
|
-
{ total, network, request, response, dom });
|
|
92
|
-
|
|
93
|
-
} else if (total < Math.floor(network) + Math.floor(request) + Math.floor(response) + Math.floor(dom)) {
|
|
94
|
-
// some browsers may report individual components incorrectly so that the sum of the parts will be bigger than total PLT
|
|
95
|
-
// in this case, don't report client performance from this page
|
|
96
|
-
_throwInternal(logger,
|
|
97
|
-
eLoggingSeverity.WARNING,
|
|
98
|
-
_eInternalMessageId.ClientPerformanceMathError,
|
|
99
|
-
"client performance math error.",
|
|
100
|
-
{ total, network, request, response, dom });
|
|
101
|
-
|
|
102
|
-
} else {
|
|
103
|
-
pageViewPerformance.durationMs = total;
|
|
104
|
-
// // convert to timespans
|
|
105
|
-
pageViewPerformance.perfTotal = pageViewPerformance.duration = msToTimeSpan(total);
|
|
106
|
-
pageViewPerformance.networkConnect = msToTimeSpan(network);
|
|
107
|
-
pageViewPerformance.sentRequest = msToTimeSpan(request);
|
|
108
|
-
pageViewPerformance.receivedResponse = msToTimeSpan(response);
|
|
109
|
-
pageViewPerformance.domProcessing = msToTimeSpan(dom);
|
|
110
|
-
pageViewPerformance.isValid = true;
|
|
111
|
-
}
|
|
54
|
+
/**
|
|
55
|
+
* This method tells if given durations should be excluded from collection.
|
|
56
|
+
*/
|
|
57
|
+
function _shouldCollectDuration(...durations: number[]): boolean {
|
|
58
|
+
var _navigator = getNavigator() || {} as any;
|
|
59
|
+
// a full list of Google crawlers user agent strings - https://support.google.com/webmasters/answer/1061943?hl=en
|
|
60
|
+
const userAgent = _navigator.userAgent;
|
|
61
|
+
let isGoogleBot = false;
|
|
62
|
+
|
|
63
|
+
if (userAgent) {
|
|
64
|
+
for (let i = 0; i < botAgentNames.length; i++) {
|
|
65
|
+
isGoogleBot = isGoogleBot || userAgent.toLowerCase().indexOf(botAgentNames[i]) !== -1;
|
|
112
66
|
}
|
|
113
67
|
}
|
|
114
68
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
69
|
+
if (isGoogleBot) {
|
|
70
|
+
// Don't report durations for GoogleBot, it is returning invalid values in performance.timing API.
|
|
71
|
+
return false;
|
|
72
|
+
} else {
|
|
73
|
+
// for other page views, don't report if it's outside of a reasonable range
|
|
74
|
+
for (let i = 0; i < durations.length; i++) {
|
|
75
|
+
if (durations[i] < 0 || durations[i] >= MAX_DURATION_ALLOWED) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
118
78
|
}
|
|
79
|
+
}
|
|
119
80
|
|
|
120
|
-
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Class encapsulates sending page view performance telemetry.
|
|
86
|
+
*/
|
|
87
|
+
export class PageViewPerformanceManager {
|
|
88
|
+
|
|
89
|
+
constructor(core: IAppInsightsCore) {
|
|
90
|
+
let _logger: IDiagnosticLogger = safeGetLogger(core);
|
|
91
|
+
|
|
92
|
+
dynamicProto(PageViewPerformanceManager, this, (_self) => {
|
|
93
|
+
_self.populatePageViewPerformanceEvent = (pageViewPerformance: IPageViewPerformanceTelemetryInternal): void => {
|
|
94
|
+
pageViewPerformance.isValid = false;
|
|
95
|
+
|
|
96
|
+
/*
|
|
97
|
+
* http://www.w3.org/TR/navigation-timing/#processing-model
|
|
98
|
+
* |-navigationStart
|
|
99
|
+
* | |-connectEnd
|
|
100
|
+
* | ||-requestStart
|
|
101
|
+
* | || |-responseStart
|
|
102
|
+
* | || | |-responseEnd
|
|
103
|
+
* | || | |
|
|
104
|
+
* | || | | |-loadEventEnd
|
|
105
|
+
* |---network---||---request---|---response---|---dom---|
|
|
106
|
+
* |--------------------------total----------------------|
|
|
107
|
+
*
|
|
108
|
+
* total = The difference between the load event of the current document is completed and the first recorded timestamp of the performance entry : https://developer.mozilla.org/en-US/docs/Web/Performance/Navigation_and_resource_timings#duration
|
|
109
|
+
* network = Redirect time + App Cache + DNS lookup time + TCP connection time
|
|
110
|
+
* request = Request time : https://developer.mozilla.org/en-US/docs/Web/Performance/Navigation_and_resource_timings#request_time
|
|
111
|
+
* response = Response time
|
|
112
|
+
* dom = Document load time : https://html.spec.whatwg.org/multipage/dom.html#document-load-timing-info
|
|
113
|
+
* = Document processing time : https://developers.google.com/web/fundamentals/performance/navigation-and-resource-timing/#document_processing
|
|
114
|
+
* + Loading time : https://developers.google.com/web/fundamentals/performance/navigation-and-resource-timing/#loading
|
|
115
|
+
*/
|
|
116
|
+
const navigationTiming = _getPerformanceNavigationTiming();
|
|
117
|
+
const timing = _getPerformanceTiming();
|
|
118
|
+
let total = 0;
|
|
119
|
+
let network = 0;
|
|
120
|
+
let request = 0;
|
|
121
|
+
let response = 0;
|
|
122
|
+
let dom = 0;
|
|
123
|
+
|
|
124
|
+
if (navigationTiming || timing) {
|
|
125
|
+
if (navigationTiming) {
|
|
126
|
+
total = navigationTiming.duration;
|
|
127
|
+
/**
|
|
128
|
+
* support both cases:
|
|
129
|
+
* - startTime is always zero: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming
|
|
130
|
+
* - for older browsers where the startTime is not zero
|
|
131
|
+
*/
|
|
132
|
+
network = navigationTiming.startTime === 0 ? navigationTiming.connectEnd : dateTimeUtilsDuration(navigationTiming.startTime, navigationTiming.connectEnd);
|
|
133
|
+
request = dateTimeUtilsDuration(navigationTiming.requestStart, navigationTiming.responseStart);
|
|
134
|
+
response = dateTimeUtilsDuration(navigationTiming.responseStart, navigationTiming.responseEnd);
|
|
135
|
+
dom = dateTimeUtilsDuration(navigationTiming.responseEnd, navigationTiming.loadEventEnd);
|
|
136
|
+
} else {
|
|
137
|
+
total = dateTimeUtilsDuration(timing.navigationStart, timing.loadEventEnd);
|
|
138
|
+
network = dateTimeUtilsDuration(timing.navigationStart, timing.connectEnd);
|
|
139
|
+
request = dateTimeUtilsDuration(timing.requestStart, timing.responseStart);
|
|
140
|
+
response = dateTimeUtilsDuration(timing.responseStart, timing.responseEnd);
|
|
141
|
+
dom = dateTimeUtilsDuration(timing.responseEnd, timing.loadEventEnd);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (total === 0) {
|
|
145
|
+
_throwInternal(_logger,
|
|
146
|
+
eLoggingSeverity.WARNING,
|
|
147
|
+
_eInternalMessageId.ErrorPVCalc,
|
|
148
|
+
"error calculating page view performance.",
|
|
149
|
+
{ total, network, request, response, dom });
|
|
150
|
+
|
|
151
|
+
} else if (!this.shouldCollectDuration(total, network, request, response, dom)) {
|
|
152
|
+
_throwInternal(_logger,
|
|
153
|
+
eLoggingSeverity.WARNING,
|
|
154
|
+
_eInternalMessageId.InvalidDurationValue,
|
|
155
|
+
"Invalid page load duration value. Browser perf data won't be sent.",
|
|
156
|
+
{ total, network, request, response, dom });
|
|
157
|
+
|
|
158
|
+
} else if (total < Math.floor(network) + Math.floor(request) + Math.floor(response) + Math.floor(dom)) {
|
|
159
|
+
// some browsers may report individual components incorrectly so that the sum of the parts will be bigger than total PLT
|
|
160
|
+
// in this case, don't report client performance from this page
|
|
161
|
+
_throwInternal(_logger,
|
|
162
|
+
eLoggingSeverity.WARNING,
|
|
163
|
+
_eInternalMessageId.ClientPerformanceMathError,
|
|
164
|
+
"client performance math error.",
|
|
165
|
+
{ total, network, request, response, dom });
|
|
166
|
+
|
|
167
|
+
} else {
|
|
168
|
+
pageViewPerformance.durationMs = total;
|
|
169
|
+
// // convert to timespans
|
|
170
|
+
pageViewPerformance.perfTotal = pageViewPerformance.duration = msToTimeSpan(total);
|
|
171
|
+
pageViewPerformance.networkConnect = msToTimeSpan(network);
|
|
172
|
+
pageViewPerformance.sentRequest = msToTimeSpan(request);
|
|
173
|
+
pageViewPerformance.receivedResponse = msToTimeSpan(response);
|
|
174
|
+
pageViewPerformance.domProcessing = msToTimeSpan(dom);
|
|
175
|
+
pageViewPerformance.isValid = true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
_self.getPerformanceTiming = _getPerformanceTiming;
|
|
181
|
+
_self.isPerformanceTimingSupported = _isPerformanceTimingSupported;
|
|
182
|
+
_self.isPerformanceTimingDataReady = _isPerformanceTimingDataReady;
|
|
183
|
+
_self.shouldCollectDuration = _shouldCollectDuration;
|
|
184
|
+
});
|
|
121
185
|
}
|
|
122
|
-
public getPerformanceNavigationTiming(): PerformanceNavigationTiming | null {
|
|
123
|
-
if (this.isPerformanceNavigationTimingSupported()) {
|
|
124
|
-
return getPerformance().getEntriesByType("navigation")[0] as PerformanceNavigationTiming;
|
|
125
|
-
}
|
|
126
186
|
|
|
127
|
-
|
|
187
|
+
public populatePageViewPerformanceEvent(pageViewPerformance: IPageViewPerformanceTelemetryInternal): void {
|
|
188
|
+
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
128
189
|
}
|
|
129
190
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
public isPerformanceNavigationTimingSupported() {
|
|
134
|
-
let perf = getPerformance();
|
|
135
|
-
return perf && perf.getEntriesByType && perf.getEntriesByType("navigation").length > 0;
|
|
191
|
+
public getPerformanceTiming(): PerformanceTiming | null {
|
|
192
|
+
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
193
|
+
return null;
|
|
136
194
|
}
|
|
137
195
|
|
|
138
196
|
/**
|
|
139
197
|
* Returns true is window performance timing API is supported, false otherwise.
|
|
140
198
|
*/
|
|
141
199
|
public isPerformanceTimingSupported() {
|
|
142
|
-
|
|
143
|
-
return
|
|
200
|
+
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
201
|
+
return true;
|
|
144
202
|
}
|
|
145
203
|
|
|
146
204
|
/**
|
|
@@ -148,50 +206,15 @@ export class PageViewPerformanceManager {
|
|
|
148
206
|
* Returns true if ready, false otherwise.
|
|
149
207
|
*/
|
|
150
208
|
public isPerformanceTimingDataReady() {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return timing
|
|
155
|
-
&& timing.domainLookupStart > 0
|
|
156
|
-
&& timing.navigationStart > 0
|
|
157
|
-
&& timing.responseStart > 0
|
|
158
|
-
&& timing.requestStart > 0
|
|
159
|
-
&& timing.loadEventEnd > 0
|
|
160
|
-
&& timing.responseEnd > 0
|
|
161
|
-
&& timing.connectEnd > 0
|
|
162
|
-
&& timing.domLoading > 0;
|
|
209
|
+
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
210
|
+
return true;
|
|
163
211
|
}
|
|
164
212
|
|
|
165
213
|
/**
|
|
166
214
|
* This method tells if given durations should be excluded from collection.
|
|
167
215
|
*/
|
|
168
216
|
public shouldCollectDuration(...durations: number[]): boolean {
|
|
169
|
-
|
|
170
|
-
// a full list of Google crawlers user agent strings - https://support.google.com/webmasters/answer/1061943?hl=en
|
|
171
|
-
const botAgentNames = ["googlebot", "adsbot-google", "apis-google", "mediapartners-google"];
|
|
172
|
-
const userAgent = _navigator.userAgent;
|
|
173
|
-
let isGoogleBot = false;
|
|
174
|
-
|
|
175
|
-
if (userAgent) {
|
|
176
|
-
for (let i = 0; i < botAgentNames.length; i++) {
|
|
177
|
-
isGoogleBot = isGoogleBot || userAgent.toLowerCase().indexOf(botAgentNames[i]) !== -1;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (isGoogleBot) {
|
|
182
|
-
// Don't report durations for GoogleBot, it is returning invalid values in performance.timing API.
|
|
183
|
-
return false;
|
|
184
|
-
} else {
|
|
185
|
-
// for other page views, don't report if it's outside of a reasonable range
|
|
186
|
-
for (let i = 0; i < durations.length; i++) {
|
|
187
|
-
if (durations[i] < 0 || durations[i] >= this.MAX_DURATION_ALLOWED) {
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
217
|
+
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
193
218
|
return true;
|
|
194
219
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
220
|
+
}
|
|
@@ -1,121 +1,129 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import dynamicProto from "@microsoft/dynamicproto-js";
|
|
5
|
+
import {
|
|
6
|
+
utlCanUseSessionStorage, utlGetSessionStorage, utlRemoveSessionStorage, utlSetSessionStorage
|
|
7
|
+
} from "@microsoft/applicationinsights-common";
|
|
8
|
+
import {
|
|
9
|
+
IDiagnosticLogger, _warnToConsole, dateNow, dumpObj, getJSON, hasJSON, objDefineAccessors, throwError
|
|
10
|
+
} from "@microsoft/applicationinsights-core-js";
|
|
11
|
+
|
|
7
12
|
/**
|
|
8
13
|
* Used to track page visit durations
|
|
9
14
|
*/
|
|
10
15
|
export class PageVisitTimeManager {
|
|
11
16
|
|
|
12
|
-
private prevPageVisitDataKeyName: string = "prevPageVisitData";
|
|
13
|
-
private pageVisitTimeTrackingHandler: (pageName: string, pageUrl: string, pageVisitTime: number) => void;
|
|
14
|
-
private _logger: IDiagnosticLogger;
|
|
15
|
-
|
|
16
17
|
/**
|
|
17
18
|
* Creates a new instance of PageVisitTimeManager
|
|
18
19
|
* @param pageVisitTimeTrackingHandler Delegate that will be called to send telemetry data to AI (when trackPreviousPageVisit is called)
|
|
19
20
|
* @returns {}
|
|
20
21
|
*/
|
|
21
22
|
constructor(logger: IDiagnosticLogger, pageVisitTimeTrackingHandler: (pageName: string, pageUrl: string, pageVisitTime: number) => void) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
let prevPageVisitDataKeyName: string = "prevPageVisitData";
|
|
24
|
+
|
|
25
|
+
dynamicProto(PageVisitTimeManager, this, (_self) => {
|
|
26
|
+
_self.trackPreviousPageVisit = (currentPageName: string, currentPageUrl: string) => {
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
// Restart timer for new page view
|
|
30
|
+
const prevPageVisitTimeData = restartPageVisitTimer(currentPageName, currentPageUrl);
|
|
31
|
+
|
|
32
|
+
// If there was a page already being timed, track the visit time for it now.
|
|
33
|
+
if (prevPageVisitTimeData) {
|
|
34
|
+
pageVisitTimeTrackingHandler(prevPageVisitTimeData.pageName, prevPageVisitTimeData.pageUrl, prevPageVisitTimeData.pageVisitTime);
|
|
35
|
+
}
|
|
36
|
+
} catch (e) {
|
|
37
|
+
_warnToConsole(logger, "Auto track page visit time failed, metric will not be collected: " + dumpObj(e));
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Stops timing of current page (if exists) and starts timing for duration of visit to pageName
|
|
43
|
+
* @param pageName Name of page to begin timing visit duration
|
|
44
|
+
* @returns {PageVisitData} Page visit data (including duration) of pageName from last call to start or restart, if exists. Null if not.
|
|
45
|
+
*/
|
|
46
|
+
function restartPageVisitTimer(pageName: string, pageUrl: string) {
|
|
47
|
+
let prevPageVisitData: PageVisitData = null;
|
|
48
|
+
try {
|
|
49
|
+
prevPageVisitData = stopPageVisitTimer();
|
|
50
|
+
startPageVisitTimer(pageName, pageUrl);
|
|
51
|
+
|
|
52
|
+
} catch (e) {
|
|
53
|
+
_warnToConsole(logger, "Call to restart failed: " + dumpObj(e));
|
|
54
|
+
prevPageVisitData = null;
|
|
55
|
+
}
|
|
36
56
|
|
|
37
|
-
|
|
38
|
-
if (prevPageVisitTimeData) {
|
|
39
|
-
this.pageVisitTimeTrackingHandler(prevPageVisitTimeData.pageName, prevPageVisitTimeData.pageUrl, prevPageVisitTimeData.pageVisitTime);
|
|
57
|
+
return prevPageVisitData;
|
|
40
58
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Starts timing visit duration of pageName
|
|
62
|
+
* @param pageName
|
|
63
|
+
* @returns {}
|
|
64
|
+
*/
|
|
65
|
+
function startPageVisitTimer(pageName: string, pageUrl: string) {
|
|
66
|
+
try {
|
|
67
|
+
if (utlCanUseSessionStorage()) {
|
|
68
|
+
if (utlGetSessionStorage(logger, prevPageVisitDataKeyName) != null) {
|
|
69
|
+
throwError("Cannot call startPageVisit consecutively without first calling stopPageVisit");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const currPageVisitData = new PageVisitData(pageName, pageUrl);
|
|
73
|
+
const currPageVisitDataStr = getJSON().stringify(currPageVisitData);
|
|
74
|
+
utlSetSessionStorage(logger, prevPageVisitDataKeyName, currPageVisitDataStr);
|
|
75
|
+
}
|
|
76
|
+
} catch (e) {
|
|
77
|
+
// TODO: Remove this catch in next phase, since if start is called twice in a row the exception needs to be propagated out
|
|
78
|
+
_warnToConsole(logger, "Call to start failed: " + dumpObj(e));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Stops timing of current page, if exists.
|
|
84
|
+
* @returns {PageVisitData} Page visit data (including duration) of pageName from call to start, if exists. Null if not.
|
|
85
|
+
*/
|
|
86
|
+
function stopPageVisitTimer() {
|
|
87
|
+
let prevPageVisitData: PageVisitData = null;
|
|
88
|
+
try {
|
|
89
|
+
if (utlCanUseSessionStorage()) {
|
|
90
|
+
|
|
91
|
+
// Define end time of page's visit
|
|
92
|
+
const pageVisitEndTime = dateNow();
|
|
93
|
+
|
|
94
|
+
// Try to retrieve page name and start time from session storage
|
|
95
|
+
const pageVisitDataJsonStr = utlGetSessionStorage(logger, prevPageVisitDataKeyName);
|
|
96
|
+
if (pageVisitDataJsonStr && hasJSON()) {
|
|
97
|
+
|
|
98
|
+
// if previous page data exists, set end time of visit
|
|
99
|
+
prevPageVisitData = getJSON().parse(pageVisitDataJsonStr);
|
|
100
|
+
prevPageVisitData.pageVisitTime = pageVisitEndTime - prevPageVisitData.pageVisitStartTime;
|
|
101
|
+
|
|
102
|
+
// Remove data from storage since we already used it
|
|
103
|
+
utlRemoveSessionStorage(logger, prevPageVisitDataKeyName);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
} catch (e) {
|
|
107
|
+
_warnToConsole(logger, "Stop page visit timer failed: " + dumpObj(e));
|
|
108
|
+
prevPageVisitData = null;
|
|
73
109
|
}
|
|
74
110
|
|
|
75
|
-
|
|
76
|
-
const currPageVisitDataStr = getJSON().stringify(currPageVisitData);
|
|
77
|
-
utlSetSessionStorage(this._logger, this.prevPageVisitDataKeyName, currPageVisitDataStr);
|
|
111
|
+
return prevPageVisitData;
|
|
78
112
|
}
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
113
|
+
|
|
114
|
+
// For backward compatibility
|
|
115
|
+
objDefineAccessors(_self, "_logger", () => logger);
|
|
116
|
+
objDefineAccessors(_self, "pageVisitTimeTrackingHandler", () => pageVisitTimeTrackingHandler);
|
|
117
|
+
});
|
|
83
118
|
}
|
|
84
119
|
|
|
85
120
|
/**
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
// Define end time of page's visit
|
|
94
|
-
const pageVisitEndTime = dateNow();
|
|
95
|
-
|
|
96
|
-
// Try to retrieve page name and start time from session storage
|
|
97
|
-
const pageVisitDataJsonStr = utlGetSessionStorage(this._logger, this.prevPageVisitDataKeyName);
|
|
98
|
-
if (pageVisitDataJsonStr && hasJSON()) {
|
|
99
|
-
|
|
100
|
-
// if previous page data exists, set end time of visit
|
|
101
|
-
const prevPageVisitData: PageVisitData = getJSON().parse(pageVisitDataJsonStr);
|
|
102
|
-
prevPageVisitData.pageVisitTime = pageVisitEndTime - prevPageVisitData.pageVisitStartTime;
|
|
103
|
-
|
|
104
|
-
// Remove data from storage since we already used it
|
|
105
|
-
utlRemoveSessionStorage(this._logger, this.prevPageVisitDataKeyName);
|
|
106
|
-
|
|
107
|
-
// Return page visit data
|
|
108
|
-
return prevPageVisitData;
|
|
109
|
-
} else {
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
} catch (e) {
|
|
116
|
-
_warnToConsole(this._logger, "Stop page visit timer failed: " + dumpObj(e));
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
121
|
+
* Tracks the previous page visit time telemetry (if exists) and starts timing of new page visit time
|
|
122
|
+
* @param currentPageName Name of page to begin timing for visit duration
|
|
123
|
+
* @param currentPageUrl Url of page to begin timing for visit duration
|
|
124
|
+
*/
|
|
125
|
+
public trackPreviousPageVisit(currentPageName: string, currentPageUrl: string): void {
|
|
126
|
+
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
119
127
|
}
|
|
120
128
|
}
|
|
121
129
|
|
|
@@ -131,4 +139,4 @@ export class PageVisitData {
|
|
|
131
139
|
this.pageName = pageName;
|
|
132
140
|
this.pageUrl = pageUrl;
|
|
133
141
|
}
|
|
134
|
-
}
|
|
142
|
+
}
|