@microsoft/applicationinsights-dependencies-js 3.0.0-beta.2303-10 → 3.0.0-beta.2304-07
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/es5/applicationinsights-dependencies-js.cjs.js +4892 -0
- package/browser/es5/applicationinsights-dependencies-js.cjs.js.map +1 -0
- package/browser/es5/applicationinsights-dependencies-js.cjs.min.js +6 -0
- package/browser/es5/applicationinsights-dependencies-js.cjs.min.js.map +1 -0
- package/browser/es5/applicationinsights-dependencies-js.gbl.js +4896 -0
- package/browser/es5/applicationinsights-dependencies-js.gbl.js.map +1 -0
- package/browser/es5/applicationinsights-dependencies-js.gbl.min.js +6 -0
- package/browser/es5/applicationinsights-dependencies-js.gbl.min.js.map +1 -0
- package/browser/es5/applicationinsights-dependencies-js.integrity.json +66 -0
- package/browser/{applicationinsights-dependencies-js.js → es5/applicationinsights-dependencies-js.js} +889 -859
- package/browser/es5/applicationinsights-dependencies-js.js.map +1 -0
- package/browser/es5/applicationinsights-dependencies-js.min.js +6 -0
- package/browser/es5/applicationinsights-dependencies-js.min.js.map +1 -0
- package/dist/{applicationinsights-dependencies-js.js → es5/applicationinsights-dependencies-js.js} +889 -859
- package/dist/es5/applicationinsights-dependencies-js.js.map +1 -0
- package/dist/es5/applicationinsights-dependencies-js.min.js +6 -0
- package/dist/es5/applicationinsights-dependencies-js.min.js.map +1 -0
- package/{dist-esm → dist-es5}/DependencyInitializer.js +1 -1
- package/{dist-esm → dist-es5}/DependencyListener.js +1 -1
- package/{dist-esm → dist-es5}/InternalConstants.js +1 -1
- package/{dist-esm → dist-es5}/__DynamicConstants.js +1 -1
- package/{dist-esm → dist-es5}/ajax.js +5 -5
- package/dist-es5/ajax.js.map +1 -0
- package/{dist-esm → dist-es5}/ajaxRecord.js +1 -1
- package/{dist-esm → dist-es5}/ajaxUtils.js +1 -1
- package/{dist-esm → dist-es5}/applicationinsights-dependencies-js.js +1 -1
- package/package.json +18 -17
- package/tsconfig.json +5 -4
- package/types/applicationinsights-dependencies-js.d.ts +284 -4
- package/{dist/applicationinsights-dependencies-js.d.ts → types/applicationinsights-dependencies-js.namespaced.d.ts} +1 -1
- package/browser/applicationinsights-dependencies-js.integrity.json +0 -26
- package/browser/applicationinsights-dependencies-js.js.map +0 -1
- package/browser/applicationinsights-dependencies-js.min.js +0 -6
- package/browser/applicationinsights-dependencies-js.min.js.map +0 -1
- package/dist/applicationinsights-dependencies-js.api.json +0 -2904
- package/dist/applicationinsights-dependencies-js.api.md +0 -197
- package/dist/applicationinsights-dependencies-js.js.map +0 -1
- package/dist/applicationinsights-dependencies-js.min.js +0 -6
- package/dist/applicationinsights-dependencies-js.min.js.map +0 -1
- package/dist/applicationinsights-dependencies-js.rollup.d.ts +0 -285
- package/dist-esm/ajax.js.map +0 -1
- package/src/DependencyInitializer.ts +0 -49
- package/src/DependencyListener.ts +0 -82
- package/src/InternalConstants.ts +0 -13
- package/src/__DynamicConstants.ts +0 -68
- package/src/ajax.ts +0 -1290
- package/src/ajaxRecord.ts +0 -436
- package/src/ajaxUtils.ts +0 -23
- package/src/applicationinsights-dependencies-js.ts +0 -9
- package/types/DependencyInitializer.d.ts +0 -45
- package/types/DependencyListener.d.ts +0 -69
- package/types/InternalConstants.d.ts +0 -2
- package/types/__DynamicConstants.d.ts +0 -56
- package/types/ajax.d.ts +0 -63
- package/types/ajaxRecord.d.ts +0 -80
- package/types/ajaxUtils.d.ts +0 -3
- package/types/tsdoc-metadata.json +0 -11
- /package/{dist-esm → dist-es5}/DependencyInitializer.js.map +0 -0
- /package/{dist-esm → dist-es5}/DependencyListener.js.map +0 -0
- /package/{dist-esm → dist-es5}/InternalConstants.js.map +0 -0
- /package/{dist-esm → dist-es5}/__DynamicConstants.js.map +0 -0
- /package/{dist-esm → dist-es5}/ajaxRecord.js.map +0 -0
- /package/{dist-esm → dist-es5}/ajaxUtils.js.map +0 -0
- /package/{dist-esm → dist-es5}/applicationinsights-dependencies-js.js.map +0 -0
package/src/ajax.ts
DELETED
|
@@ -1,1290 +0,0 @@
|
|
|
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
|
-
DisabledPropertyName, IConfig, ICorrelationConfig, IDependencyTelemetry, IRequestContext, ITelemetryContext, PropertiesPluginIdentifier,
|
|
7
|
-
RemoteDependencyData, RequestHeaders, correlationIdCanIncludeCorrelationHeader, correlationIdGetCorrelationContext,
|
|
8
|
-
createDistributedTraceContextFromTrace, createTelemetryItem, createTraceParent, dateTimeUtilsNow, eDistributedTracingModes,
|
|
9
|
-
eRequestHeaders, formatTraceParent, isInternalApplicationInsightsEndpoint
|
|
10
|
-
} from "@microsoft/applicationinsights-common";
|
|
11
|
-
import {
|
|
12
|
-
BaseTelemetryPlugin, IAppInsightsCore, IConfigDefaults, IConfiguration, ICustomProperties, IDistributedTraceContext,
|
|
13
|
-
IInstrumentCallDetails, IInstrumentHooksCallbacks, IPlugin, IProcessTelemetryContext, ITelemetryItem, ITelemetryPluginChain,
|
|
14
|
-
InstrumentFunc, InstrumentProto, _eInternalMessageId, _throwInternal, arrForEach, createProcessTelemetryContext, createUniqueNamespace,
|
|
15
|
-
dumpObj, eLoggingSeverity, eventOn, generateW3CId, getExceptionName, getGlobal, getIEVersion, getLocation, getPerformance, isFunction,
|
|
16
|
-
isNullOrUndefined, isString, isXhrSupported, mergeEvtNamespace, onConfigChange, strPrototype, strTrim
|
|
17
|
-
} from "@microsoft/applicationinsights-core-js";
|
|
18
|
-
import { isWebWorker, objFreeze, scheduleTimeout, strIndexOf } from "@nevware21/ts-utils";
|
|
19
|
-
import { DependencyInitializerFunction, IDependencyInitializerDetails, IDependencyInitializerHandler } from "./DependencyInitializer";
|
|
20
|
-
import {
|
|
21
|
-
DependencyListenerFunction, IDependencyHandler, IDependencyListenerContainer, IDependencyListenerDetails, IDependencyListenerHandler
|
|
22
|
-
} from "./DependencyListener";
|
|
23
|
-
import { IAjaxRecordResponse, ajaxRecord } from "./ajaxRecord";
|
|
24
|
-
|
|
25
|
-
const AJAX_MONITOR_PREFIX = "ai.ajxmn.";
|
|
26
|
-
const strDiagLog = "diagLog";
|
|
27
|
-
const strAjaxData = "ajaxData";
|
|
28
|
-
const STR_FETCH = "fetch";
|
|
29
|
-
|
|
30
|
-
const ERROR_HEADER = "Failed to monitor XMLHttpRequest";
|
|
31
|
-
const ERROR_PREFIX = ", monitoring data for this ajax call ";
|
|
32
|
-
const ERROR_POSTFIX = ERROR_PREFIX + "may be incorrect.";
|
|
33
|
-
const ERROR_NOT_SENT = ERROR_PREFIX + "won't be sent.";
|
|
34
|
-
const CORRELATION_HEADER_ERROR = "Failed to get Request-Context correlation header as it may be not included in the response or not accessible.";
|
|
35
|
-
const CUSTOM_REQUEST_CONTEXT_ERROR = "Failed to add custom defined request context as configured call back may missing a null check.";
|
|
36
|
-
const FAILED_TO_CALCULATE_DURATION_ERROR = "Failed to calculate the duration of the ";
|
|
37
|
-
|
|
38
|
-
// Using a global value so that to handle same iKey with multiple app insights instances (mostly for testing)
|
|
39
|
-
let _markCount: number = 0;
|
|
40
|
-
|
|
41
|
-
interface _IInternalDependencyHandler<F> {
|
|
42
|
-
id: number;
|
|
43
|
-
fn: F;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** @Ignore */
|
|
47
|
-
function _supportsFetch(): (input: RequestInfo, init?: RequestInit) => Promise<Response> {
|
|
48
|
-
let _global = getGlobal();
|
|
49
|
-
if (!_global ||
|
|
50
|
-
isNullOrUndefined((_global as any).Request) ||
|
|
51
|
-
isNullOrUndefined((_global as any).Request[strPrototype]) ||
|
|
52
|
-
isNullOrUndefined(_global[STR_FETCH])) {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return _global[STR_FETCH];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Determines whether ajax monitoring can be enabled on this document
|
|
61
|
-
* @returns True if Ajax monitoring is supported on this page, otherwise false
|
|
62
|
-
* @ignore
|
|
63
|
-
*/
|
|
64
|
-
function _supportsAjaxMonitoring(ajaxMonitorInstance:AjaxMonitor): boolean {
|
|
65
|
-
let result = false;
|
|
66
|
-
|
|
67
|
-
if (isXhrSupported()) {
|
|
68
|
-
let proto = XMLHttpRequest[strPrototype];
|
|
69
|
-
result = !isNullOrUndefined(proto) &&
|
|
70
|
-
!isNullOrUndefined(proto.open) && // eslint-disable-line security/detect-non-literal-fs-filename -- false positive
|
|
71
|
-
!isNullOrUndefined(proto.send) &&
|
|
72
|
-
!isNullOrUndefined(proto.abort);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
let ieVer = getIEVersion();
|
|
76
|
-
if (ieVer && ieVer < 9) {
|
|
77
|
-
result = false;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (result) {
|
|
81
|
-
// Disable if the XmlHttpRequest can't be extended or hooked
|
|
82
|
-
try {
|
|
83
|
-
let xhr = new XMLHttpRequest();
|
|
84
|
-
xhr[strAjaxData] = {};
|
|
85
|
-
|
|
86
|
-
// Check that we can update the prototype
|
|
87
|
-
let theOpen = XMLHttpRequest[strPrototype].open;
|
|
88
|
-
XMLHttpRequest[strPrototype].open = theOpen;
|
|
89
|
-
} catch (e) {
|
|
90
|
-
// We can't decorate the xhr object so disable monitoring
|
|
91
|
-
result = false;
|
|
92
|
-
_throwInternalCritical(ajaxMonitorInstance,
|
|
93
|
-
_eInternalMessageId.FailedMonitorAjaxOpen,
|
|
94
|
-
"Failed to enable XMLHttpRequest monitoring, extension is not supported",
|
|
95
|
-
{
|
|
96
|
-
exception: dumpObj(e)
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return result;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** @Ignore */
|
|
105
|
-
function _getFailedAjaxDiagnosticsMessage(xhr: XMLHttpRequestInstrumented): string {
|
|
106
|
-
let result = "";
|
|
107
|
-
try {
|
|
108
|
-
if (xhr && xhr[strAjaxData] && xhr[strAjaxData].requestUrl) {
|
|
109
|
-
result += "(url: '" + xhr[strAjaxData].requestUrl + "')";
|
|
110
|
-
}
|
|
111
|
-
} catch (e) {
|
|
112
|
-
// eslint-disable-next-line no-empty
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return result;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** @ignore */
|
|
119
|
-
function _throwInternalCritical(ajaxMonitorInstance:AjaxMonitor, msgId: _eInternalMessageId, message: string, properties?: Object, isUserAct?: boolean): void {
|
|
120
|
-
_throwInternal(ajaxMonitorInstance[strDiagLog](), eLoggingSeverity.CRITICAL, msgId, message, properties, isUserAct);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** @ignore */
|
|
124
|
-
function _throwInternalWarning(ajaxMonitorInstance:AjaxMonitor, msgId: _eInternalMessageId, message: string, properties?: Object, isUserAct?: boolean): void {
|
|
125
|
-
_throwInternal(ajaxMonitorInstance[strDiagLog](), eLoggingSeverity.WARNING, msgId, message, properties, isUserAct);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/** @Ignore */
|
|
129
|
-
function _createErrorCallbackFunc(ajaxMonitorInstance:AjaxMonitor, internalMessage: _eInternalMessageId, message:string) {
|
|
130
|
-
// tslint:disable-next-line
|
|
131
|
-
return function (args:IInstrumentCallDetails) {
|
|
132
|
-
_throwInternalCritical(ajaxMonitorInstance,
|
|
133
|
-
internalMessage,
|
|
134
|
-
message,
|
|
135
|
-
{
|
|
136
|
-
ajaxDiagnosticsMessage: _getFailedAjaxDiagnosticsMessage(args.inst),
|
|
137
|
-
exception: dumpObj(args.err)
|
|
138
|
-
});
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function _indexOf(value:string, match:string):number {
|
|
143
|
-
if (value && match) {
|
|
144
|
-
return strIndexOf(value, match);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return -1;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function _addHandler<F>(container: _IInternalDependencyHandler<F>[], id: number, theFunc: F): IDependencyHandler {
|
|
151
|
-
let theHandler: _IInternalDependencyHandler<F> = {
|
|
152
|
-
id: id,
|
|
153
|
-
fn: theFunc
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
container.push(theHandler);
|
|
157
|
-
|
|
158
|
-
return {
|
|
159
|
-
remove: () => {
|
|
160
|
-
arrForEach(container, (initializer, idx) => {
|
|
161
|
-
if (initializer.id === theHandler.id) {
|
|
162
|
-
container.splice(idx, 1);
|
|
163
|
-
return -1;
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function _processDependencyContainer<F extends Function, D>(core: IAppInsightsCore, container: _IInternalDependencyHandler<F>[], details: D, message: string) {
|
|
171
|
-
let result = true;
|
|
172
|
-
arrForEach(container, (theFunc, idx) => {
|
|
173
|
-
try {
|
|
174
|
-
if (theFunc.fn.call(null, details) === false) {
|
|
175
|
-
result = false;
|
|
176
|
-
}
|
|
177
|
-
} catch (e) {
|
|
178
|
-
_throwInternal(
|
|
179
|
-
core && core.logger,
|
|
180
|
-
eLoggingSeverity.CRITICAL,
|
|
181
|
-
_eInternalMessageId.TelemetryInitializerFailed,
|
|
182
|
-
"Dependency " + message + " [#" + idx + "] failed: " + getExceptionName(e),
|
|
183
|
-
{ exception: dumpObj(e) }, true);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
return result;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function _processDependencyListeners(listeners: _IInternalDependencyHandler<DependencyListenerFunction>[], core: IAppInsightsCore, ajaxData: ajaxRecord, xhr: XMLHttpRequest, input?: Request | string, init?: RequestInit): void {
|
|
191
|
-
var initializersCount = listeners.length;
|
|
192
|
-
if (initializersCount > 0) {
|
|
193
|
-
let details: IDependencyListenerDetails = {
|
|
194
|
-
core: core,
|
|
195
|
-
xhr: xhr,
|
|
196
|
-
input: input,
|
|
197
|
-
init: init,
|
|
198
|
-
traceId: ajaxData.traceID,
|
|
199
|
-
spanId: ajaxData.spanID,
|
|
200
|
-
traceFlags: ajaxData.traceFlags,
|
|
201
|
-
context: ajaxData.context || {},
|
|
202
|
-
aborted: !!ajaxData.aborted
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
_processDependencyContainer(core, listeners, details, "listener");
|
|
206
|
-
|
|
207
|
-
ajaxData.traceID = details.traceId;
|
|
208
|
-
ajaxData.spanID = details.spanId;
|
|
209
|
-
ajaxData.traceFlags = details.traceFlags;
|
|
210
|
-
ajaxData.context = details.context;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
export interface XMLHttpRequestInstrumented extends XMLHttpRequest {
|
|
215
|
-
ajaxData: ajaxRecord;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const BLOB_CORE = "*.blob.core.";
|
|
219
|
-
|
|
220
|
-
export const DfltAjaxCorrelationHeaderExDomains = objFreeze([
|
|
221
|
-
BLOB_CORE + "windows.net",
|
|
222
|
-
BLOB_CORE + "chinacloudapi.cn",
|
|
223
|
-
BLOB_CORE + "cloudapi.de",
|
|
224
|
-
BLOB_CORE + "usgovcloudapi.net"
|
|
225
|
-
]);
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const _internalExcludeEndpoints = [
|
|
229
|
-
/https:\/\/[^\/]*(\.pipe\.aria|aria\.pipe|events\.data|collector\.azure)\.[^\/]+\/(OneCollector\/1|Collector\/3)\.0/i
|
|
230
|
-
];
|
|
231
|
-
|
|
232
|
-
export interface IDependenciesPlugin extends IDependencyListenerContainer {
|
|
233
|
-
/**
|
|
234
|
-
* Logs dependency call
|
|
235
|
-
* @param dependencyData - dependency data object
|
|
236
|
-
*/
|
|
237
|
-
trackDependencyData(dependency: IDependencyTelemetry): void;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export interface IInstrumentationRequirements extends IDependenciesPlugin {
|
|
241
|
-
includeCorrelationHeaders: (ajaxData: ajaxRecord, input?: Request | string, init?: RequestInit, xhr?: XMLHttpRequestInstrumented) => any;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const _defaultConfig: IConfigDefaults<ICorrelationConfig> = objFreeze({
|
|
245
|
-
maxAjaxCallsPerView: 500,
|
|
246
|
-
disableAjaxTracking: false,
|
|
247
|
-
disableFetchTracking: false,
|
|
248
|
-
excludeRequestFromAutoTrackingPatterns: undefined,
|
|
249
|
-
disableCorrelationHeaders: false,
|
|
250
|
-
distributedTracingMode: eDistributedTracingModes.AI_AND_W3C,
|
|
251
|
-
correlationHeaderExcludedDomains: DfltAjaxCorrelationHeaderExDomains,
|
|
252
|
-
correlationHeaderDomains: undefined,
|
|
253
|
-
correlationHeaderExcludePatterns: undefined,
|
|
254
|
-
appId: undefined,
|
|
255
|
-
enableCorsCorrelation: false,
|
|
256
|
-
enableRequestHeaderTracking: false,
|
|
257
|
-
enableResponseHeaderTracking: false,
|
|
258
|
-
enableAjaxErrorStatusText: false,
|
|
259
|
-
enableAjaxPerfTracking: false,
|
|
260
|
-
maxAjaxPerfLookupAttempts: 3,
|
|
261
|
-
ajaxPerfLookupDelay: 25,
|
|
262
|
-
ignoreHeaders:[
|
|
263
|
-
"Authorization",
|
|
264
|
-
"X-API-Key",
|
|
265
|
-
"WWW-Authenticate"
|
|
266
|
-
],
|
|
267
|
-
addRequestContext: undefined,
|
|
268
|
-
addIntEndpoints: true
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
export class AjaxMonitor extends BaseTelemetryPlugin implements IDependenciesPlugin, IInstrumentationRequirements, IDependencyListenerContainer {
|
|
272
|
-
|
|
273
|
-
public static identifier: string = "AjaxDependencyPlugin";
|
|
274
|
-
|
|
275
|
-
public identifier: string = AjaxMonitor.identifier;
|
|
276
|
-
priority: number = 120;
|
|
277
|
-
|
|
278
|
-
constructor() {
|
|
279
|
-
super();
|
|
280
|
-
let _fetchInitialized: boolean; // fetch monitoring initialized
|
|
281
|
-
let _xhrInitialized: boolean; // XHR monitoring initialized
|
|
282
|
-
let _currentWindowHost: string;
|
|
283
|
-
let _extensionConfig: ICorrelationConfig;
|
|
284
|
-
let _enableRequestHeaderTracking: boolean;
|
|
285
|
-
let _enableAjaxErrorStatusText: boolean;
|
|
286
|
-
let _trackAjaxAttempts: number;
|
|
287
|
-
let _context: ITelemetryContext;
|
|
288
|
-
let _isUsingW3CHeaders: boolean;
|
|
289
|
-
let _isUsingAIHeaders: boolean;
|
|
290
|
-
let _markPrefix: string;
|
|
291
|
-
let _enableAjaxPerfTracking: boolean;
|
|
292
|
-
let _maxAjaxCallsPerView: number;
|
|
293
|
-
let _enableResponseHeaderTracking: boolean;
|
|
294
|
-
let _disabledUrls: any;
|
|
295
|
-
let _disableAjaxTracking: boolean;
|
|
296
|
-
let _disableFetchTracking: boolean;
|
|
297
|
-
let _excludeRequestFromAutoTrackingPatterns: (string | RegExp)[];
|
|
298
|
-
let _addRequestContext: (requestContext?: IRequestContext) => ICustomProperties;
|
|
299
|
-
let _evtNamespace: string | string[];
|
|
300
|
-
let _dependencyHandlerId: number;
|
|
301
|
-
let _dependencyListeners: _IInternalDependencyHandler<DependencyListenerFunction>[];
|
|
302
|
-
let _dependencyInitializers: _IInternalDependencyHandler<DependencyInitializerFunction>[];
|
|
303
|
-
let _ignoreHeaders: string[];
|
|
304
|
-
let _maxAjaxPerfLookupAttempts: number;
|
|
305
|
-
let _ajaxPerfLookupDelay: number;
|
|
306
|
-
let _distributedTracingMode: eDistributedTracingModes;
|
|
307
|
-
let _appId: string;
|
|
308
|
-
let _polyfillInitialized: boolean;
|
|
309
|
-
|
|
310
|
-
dynamicProto(AjaxMonitor, this, (_self, _base) => {
|
|
311
|
-
let _addHook = _base._addHook;
|
|
312
|
-
|
|
313
|
-
_initDefaults();
|
|
314
|
-
|
|
315
|
-
_self.initialize = (config: IConfiguration & IConfig, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?:ITelemetryPluginChain) => {
|
|
316
|
-
if (!_self.isInitialized()) {
|
|
317
|
-
_base.initialize(config, core, extensions, pluginChain);
|
|
318
|
-
|
|
319
|
-
_evtNamespace = mergeEvtNamespace(createUniqueNamespace("ajax"), core && core.evtNamespace && core.evtNamespace());
|
|
320
|
-
|
|
321
|
-
_populateDefaults(config);
|
|
322
|
-
|
|
323
|
-
_instrumentXhr();
|
|
324
|
-
_instrumentFetch();
|
|
325
|
-
_populateContext();
|
|
326
|
-
}
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
_self._doTeardown = () => {
|
|
330
|
-
_initDefaults();
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
_self.trackDependencyData = (dependency: IDependencyTelemetry, properties?: { [key: string]: any }) => {
|
|
334
|
-
_reportDependencyInternal(_dependencyInitializers, _self.core, null, dependency, properties);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
_self.includeCorrelationHeaders = (ajaxData: ajaxRecord, input?: Request | string, init?: RequestInit, xhr?: XMLHttpRequestInstrumented): any => {
|
|
338
|
-
// Test Hook to allow the overriding of the location host
|
|
339
|
-
let currentWindowHost = _self["_currentWindowHost"] || _currentWindowHost;
|
|
340
|
-
|
|
341
|
-
_processDependencyListeners(_dependencyListeners, _self.core, ajaxData, xhr, input, init);
|
|
342
|
-
|
|
343
|
-
if (input) { // Fetch
|
|
344
|
-
if (correlationIdCanIncludeCorrelationHeader(_extensionConfig, ajaxData.getAbsoluteUrl(), currentWindowHost)) {
|
|
345
|
-
if (!init) {
|
|
346
|
-
init = {};
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// init headers override original request headers
|
|
350
|
-
// so, if they exist use only them, otherwise use request's because they should have been applied in the first place
|
|
351
|
-
// not using original request headers will result in them being lost
|
|
352
|
-
let headers = new Headers(init.headers || (input instanceof Request ? (input.headers || {}) : {}));
|
|
353
|
-
if (_isUsingAIHeaders) {
|
|
354
|
-
const id = "|" + ajaxData.traceID + "." + ajaxData.spanID;
|
|
355
|
-
headers.set(RequestHeaders[eRequestHeaders.requestIdHeader], id);
|
|
356
|
-
if (_enableRequestHeaderTracking) {
|
|
357
|
-
ajaxData.requestHeaders[RequestHeaders[eRequestHeaders.requestIdHeader]] = id;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
const appId: string = _appId ||(_context && _context.appId());
|
|
361
|
-
if (appId) {
|
|
362
|
-
headers.set(RequestHeaders[eRequestHeaders.requestContextHeader], RequestHeaders[eRequestHeaders.requestContextAppIdFormat] + appId);
|
|
363
|
-
if (_enableRequestHeaderTracking) {
|
|
364
|
-
ajaxData.requestHeaders[RequestHeaders[eRequestHeaders.requestContextHeader]] = RequestHeaders[eRequestHeaders.requestContextAppIdFormat] + appId;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
if (_isUsingW3CHeaders) {
|
|
368
|
-
let traceFlags = ajaxData.traceFlags;
|
|
369
|
-
if (isNullOrUndefined(traceFlags)) {
|
|
370
|
-
traceFlags = 0x01;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const traceParent = formatTraceParent(createTraceParent(ajaxData.traceID, ajaxData.spanID, traceFlags));
|
|
374
|
-
headers.set(RequestHeaders[eRequestHeaders.traceParentHeader], traceParent);
|
|
375
|
-
if (_enableRequestHeaderTracking) {
|
|
376
|
-
ajaxData.requestHeaders[RequestHeaders[eRequestHeaders.traceParentHeader]] = traceParent;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
init.headers = headers;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
return init;
|
|
384
|
-
} else if (xhr) { // XHR
|
|
385
|
-
if (correlationIdCanIncludeCorrelationHeader(_extensionConfig, ajaxData.getAbsoluteUrl(), currentWindowHost)) {
|
|
386
|
-
if (_isUsingAIHeaders) {
|
|
387
|
-
const id = "|" + ajaxData.traceID + "." + ajaxData.spanID;
|
|
388
|
-
xhr.setRequestHeader(RequestHeaders[eRequestHeaders.requestIdHeader], id);
|
|
389
|
-
if (_enableRequestHeaderTracking) {
|
|
390
|
-
ajaxData.requestHeaders[RequestHeaders[eRequestHeaders.requestIdHeader]] = id;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
const appId = _appId || (_context && _context.appId());
|
|
394
|
-
if (appId) {
|
|
395
|
-
xhr.setRequestHeader(RequestHeaders[eRequestHeaders.requestContextHeader], RequestHeaders[eRequestHeaders.requestContextAppIdFormat] + appId);
|
|
396
|
-
if (_enableRequestHeaderTracking) {
|
|
397
|
-
ajaxData.requestHeaders[RequestHeaders[eRequestHeaders.requestContextHeader]] = RequestHeaders[eRequestHeaders.requestContextAppIdFormat] + appId;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
if (_isUsingW3CHeaders) {
|
|
401
|
-
let traceFlags = ajaxData.traceFlags;
|
|
402
|
-
if (isNullOrUndefined(traceFlags)) {
|
|
403
|
-
traceFlags = 0x01;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
const traceParent = formatTraceParent(createTraceParent(ajaxData.traceID, ajaxData.spanID, traceFlags));
|
|
407
|
-
xhr.setRequestHeader(RequestHeaders[eRequestHeaders.traceParentHeader], traceParent);
|
|
408
|
-
if (_enableRequestHeaderTracking) {
|
|
409
|
-
ajaxData.requestHeaders[RequestHeaders[eRequestHeaders.traceParentHeader]] = traceParent;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
return xhr;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
return undefined;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
_self.trackDependencyDataInternal = (dependency: IDependencyTelemetry, properties?: { [key: string]: any }, systemProperties?: { [key: string]: any }) => {
|
|
421
|
-
if (_maxAjaxCallsPerView === -1 || _trackAjaxAttempts < _maxAjaxCallsPerView) {
|
|
422
|
-
// Hack since expected format in w3c mode is |abc.def.
|
|
423
|
-
// Non-w3c format is |abc.def
|
|
424
|
-
// @todo Remove if better solution is available, e.g. handle in portal
|
|
425
|
-
if ((_distributedTracingMode === eDistributedTracingModes.W3C
|
|
426
|
-
|| _distributedTracingMode === eDistributedTracingModes.AI_AND_W3C)
|
|
427
|
-
&& typeof dependency.id === "string" && dependency.id[dependency.id.length - 1] !== "."
|
|
428
|
-
) {
|
|
429
|
-
dependency.id += ".";
|
|
430
|
-
}
|
|
431
|
-
if (isNullOrUndefined(dependency.startTime)) {
|
|
432
|
-
dependency.startTime = new Date();
|
|
433
|
-
}
|
|
434
|
-
const item = createTelemetryItem<IDependencyTelemetry>(
|
|
435
|
-
dependency,
|
|
436
|
-
RemoteDependencyData.dataType,
|
|
437
|
-
RemoteDependencyData.envelopeType,
|
|
438
|
-
_self[strDiagLog](),
|
|
439
|
-
properties,
|
|
440
|
-
systemProperties);
|
|
441
|
-
|
|
442
|
-
_self.core.track(item);
|
|
443
|
-
} else if (_trackAjaxAttempts === _maxAjaxCallsPerView) {
|
|
444
|
-
_throwInternalCritical(_self,
|
|
445
|
-
_eInternalMessageId.MaxAjaxPerPVExceeded,
|
|
446
|
-
"Maximum ajax per page view limit reached, ajax monitoring is paused until the next trackPageView(). In order to increase the limit set the maxAjaxCallsPerView configuration parameter.",
|
|
447
|
-
true);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
++_trackAjaxAttempts;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
_self.addDependencyListener = (dependencyListener: DependencyListenerFunction): IDependencyListenerHandler => {
|
|
454
|
-
return _addHandler(_dependencyListeners, _dependencyHandlerId++, dependencyListener);
|
|
455
|
-
};
|
|
456
|
-
|
|
457
|
-
_self.addDependencyInitializer = (dependencyInitializer: DependencyInitializerFunction): IDependencyInitializerHandler => {
|
|
458
|
-
return _addHandler(_dependencyInitializers, _dependencyHandlerId++, dependencyInitializer);
|
|
459
|
-
};
|
|
460
|
-
|
|
461
|
-
function _initDefaults() {
|
|
462
|
-
let location = getLocation();
|
|
463
|
-
_fetchInitialized = false; // fetch monitoring initialized
|
|
464
|
-
_xhrInitialized = false; // XHR monitoring initialized
|
|
465
|
-
_polyfillInitialized = false; // polyfill monitoring initialized
|
|
466
|
-
_currentWindowHost = location && location.host && location.host.toLowerCase();
|
|
467
|
-
_extensionConfig = null;
|
|
468
|
-
_enableRequestHeaderTracking = false;
|
|
469
|
-
_enableAjaxErrorStatusText = false;
|
|
470
|
-
_trackAjaxAttempts = 0;
|
|
471
|
-
_context = null;
|
|
472
|
-
_isUsingW3CHeaders = false;
|
|
473
|
-
_isUsingAIHeaders = false;
|
|
474
|
-
_markPrefix = null;
|
|
475
|
-
_enableAjaxPerfTracking = false;
|
|
476
|
-
_maxAjaxCallsPerView = 0;
|
|
477
|
-
_enableResponseHeaderTracking = false;
|
|
478
|
-
_disabledUrls = {};
|
|
479
|
-
_disableAjaxTracking = false;
|
|
480
|
-
_disableFetchTracking = false;
|
|
481
|
-
|
|
482
|
-
_excludeRequestFromAutoTrackingPatterns = null;
|
|
483
|
-
_addRequestContext = null;
|
|
484
|
-
_evtNamespace = null;
|
|
485
|
-
_dependencyHandlerId = 0;
|
|
486
|
-
_dependencyListeners = [];
|
|
487
|
-
_dependencyInitializers = [];
|
|
488
|
-
_ignoreHeaders = null;
|
|
489
|
-
_maxAjaxPerfLookupAttempts = 1;
|
|
490
|
-
_ajaxPerfLookupDelay = 1;
|
|
491
|
-
_distributedTracingMode = eDistributedTracingModes.AI_AND_W3C;
|
|
492
|
-
_appId = null;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
function _populateDefaults(config: IConfiguration) {
|
|
496
|
-
_self._addHook(onConfigChange(config, (details) => {
|
|
497
|
-
let config = details.cfg;
|
|
498
|
-
let ctx = createProcessTelemetryContext(null, config, _self.core);
|
|
499
|
-
_extensionConfig = ctx.getExtCfg(AjaxMonitor.identifier, _defaultConfig);
|
|
500
|
-
|
|
501
|
-
_distributedTracingMode = _extensionConfig.distributedTracingMode;
|
|
502
|
-
_enableRequestHeaderTracking = _extensionConfig.enableRequestHeaderTracking;
|
|
503
|
-
_enableAjaxErrorStatusText = _extensionConfig.enableAjaxErrorStatusText;
|
|
504
|
-
_enableAjaxPerfTracking = _extensionConfig.enableAjaxPerfTracking;
|
|
505
|
-
_maxAjaxCallsPerView = _extensionConfig.maxAjaxCallsPerView;
|
|
506
|
-
_excludeRequestFromAutoTrackingPatterns = [].concat(_extensionConfig.excludeRequestFromAutoTrackingPatterns || [], _extensionConfig.addIntEndpoints !== false ? _internalExcludeEndpoints : []);
|
|
507
|
-
_addRequestContext = _extensionConfig.addRequestContext;
|
|
508
|
-
|
|
509
|
-
_isUsingAIHeaders = _distributedTracingMode === eDistributedTracingModes.AI || _distributedTracingMode === eDistributedTracingModes.AI_AND_W3C;
|
|
510
|
-
_isUsingW3CHeaders = _distributedTracingMode === eDistributedTracingModes.AI_AND_W3C || _distributedTracingMode === eDistributedTracingModes.W3C;
|
|
511
|
-
|
|
512
|
-
if (_enableAjaxPerfTracking) {
|
|
513
|
-
let iKey = config.instrumentationKey || "unkwn";
|
|
514
|
-
if (iKey.length > 5) {
|
|
515
|
-
_markPrefix = AJAX_MONITOR_PREFIX + iKey.substring(iKey.length - 5) + ".";
|
|
516
|
-
} else {
|
|
517
|
-
_markPrefix = AJAX_MONITOR_PREFIX + iKey + ".";
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
_disableAjaxTracking = !!_extensionConfig.disableAjaxTracking;
|
|
522
|
-
_maxAjaxPerfLookupAttempts = _extensionConfig.maxAjaxPerfLookupAttempts;
|
|
523
|
-
_ajaxPerfLookupDelay = _extensionConfig.ajaxPerfLookupDelay;
|
|
524
|
-
_ignoreHeaders = _extensionConfig.ignoreHeaders;
|
|
525
|
-
_appId = _extensionConfig.appId;
|
|
526
|
-
}));
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
function _populateContext() {
|
|
530
|
-
let propExt = _self.core.getPlugin<any>(PropertiesPluginIdentifier);
|
|
531
|
-
if (propExt) {
|
|
532
|
-
_context = propExt.plugin.context; // we could move IPropertiesPlugin to common as well
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// discard the header if it's defined as ignoreHeaders in ICorrelationConfig
|
|
537
|
-
function _canIncludeHeaders(header: string) {
|
|
538
|
-
let rlt = true;
|
|
539
|
-
if (header || _ignoreHeaders) {
|
|
540
|
-
arrForEach(_ignoreHeaders, (key => {
|
|
541
|
-
if (key.toLowerCase() === header.toLowerCase()) {
|
|
542
|
-
rlt = false;
|
|
543
|
-
return -1;
|
|
544
|
-
}
|
|
545
|
-
}))
|
|
546
|
-
}
|
|
547
|
-
return rlt;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
// Fetch Stuff
|
|
551
|
-
function _instrumentFetch(): void {
|
|
552
|
-
let fetch = _supportsFetch();
|
|
553
|
-
if (!fetch) {
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
let global = getGlobal();
|
|
558
|
-
let isPolyfill = (fetch as any).polyfill;
|
|
559
|
-
_self._addHook(onConfigChange(_extensionConfig, () => {
|
|
560
|
-
_disableFetchTracking = !!_extensionConfig.disableFetchTracking;
|
|
561
|
-
_enableResponseHeaderTracking = _extensionConfig.enableResponseHeaderTracking;
|
|
562
|
-
|
|
563
|
-
if (!_disableFetchTracking && !_fetchInitialized) {
|
|
564
|
-
_addHook(InstrumentFunc(global, STR_FETCH, {
|
|
565
|
-
ns: _evtNamespace,
|
|
566
|
-
// Add request hook
|
|
567
|
-
req: (callDetails: IInstrumentCallDetails, input, init) => {
|
|
568
|
-
let fetchData: ajaxRecord;
|
|
569
|
-
if (!_disableFetchTracking && _fetchInitialized &&
|
|
570
|
-
!_isDisabledRequest(null, input, init) &&
|
|
571
|
-
// If we have a polyfil and XHR instrumented then let XHR report otherwise we get duplicates
|
|
572
|
-
!(isPolyfill && _xhrInitialized)) {
|
|
573
|
-
let ctx = callDetails.ctx();
|
|
574
|
-
fetchData = _createFetchRecord(input, init);
|
|
575
|
-
let newInit = _self.includeCorrelationHeaders(fetchData, input, init);
|
|
576
|
-
if (newInit !== init) {
|
|
577
|
-
callDetails.set(1, newInit);
|
|
578
|
-
}
|
|
579
|
-
ctx.data = fetchData;
|
|
580
|
-
}
|
|
581
|
-
},
|
|
582
|
-
rsp: (callDetails: IInstrumentCallDetails, input) => {
|
|
583
|
-
if (!_disableFetchTracking) {
|
|
584
|
-
let fetchData = callDetails.ctx().data;
|
|
585
|
-
if (fetchData) {
|
|
586
|
-
// Replace the result with the new promise from this code
|
|
587
|
-
callDetails.rslt = callDetails.rslt.then((response: any) => {
|
|
588
|
-
_reportFetchMetrics(callDetails, (response||{}).status, input, response, fetchData, () => {
|
|
589
|
-
let ajaxResponse:IAjaxRecordResponse = {
|
|
590
|
-
statusText: (response||{}).statusText,
|
|
591
|
-
headerMap: null,
|
|
592
|
-
correlationContext: _getFetchCorrelationContext(response)
|
|
593
|
-
};
|
|
594
|
-
|
|
595
|
-
if (_enableResponseHeaderTracking && response) {
|
|
596
|
-
const responseHeaderMap = {};
|
|
597
|
-
response.headers.forEach((value: string, name: string) => { // @skip-minify
|
|
598
|
-
if (_canIncludeHeaders(name)) {
|
|
599
|
-
responseHeaderMap[name] = value;
|
|
600
|
-
}
|
|
601
|
-
});
|
|
602
|
-
|
|
603
|
-
ajaxResponse.headerMap = responseHeaderMap;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
return ajaxResponse;
|
|
607
|
-
});
|
|
608
|
-
|
|
609
|
-
return response;
|
|
610
|
-
})
|
|
611
|
-
.catch((reason: any) => {
|
|
612
|
-
_reportFetchMetrics(callDetails, 0, input, null, fetchData, null, { error: reason.message || dumpObj(reason) });
|
|
613
|
-
throw reason;
|
|
614
|
-
});
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
},
|
|
618
|
-
// Create an error callback to report any hook errors
|
|
619
|
-
hkErr: _createErrorCallbackFunc(_self, _eInternalMessageId.FailedMonitorAjaxOpen,
|
|
620
|
-
"Failed to monitor Window.fetch" + ERROR_POSTFIX)
|
|
621
|
-
}, true, isWebWorker()));
|
|
622
|
-
|
|
623
|
-
_fetchInitialized = true;
|
|
624
|
-
} else if (isPolyfill && !_polyfillInitialized) {
|
|
625
|
-
// If fetch is a polyfill we need to capture the request to ensure that we correctly track
|
|
626
|
-
// disabled request URLS (i.e. internal urls) to ensure we don't end up in a constant loop
|
|
627
|
-
// of reporting ourselves, for example React Native uses a polyfill for fetch
|
|
628
|
-
// Note: Polyfill implementations that don't support the "polyfill" tag are not supported
|
|
629
|
-
// the workaround is to add a polyfill property to your fetch implementation before initializing
|
|
630
|
-
// App Insights
|
|
631
|
-
_addHook(InstrumentFunc(global, STR_FETCH, {
|
|
632
|
-
ns: _evtNamespace,
|
|
633
|
-
req: (callDetails: IInstrumentCallDetails, input, init) => {
|
|
634
|
-
// Just call so that we record any disabled URL
|
|
635
|
-
_isDisabledRequest(null, input, init);
|
|
636
|
-
}
|
|
637
|
-
}));
|
|
638
|
-
_polyfillInitialized = true;
|
|
639
|
-
}
|
|
640
|
-
}));
|
|
641
|
-
|
|
642
|
-
if (isPolyfill) {
|
|
643
|
-
// retag the instrumented fetch with the same polyfill settings this is mostly for testing
|
|
644
|
-
// But also supports multiple App Insights usages
|
|
645
|
-
(global[STR_FETCH] as any).polyfill = isPolyfill;
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
function _hookProto(target: any, funcName: string, callbacks: IInstrumentHooksCallbacks) {
|
|
650
|
-
_addHook(InstrumentProto(target, funcName, callbacks));
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
function _instrumentXhr():void {
|
|
654
|
-
if (!_supportsAjaxMonitoring(_self)) {
|
|
655
|
-
return;
|
|
656
|
-
}
|
|
657
|
-
_self._addHook(onConfigChange(_extensionConfig, () => {
|
|
658
|
-
_disableAjaxTracking = !!_extensionConfig.disableAjaxTracking;
|
|
659
|
-
_enableRequestHeaderTracking = _extensionConfig.enableRequestHeaderTracking;
|
|
660
|
-
|
|
661
|
-
if (!_disableAjaxTracking && !_xhrInitialized) {
|
|
662
|
-
// Instrument open
|
|
663
|
-
_hookProto(XMLHttpRequest, "open", {
|
|
664
|
-
ns: _evtNamespace,
|
|
665
|
-
req: (args:IInstrumentCallDetails, method:string, url:string, async?:boolean) => {
|
|
666
|
-
if (!_disableAjaxTracking) {
|
|
667
|
-
let xhr = args.inst as XMLHttpRequestInstrumented;
|
|
668
|
-
let ajaxData = xhr[strAjaxData];
|
|
669
|
-
if (!_isDisabledRequest(xhr, url) && _isMonitoredXhrInstance(xhr, true)) {
|
|
670
|
-
if (!ajaxData || !ajaxData.xhrMonitoringState.openDone) {
|
|
671
|
-
// Only create a single ajaxData (even when multiple AI instances are running)
|
|
672
|
-
_openHandler(xhr, method, url, async);
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
// always attach to the on ready state change (required for handling multiple instances)
|
|
676
|
-
_attachToOnReadyStateChange(xhr);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
},
|
|
680
|
-
hkErr: _createErrorCallbackFunc(_self, _eInternalMessageId.FailedMonitorAjaxOpen,
|
|
681
|
-
ERROR_HEADER + ".open" + ERROR_POSTFIX)
|
|
682
|
-
});
|
|
683
|
-
|
|
684
|
-
// Instrument send
|
|
685
|
-
_hookProto(XMLHttpRequest, "send", {
|
|
686
|
-
ns: _evtNamespace,
|
|
687
|
-
req: (args:IInstrumentCallDetails, context?: Document | BodyInit | null) => {
|
|
688
|
-
if (!_disableAjaxTracking) {
|
|
689
|
-
let xhr = args.inst as XMLHttpRequestInstrumented;
|
|
690
|
-
let ajaxData = xhr[strAjaxData];
|
|
691
|
-
if (_isMonitoredXhrInstance(xhr) && !ajaxData.xhrMonitoringState.sendDone) {
|
|
692
|
-
_createMarkId("xhr", ajaxData);
|
|
693
|
-
ajaxData.requestSentTime = dateTimeUtilsNow();
|
|
694
|
-
_self.includeCorrelationHeaders(ajaxData, undefined, undefined, xhr);
|
|
695
|
-
ajaxData.xhrMonitoringState.sendDone = true;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
},
|
|
699
|
-
hkErr: _createErrorCallbackFunc(_self, _eInternalMessageId.FailedMonitorAjaxSend,
|
|
700
|
-
ERROR_HEADER + ERROR_POSTFIX)
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
// Instrument abort
|
|
704
|
-
_hookProto(XMLHttpRequest, "abort", {
|
|
705
|
-
ns: _evtNamespace,
|
|
706
|
-
req: (args:IInstrumentCallDetails) => {
|
|
707
|
-
if (!_disableAjaxTracking) {
|
|
708
|
-
let xhr = args.inst as XMLHttpRequestInstrumented;
|
|
709
|
-
let ajaxData = xhr[strAjaxData];
|
|
710
|
-
if (_isMonitoredXhrInstance(xhr) && !ajaxData.xhrMonitoringState.abortDone) {
|
|
711
|
-
ajaxData.aborted = 1;
|
|
712
|
-
ajaxData.xhrMonitoringState.abortDone = true;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
},
|
|
716
|
-
hkErr: _createErrorCallbackFunc(_self, _eInternalMessageId.FailedMonitorAjaxAbort,
|
|
717
|
-
ERROR_HEADER + ".abort" + ERROR_POSTFIX)
|
|
718
|
-
});
|
|
719
|
-
|
|
720
|
-
// Instrument setRequestHeader
|
|
721
|
-
_hookProto(XMLHttpRequest, "setRequestHeader", {
|
|
722
|
-
ns: _evtNamespace,
|
|
723
|
-
req: (args: IInstrumentCallDetails, header: string, value: string) => {
|
|
724
|
-
if (!_disableAjaxTracking && _enableRequestHeaderTracking) {
|
|
725
|
-
let xhr = args.inst as XMLHttpRequestInstrumented;
|
|
726
|
-
if (_isMonitoredXhrInstance(xhr) && _canIncludeHeaders(header)) {
|
|
727
|
-
xhr[strAjaxData].requestHeaders[header] = value;
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
},
|
|
731
|
-
hkErr: _createErrorCallbackFunc(_self, _eInternalMessageId.FailedMonitorAjaxSetRequestHeader,
|
|
732
|
-
ERROR_HEADER + ".setRequestHeader" + ERROR_POSTFIX)
|
|
733
|
-
});
|
|
734
|
-
|
|
735
|
-
_xhrInitialized = true;
|
|
736
|
-
}
|
|
737
|
-
}));
|
|
738
|
-
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
function _isDisabledRequest(xhr?: XMLHttpRequestInstrumented, request?: Request | string, init?: RequestInit) {
|
|
742
|
-
let isDisabled = false;
|
|
743
|
-
let theUrl:string = ((!isString(request) ? ((request ||{}) as Request).url || "" : request as string) ||"").toLowerCase();
|
|
744
|
-
|
|
745
|
-
// check excludeRequestFromAutoTrackingPatterns before stripping off any query string
|
|
746
|
-
arrForEach(_excludeRequestFromAutoTrackingPatterns, (regex: string | RegExp) => {
|
|
747
|
-
let theRegex = regex;
|
|
748
|
-
if (isString(regex)) {
|
|
749
|
-
theRegex = new RegExp(regex);
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
if (!isDisabled) {
|
|
753
|
-
isDisabled = (theRegex as RegExp).test(theUrl);
|
|
754
|
-
}
|
|
755
|
-
});
|
|
756
|
-
|
|
757
|
-
// if request url matches with exclude regex pattern, return true and no need to check for headers
|
|
758
|
-
if (isDisabled) {
|
|
759
|
-
return isDisabled;
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
let idx = _indexOf(theUrl, "?");
|
|
763
|
-
let idx2 = _indexOf(theUrl, "#");
|
|
764
|
-
if (idx === -1 || (idx2 !== -1 && idx2 < idx)) {
|
|
765
|
-
idx = idx2;
|
|
766
|
-
}
|
|
767
|
-
if (idx !== -1) {
|
|
768
|
-
// Strip off any Query string
|
|
769
|
-
theUrl = theUrl.substring(0, idx);
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
// check that this instance is not not used by ajax call performed inside client side monitoring to send data to collector
|
|
773
|
-
if (!isNullOrUndefined(xhr)) {
|
|
774
|
-
// Look on the XMLHttpRequest of the URL string value
|
|
775
|
-
isDisabled = xhr[DisabledPropertyName] === true || theUrl[DisabledPropertyName] === true;
|
|
776
|
-
} else if (!isNullOrUndefined(request)) { // fetch
|
|
777
|
-
// Look for DisabledPropertyName in either Request or RequestInit
|
|
778
|
-
isDisabled = (typeof request === "object" ? request[DisabledPropertyName] === true : false) ||
|
|
779
|
-
(init ? init[DisabledPropertyName] === true : false);
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
// Also add extra check just in case the XHR or fetch objects where not decorated with the DisableProperty due to sealing or freezing
|
|
783
|
-
if (!isDisabled && theUrl && isInternalApplicationInsightsEndpoint(theUrl)) {
|
|
784
|
-
isDisabled = true;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
if (isDisabled) {
|
|
788
|
-
// Add the disabled url if not present
|
|
789
|
-
if (!_disabledUrls[theUrl]) {
|
|
790
|
-
_disabledUrls[theUrl] = 1;
|
|
791
|
-
}
|
|
792
|
-
} else {
|
|
793
|
-
// Check to see if the url is listed as disabled
|
|
794
|
-
if (_disabledUrls[theUrl]) {
|
|
795
|
-
isDisabled = true;
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
return isDisabled;
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/// <summary>Verifies that particalar instance of XMLHttpRequest needs to be monitored</summary>
|
|
803
|
-
/// <param name="excludeAjaxDataValidation">Optional parameter. True if ajaxData must be excluded from verification</param>
|
|
804
|
-
/// <returns type="bool">True if instance needs to be monitored, otherwise false</returns>
|
|
805
|
-
function _isMonitoredXhrInstance(xhr: XMLHttpRequestInstrumented, excludeAjaxDataValidation?: boolean): boolean {
|
|
806
|
-
let ajaxValidation = true;
|
|
807
|
-
let initialized = _xhrInitialized;
|
|
808
|
-
if (!isNullOrUndefined(xhr)) {
|
|
809
|
-
ajaxValidation = excludeAjaxDataValidation === true || !isNullOrUndefined(xhr[strAjaxData]);
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
// checking to see that all interested functions on xhr were instrumented
|
|
813
|
-
return initialized
|
|
814
|
-
// checking on ajaxData to see that it was not removed in user code
|
|
815
|
-
&& ajaxValidation;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
function _getDistributedTraceCtx(): IDistributedTraceContext {
|
|
819
|
-
let distributedTraceCtx: IDistributedTraceContext = null;
|
|
820
|
-
if (_self.core && _self.core.getTraceCtx) {
|
|
821
|
-
distributedTraceCtx = _self.core.getTraceCtx(false);
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
// Fall back
|
|
825
|
-
if (!distributedTraceCtx && _context && _context.telemetryTrace) {
|
|
826
|
-
distributedTraceCtx = createDistributedTraceContextFromTrace(_context.telemetryTrace);
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
return distributedTraceCtx;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
function _openHandler(xhr: XMLHttpRequestInstrumented, method: string, url: string, async: boolean) {
|
|
833
|
-
let distributedTraceCtx: IDistributedTraceContext = _getDistributedTraceCtx();
|
|
834
|
-
|
|
835
|
-
const traceID = (distributedTraceCtx && distributedTraceCtx.getTraceId()) || generateW3CId();
|
|
836
|
-
const spanID = generateW3CId().substr(0, 16);
|
|
837
|
-
|
|
838
|
-
const ajaxData = new ajaxRecord(traceID, spanID, _self[strDiagLog](), _self.core?.getTraceCtx());
|
|
839
|
-
ajaxData.traceFlags = distributedTraceCtx && distributedTraceCtx.getTraceFlags();
|
|
840
|
-
ajaxData.method = method;
|
|
841
|
-
ajaxData.requestUrl = url;
|
|
842
|
-
ajaxData.xhrMonitoringState.openDone = true;
|
|
843
|
-
ajaxData.requestHeaders = {};
|
|
844
|
-
ajaxData.async = async;
|
|
845
|
-
ajaxData.errorStatusText = _enableAjaxErrorStatusText;
|
|
846
|
-
xhr[strAjaxData] = ajaxData;
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
function _attachToOnReadyStateChange(xhr: XMLHttpRequestInstrumented) {
|
|
850
|
-
xhr[strAjaxData].xhrMonitoringState.stateChangeAttached = eventOn(xhr, "readystatechange", () => {
|
|
851
|
-
try {
|
|
852
|
-
if (xhr && xhr.readyState === 4 && _isMonitoredXhrInstance(xhr)) {
|
|
853
|
-
_onAjaxComplete(xhr);
|
|
854
|
-
}
|
|
855
|
-
} catch (e) {
|
|
856
|
-
const exceptionText = dumpObj(e);
|
|
857
|
-
|
|
858
|
-
// ignore messages with c00c023f, as this a known IE9 XHR abort issue
|
|
859
|
-
if (!exceptionText || _indexOf(exceptionText.toLowerCase(), "c00c023f") === -1) {
|
|
860
|
-
_throwInternalCritical(_self,
|
|
861
|
-
_eInternalMessageId.FailedMonitorAjaxRSC,
|
|
862
|
-
ERROR_HEADER + " 'readystatechange' event handler" + ERROR_POSTFIX,
|
|
863
|
-
{
|
|
864
|
-
ajaxDiagnosticsMessage: _getFailedAjaxDiagnosticsMessage(xhr),
|
|
865
|
-
exception: exceptionText
|
|
866
|
-
});
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
}, _evtNamespace);
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
function _getResponseText(xhr: XMLHttpRequestInstrumented) {
|
|
873
|
-
try {
|
|
874
|
-
const responseType = xhr.responseType;
|
|
875
|
-
if (responseType === "" || responseType === "text") {
|
|
876
|
-
// As per the specification responseText is only valid if the type is an empty string or "text"
|
|
877
|
-
return xhr.responseText;
|
|
878
|
-
}
|
|
879
|
-
} catch (e) {
|
|
880
|
-
// This shouldn't happen because of the above check -- but just in case, so just ignore
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
return null;
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
function _onAjaxComplete(xhr: XMLHttpRequestInstrumented) {
|
|
887
|
-
let ajaxData = xhr[strAjaxData];
|
|
888
|
-
ajaxData.responseFinishedTime = dateTimeUtilsNow();
|
|
889
|
-
ajaxData.status = xhr.status;
|
|
890
|
-
|
|
891
|
-
function _reportXhrError(e: any, failedProps?:Object) {
|
|
892
|
-
let errorProps = failedProps||{};
|
|
893
|
-
errorProps["ajaxDiagnosticsMessage"] = _getFailedAjaxDiagnosticsMessage(xhr);
|
|
894
|
-
if (e) {
|
|
895
|
-
errorProps["exception"] = dumpObj(e);
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
_throwInternalWarning(_self,
|
|
899
|
-
_eInternalMessageId.FailedMonitorAjaxDur,
|
|
900
|
-
FAILED_TO_CALCULATE_DURATION_ERROR + "ajax call" + ERROR_NOT_SENT,
|
|
901
|
-
errorProps
|
|
902
|
-
);
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
_findPerfResourceEntry("xmlhttprequest", ajaxData, () => {
|
|
906
|
-
try {
|
|
907
|
-
const dependency = ajaxData.CreateTrackItem("Ajax", _enableRequestHeaderTracking, () => {
|
|
908
|
-
let ajaxResponse:IAjaxRecordResponse = {
|
|
909
|
-
statusText: xhr.statusText,
|
|
910
|
-
headerMap: null,
|
|
911
|
-
correlationContext: _getAjaxCorrelationContext(xhr),
|
|
912
|
-
type: xhr.responseType,
|
|
913
|
-
responseText: _getResponseText(xhr),
|
|
914
|
-
response: xhr.response
|
|
915
|
-
};
|
|
916
|
-
|
|
917
|
-
if (_enableResponseHeaderTracking) {
|
|
918
|
-
const headers = xhr.getAllResponseHeaders();
|
|
919
|
-
if (headers) {
|
|
920
|
-
// xhr.getAllResponseHeaders() method returns all the response headers, separated by CRLF, as a string or null
|
|
921
|
-
// the regex converts the header string into an array of individual headers
|
|
922
|
-
const arr = strTrim(headers).split(/[\r\n]+/);
|
|
923
|
-
const responseHeaderMap = {};
|
|
924
|
-
arrForEach(arr, (line) => {
|
|
925
|
-
const parts = line.split(": ");
|
|
926
|
-
const header = parts.shift();
|
|
927
|
-
const value = parts.join(": ");
|
|
928
|
-
if(_canIncludeHeaders(header)) {
|
|
929
|
-
responseHeaderMap[header] = value;
|
|
930
|
-
}
|
|
931
|
-
});
|
|
932
|
-
|
|
933
|
-
ajaxResponse.headerMap = responseHeaderMap;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
return ajaxResponse;
|
|
938
|
-
});
|
|
939
|
-
|
|
940
|
-
let properties;
|
|
941
|
-
try {
|
|
942
|
-
if (!!_addRequestContext) {
|
|
943
|
-
properties = _addRequestContext({status: xhr.status, xhr});
|
|
944
|
-
}
|
|
945
|
-
} catch (e) {
|
|
946
|
-
_throwInternalWarning(_self,
|
|
947
|
-
_eInternalMessageId.FailedAddingCustomDefinedRequestContext,
|
|
948
|
-
CUSTOM_REQUEST_CONTEXT_ERROR);
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
if (dependency) {
|
|
952
|
-
if (properties !== undefined) {
|
|
953
|
-
dependency.properties = {...dependency.properties, ...properties};
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
let sysProperties = ajaxData.getPartAProps();
|
|
957
|
-
_reportDependencyInternal(_dependencyInitializers, _self.core, ajaxData, dependency, null, sysProperties);
|
|
958
|
-
} else {
|
|
959
|
-
_reportXhrError(null, {
|
|
960
|
-
requestSentTime: ajaxData.requestSentTime,
|
|
961
|
-
responseFinishedTime: ajaxData.responseFinishedTime
|
|
962
|
-
});
|
|
963
|
-
}
|
|
964
|
-
} finally {
|
|
965
|
-
// cleanup telemetry data
|
|
966
|
-
try {
|
|
967
|
-
xhr[strAjaxData] = null;
|
|
968
|
-
} catch (e) {
|
|
969
|
-
// May throw in environments that prevent extension or freeze xhr
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
}, (e) => {
|
|
973
|
-
_reportXhrError(e, null);
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
function _getAjaxCorrelationContext(xhr: XMLHttpRequestInstrumented) {
|
|
978
|
-
try {
|
|
979
|
-
const responseHeadersString = xhr.getAllResponseHeaders();
|
|
980
|
-
if (responseHeadersString !== null) {
|
|
981
|
-
const index = _indexOf(responseHeadersString.toLowerCase(), RequestHeaders[eRequestHeaders.requestContextHeaderLowerCase]);
|
|
982
|
-
if (index !== -1) {
|
|
983
|
-
const responseHeader = xhr.getResponseHeader(RequestHeaders[eRequestHeaders.requestContextHeader]);
|
|
984
|
-
return correlationIdGetCorrelationContext(responseHeader);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
} catch (e) {
|
|
988
|
-
_throwInternalWarning(_self,
|
|
989
|
-
_eInternalMessageId.FailedMonitorAjaxGetCorrelationHeader,
|
|
990
|
-
CORRELATION_HEADER_ERROR,
|
|
991
|
-
{
|
|
992
|
-
ajaxDiagnosticsMessage: _getFailedAjaxDiagnosticsMessage(xhr),
|
|
993
|
-
exception: dumpObj(e)
|
|
994
|
-
});
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
function _createMarkId(type:string, ajaxData:ajaxRecord) {
|
|
999
|
-
if (ajaxData.requestUrl && _markPrefix && _enableAjaxPerfTracking) {
|
|
1000
|
-
let performance = getPerformance();
|
|
1001
|
-
if (performance && isFunction(performance.mark)) {
|
|
1002
|
-
_markCount++;
|
|
1003
|
-
let markId = _markPrefix + type + "#" + _markCount;
|
|
1004
|
-
performance.mark(markId);
|
|
1005
|
-
let entries = performance.getEntriesByName(markId);
|
|
1006
|
-
if (entries && entries.length === 1) {
|
|
1007
|
-
ajaxData.perfMark = entries[0] as any;
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
function _findPerfResourceEntry(initiatorType:string, ajaxData:ajaxRecord, trackCallback:() => void, reportError:(e:any) => void): void {
|
|
1014
|
-
let perfMark = ajaxData.perfMark;
|
|
1015
|
-
let performance = getPerformance();
|
|
1016
|
-
let maxAttempts = _maxAjaxPerfLookupAttempts;
|
|
1017
|
-
let retryDelay = _ajaxPerfLookupDelay;
|
|
1018
|
-
let requestUrl = ajaxData.requestUrl;
|
|
1019
|
-
let attempt = 0;
|
|
1020
|
-
(function locateResourceTiming() {
|
|
1021
|
-
try {
|
|
1022
|
-
if (performance && perfMark) {
|
|
1023
|
-
attempt++;
|
|
1024
|
-
let perfTiming:PerformanceResourceTiming = null;
|
|
1025
|
-
let entries = performance.getEntries();
|
|
1026
|
-
for (let lp = entries.length - 1; lp >= 0; lp--) {
|
|
1027
|
-
let entry:PerformanceEntry = entries[lp];
|
|
1028
|
-
if (entry) {
|
|
1029
|
-
if (entry.entryType === "resource") {
|
|
1030
|
-
if ((entry as PerformanceResourceTiming).initiatorType === initiatorType &&
|
|
1031
|
-
(_indexOf(entry.name, requestUrl) !== -1 || _indexOf(requestUrl, entry.name) !== -1)) {
|
|
1032
|
-
|
|
1033
|
-
perfTiming = entry as PerformanceResourceTiming;
|
|
1034
|
-
}
|
|
1035
|
-
} else if (entry.entryType === "mark" && entry.name === perfMark.name) {
|
|
1036
|
-
// We hit the start event
|
|
1037
|
-
ajaxData.perfTiming = perfTiming;
|
|
1038
|
-
break;
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
if (entry.startTime < perfMark.startTime - 1000) {
|
|
1042
|
-
// Fallback to try and reduce the time spent looking for the perf entry
|
|
1043
|
-
break;
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
if (!perfMark || // - we don't have a perfMark or
|
|
1050
|
-
ajaxData.perfTiming || // - we have not found the perf entry or
|
|
1051
|
-
attempt >= maxAttempts || // - we have tried too many attempts or
|
|
1052
|
-
ajaxData.async === false) { // - this is a sync request
|
|
1053
|
-
|
|
1054
|
-
if (perfMark && isFunction(performance.clearMarks)) {
|
|
1055
|
-
// Remove the mark so we don't fill up the performance resources too much
|
|
1056
|
-
performance.clearMarks(perfMark.name);
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
ajaxData.perfAttempts = attempt;
|
|
1060
|
-
|
|
1061
|
-
// just continue and report the track event
|
|
1062
|
-
trackCallback();
|
|
1063
|
-
} else {
|
|
1064
|
-
// We need to wait for the browser to populate the window.performance entry
|
|
1065
|
-
// This needs to be at least 1ms as waiting <= 1 (on firefox) is not enough time for fetch or xhr,
|
|
1066
|
-
// this is a scheduling issue for the browser implementation
|
|
1067
|
-
scheduleTimeout(locateResourceTiming, retryDelay);
|
|
1068
|
-
}
|
|
1069
|
-
} catch (e) {
|
|
1070
|
-
reportError(e);
|
|
1071
|
-
}
|
|
1072
|
-
})();
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
function _createFetchRecord(input?: Request | string, init?: RequestInit): ajaxRecord {
|
|
1076
|
-
let distributedTraceCtx: IDistributedTraceContext = _getDistributedTraceCtx();
|
|
1077
|
-
|
|
1078
|
-
const traceID = (distributedTraceCtx && distributedTraceCtx.getTraceId()) || generateW3CId();
|
|
1079
|
-
const spanID = generateW3CId().substr(0, 16);
|
|
1080
|
-
|
|
1081
|
-
let ajaxData = new ajaxRecord(traceID, spanID, _self[strDiagLog](), _self.core?.getTraceCtx());
|
|
1082
|
-
ajaxData.traceFlags = distributedTraceCtx && distributedTraceCtx.getTraceFlags();
|
|
1083
|
-
ajaxData.requestSentTime = dateTimeUtilsNow();
|
|
1084
|
-
ajaxData.errorStatusText = _enableAjaxErrorStatusText;
|
|
1085
|
-
|
|
1086
|
-
if (input instanceof Request) {
|
|
1087
|
-
ajaxData.requestUrl = input ? input.url : "";
|
|
1088
|
-
} else {
|
|
1089
|
-
ajaxData.requestUrl = input;
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
let method = "GET";
|
|
1093
|
-
if (init && init.method) {
|
|
1094
|
-
method = init.method;
|
|
1095
|
-
} else if (input && input instanceof Request) {
|
|
1096
|
-
method = input.method;
|
|
1097
|
-
}
|
|
1098
|
-
ajaxData.method = method;
|
|
1099
|
-
|
|
1100
|
-
let requestHeaders = {};
|
|
1101
|
-
if (_enableRequestHeaderTracking) {
|
|
1102
|
-
let headers = new Headers((init ? init.headers : 0) || (input instanceof Request ? (input.headers || {}) : {}));
|
|
1103
|
-
headers.forEach((value, key) => { // @skip-minify
|
|
1104
|
-
if (_canIncludeHeaders(key)) {
|
|
1105
|
-
requestHeaders[key] = value;
|
|
1106
|
-
}
|
|
1107
|
-
});
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
ajaxData.requestHeaders = requestHeaders;
|
|
1111
|
-
|
|
1112
|
-
_createMarkId(STR_FETCH, ajaxData);
|
|
1113
|
-
|
|
1114
|
-
return ajaxData;
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
function _getFailedFetchDiagnosticsMessage(input: Request | Response | string): string {
|
|
1118
|
-
let result: string = "";
|
|
1119
|
-
try {
|
|
1120
|
-
if (!isNullOrUndefined(input)) {
|
|
1121
|
-
if (typeof (input) === "string") {
|
|
1122
|
-
result += `(url: '${input}')`;
|
|
1123
|
-
} else {
|
|
1124
|
-
result += `(url: '${input.url}')`;
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
} catch (e) {
|
|
1128
|
-
_throwInternalCritical(_self,
|
|
1129
|
-
_eInternalMessageId.FailedMonitorAjaxOpen,
|
|
1130
|
-
"Failed to grab failed fetch diagnostics message",
|
|
1131
|
-
{ exception: dumpObj(e) }
|
|
1132
|
-
);
|
|
1133
|
-
}
|
|
1134
|
-
return result;
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
function _reportFetchMetrics(callDetails: IInstrumentCallDetails, status: number, input: Request, response: Response | string, ajaxData: ajaxRecord, getResponse:() => IAjaxRecordResponse, properties?: { [key: string]: any }): void {
|
|
1138
|
-
if (!ajaxData) {
|
|
1139
|
-
return;
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
function _reportFetchError(msgId: _eInternalMessageId, e: any, failedProps?:Object) {
|
|
1143
|
-
let errorProps = failedProps||{};
|
|
1144
|
-
errorProps["fetchDiagnosticsMessage"] = _getFailedFetchDiagnosticsMessage(input);
|
|
1145
|
-
if (e) {
|
|
1146
|
-
errorProps["exception"] = dumpObj(e);
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
_throwInternalWarning(_self,
|
|
1150
|
-
msgId,
|
|
1151
|
-
FAILED_TO_CALCULATE_DURATION_ERROR + "fetch call" + ERROR_NOT_SENT,
|
|
1152
|
-
errorProps
|
|
1153
|
-
);
|
|
1154
|
-
}
|
|
1155
|
-
ajaxData.responseFinishedTime = dateTimeUtilsNow();
|
|
1156
|
-
ajaxData.status = status;
|
|
1157
|
-
|
|
1158
|
-
_findPerfResourceEntry(STR_FETCH, ajaxData, () => {
|
|
1159
|
-
const dependency = ajaxData.CreateTrackItem("Fetch", _enableRequestHeaderTracking, getResponse);
|
|
1160
|
-
|
|
1161
|
-
let properties;
|
|
1162
|
-
try {
|
|
1163
|
-
if (!!_addRequestContext) {
|
|
1164
|
-
properties = _addRequestContext({status, request: input, response});
|
|
1165
|
-
}
|
|
1166
|
-
} catch (e) {
|
|
1167
|
-
_throwInternalWarning(_self,
|
|
1168
|
-
_eInternalMessageId.FailedAddingCustomDefinedRequestContext,
|
|
1169
|
-
CUSTOM_REQUEST_CONTEXT_ERROR);
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
if (dependency) {
|
|
1173
|
-
if (properties !== undefined) {
|
|
1174
|
-
dependency.properties = {...dependency.properties, ...properties};
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
let sysProperties = ajaxData.getPartAProps();
|
|
1178
|
-
_reportDependencyInternal(_dependencyInitializers, _self.core, ajaxData, dependency, null, sysProperties);
|
|
1179
|
-
} else {
|
|
1180
|
-
_reportFetchError(_eInternalMessageId.FailedMonitorAjaxDur, null,
|
|
1181
|
-
{
|
|
1182
|
-
requestSentTime: ajaxData.requestSentTime,
|
|
1183
|
-
responseFinishedTime: ajaxData.responseFinishedTime
|
|
1184
|
-
});
|
|
1185
|
-
}
|
|
1186
|
-
}, (e) => {
|
|
1187
|
-
_reportFetchError(_eInternalMessageId.FailedMonitorAjaxGetCorrelationHeader, e, null);
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
function _getFetchCorrelationContext(response: Response): string {
|
|
1192
|
-
if (response && response.headers) {
|
|
1193
|
-
try {
|
|
1194
|
-
const responseHeader: string = response.headers.get(RequestHeaders[eRequestHeaders.requestContextHeader]);
|
|
1195
|
-
return correlationIdGetCorrelationContext(responseHeader);
|
|
1196
|
-
} catch (e) {
|
|
1197
|
-
_throwInternalWarning(_self,
|
|
1198
|
-
_eInternalMessageId.FailedMonitorAjaxGetCorrelationHeader,
|
|
1199
|
-
CORRELATION_HEADER_ERROR,
|
|
1200
|
-
{
|
|
1201
|
-
fetchDiagnosticsMessage: _getFailedFetchDiagnosticsMessage(response),
|
|
1202
|
-
exception: dumpObj(e)
|
|
1203
|
-
});
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
function _reportDependencyInternal(
|
|
1209
|
-
initializers: _IInternalDependencyHandler<DependencyInitializerFunction>[],
|
|
1210
|
-
core: IAppInsightsCore,
|
|
1211
|
-
ajaxData: ajaxRecord,
|
|
1212
|
-
dependency: IDependencyTelemetry,
|
|
1213
|
-
properties?: { [key: string]: any },
|
|
1214
|
-
systemProperties?: { [key: string]: any }
|
|
1215
|
-
) {
|
|
1216
|
-
|
|
1217
|
-
let result = true;
|
|
1218
|
-
var initializersCount = initializers.length;
|
|
1219
|
-
if (initializersCount > 0) {
|
|
1220
|
-
let details: IDependencyInitializerDetails = {
|
|
1221
|
-
item: dependency,
|
|
1222
|
-
properties: properties,
|
|
1223
|
-
sysProperties: systemProperties,
|
|
1224
|
-
context: ajaxData ? ajaxData.context : null,
|
|
1225
|
-
aborted: ajaxData ? !!ajaxData.aborted : false
|
|
1226
|
-
};
|
|
1227
|
-
|
|
1228
|
-
result = _processDependencyContainer(core, initializers, details, "initializer");
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
if (result) {
|
|
1232
|
-
_self.trackDependencyDataInternal(dependency, properties, systemProperties);
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
});
|
|
1236
|
-
}
|
|
1237
|
-
|
|
1238
|
-
public initialize(config: IConfiguration & IConfig, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?:ITelemetryPluginChain) {
|
|
1239
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
public processTelemetry(item: ITelemetryItem, itemCtx?: IProcessTelemetryContext) {
|
|
1243
|
-
this.processNext(item, itemCtx);
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
/**
|
|
1247
|
-
* Logs dependency call
|
|
1248
|
-
* @param dependencyData - dependency data object
|
|
1249
|
-
*/
|
|
1250
|
-
public trackDependencyData(dependency: IDependencyTelemetry, properties?: { [key: string]: any }) {
|
|
1251
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
public includeCorrelationHeaders(ajaxData: ajaxRecord, input?: Request | string, init?: RequestInit, xhr?: XMLHttpRequestInstrumented): any {
|
|
1255
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
/**
|
|
1259
|
-
* Add an ajax listener which is called just prior to the request being sent and before the correlation headers are added, to allow you
|
|
1260
|
-
* to access the headers and modify the values used to generate the distributed tracing correlation headers.
|
|
1261
|
-
* @param dependencyListener - The Telemetry Initializer function
|
|
1262
|
-
* @returns - A IDependencyListenerHandler to enable the initializer to be removed
|
|
1263
|
-
*/
|
|
1264
|
-
public addDependencyListener(dependencyListener: DependencyListenerFunction): IDependencyListenerHandler {
|
|
1265
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1266
|
-
return null;
|
|
1267
|
-
}
|
|
1268
|
-
|
|
1269
|
-
/**
|
|
1270
|
-
* Add an dependency telemetry initializer callback function to allow populating additional properties or drop the request.
|
|
1271
|
-
* It is called after the dependency call has completed and any available performance details are available. A dependency
|
|
1272
|
-
* initializer is similar to the TelemetryInitializer function but it allows you to block the reporting of the dependency
|
|
1273
|
-
* request so that it doesn't count against the `maxAjaxCallsPerView`.
|
|
1274
|
-
* @param dependencyInitializer - The Dependency Telemetry Initializer function
|
|
1275
|
-
* @returns - A IDependencyInitializerHandler to enable the initializer to be removed
|
|
1276
|
-
*/
|
|
1277
|
-
public addDependencyInitializer(dependencyInitializer: DependencyInitializerFunction): IDependencyInitializerHandler {
|
|
1278
|
-
return null;
|
|
1279
|
-
}
|
|
1280
|
-
|
|
1281
|
-
/**
|
|
1282
|
-
* Protected function to allow sub classes the chance to add additional properties to the dependency event
|
|
1283
|
-
* before it's sent. This function calls track, so sub-classes must call this function after they have
|
|
1284
|
-
* populated their properties.
|
|
1285
|
-
* @param dependencyData - dependency data object
|
|
1286
|
-
*/
|
|
1287
|
-
protected trackDependencyDataInternal(dependency: IDependencyTelemetry, properties?: { [key: string]: any }, systemProperties?: { [key: string]: any }) {
|
|
1288
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1289
|
-
}
|
|
1290
|
-
}
|