@microsoft/applicationinsights-dependencies-js 3.0.0-beta.2303-11 → 3.0.0-nightly3.2304-28

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.
Files changed (64) hide show
  1. package/browser/es5/applicationinsights-dependencies-js.cjs.js +4892 -0
  2. package/browser/es5/applicationinsights-dependencies-js.cjs.js.map +1 -0
  3. package/browser/es5/applicationinsights-dependencies-js.cjs.min.js +6 -0
  4. package/browser/es5/applicationinsights-dependencies-js.cjs.min.js.map +1 -0
  5. package/browser/es5/applicationinsights-dependencies-js.gbl.js +4896 -0
  6. package/browser/es5/applicationinsights-dependencies-js.gbl.js.map +1 -0
  7. package/browser/es5/applicationinsights-dependencies-js.gbl.min.js +6 -0
  8. package/browser/es5/applicationinsights-dependencies-js.gbl.min.js.map +1 -0
  9. package/browser/es5/applicationinsights-dependencies-js.integrity.json +66 -0
  10. package/browser/{applicationinsights-dependencies-js.js → es5/applicationinsights-dependencies-js.js} +864 -839
  11. package/browser/es5/applicationinsights-dependencies-js.js.map +1 -0
  12. package/browser/es5/applicationinsights-dependencies-js.min.js +6 -0
  13. package/browser/es5/applicationinsights-dependencies-js.min.js.map +1 -0
  14. package/dist/{applicationinsights-dependencies-js.js → es5/applicationinsights-dependencies-js.js} +864 -839
  15. package/dist/es5/applicationinsights-dependencies-js.js.map +1 -0
  16. package/dist/es5/applicationinsights-dependencies-js.min.js +6 -0
  17. package/dist/es5/applicationinsights-dependencies-js.min.js.map +1 -0
  18. package/{dist-esm → dist-es5}/DependencyInitializer.js +1 -1
  19. package/{dist-esm → dist-es5}/DependencyListener.js +1 -1
  20. package/{dist-esm → dist-es5}/InternalConstants.js +1 -1
  21. package/{dist-esm → dist-es5}/__DynamicConstants.js +1 -1
  22. package/{dist-esm → dist-es5}/ajax.js +5 -5
  23. package/dist-es5/ajax.js.map +1 -0
  24. package/{dist-esm → dist-es5}/ajaxRecord.js +1 -1
  25. package/{dist-esm → dist-es5}/ajaxUtils.js +1 -1
  26. package/{dist-esm → dist-es5}/applicationinsights-dependencies-js.js +1 -1
  27. package/package.json +19 -18
  28. package/tsconfig.json +5 -4
  29. package/types/applicationinsights-dependencies-js.d.ts +284 -4
  30. package/{dist/applicationinsights-dependencies-js.d.ts → types/applicationinsights-dependencies-js.namespaced.d.ts} +1 -1
  31. package/browser/applicationinsights-dependencies-js.integrity.json +0 -26
  32. package/browser/applicationinsights-dependencies-js.js.map +0 -1
  33. package/browser/applicationinsights-dependencies-js.min.js +0 -6
  34. package/browser/applicationinsights-dependencies-js.min.js.map +0 -1
  35. package/dist/applicationinsights-dependencies-js.api.json +0 -2904
  36. package/dist/applicationinsights-dependencies-js.api.md +0 -197
  37. package/dist/applicationinsights-dependencies-js.js.map +0 -1
  38. package/dist/applicationinsights-dependencies-js.min.js +0 -6
  39. package/dist/applicationinsights-dependencies-js.min.js.map +0 -1
  40. package/dist/applicationinsights-dependencies-js.rollup.d.ts +0 -285
  41. package/dist-esm/ajax.js.map +0 -1
  42. package/src/DependencyInitializer.ts +0 -49
  43. package/src/DependencyListener.ts +0 -82
  44. package/src/InternalConstants.ts +0 -13
  45. package/src/__DynamicConstants.ts +0 -68
  46. package/src/ajax.ts +0 -1290
  47. package/src/ajaxRecord.ts +0 -436
  48. package/src/ajaxUtils.ts +0 -23
  49. package/src/applicationinsights-dependencies-js.ts +0 -9
  50. package/types/DependencyInitializer.d.ts +0 -45
  51. package/types/DependencyListener.d.ts +0 -69
  52. package/types/InternalConstants.d.ts +0 -2
  53. package/types/__DynamicConstants.d.ts +0 -56
  54. package/types/ajax.d.ts +0 -63
  55. package/types/ajaxRecord.d.ts +0 -80
  56. package/types/ajaxUtils.d.ts +0 -3
  57. package/types/tsdoc-metadata.json +0 -11
  58. /package/{dist-esm → dist-es5}/DependencyInitializer.js.map +0 -0
  59. /package/{dist-esm → dist-es5}/DependencyListener.js.map +0 -0
  60. /package/{dist-esm → dist-es5}/InternalConstants.js.map +0 -0
  61. /package/{dist-esm → dist-es5}/__DynamicConstants.js.map +0 -0
  62. /package/{dist-esm → dist-es5}/ajaxRecord.js.map +0 -0
  63. /package/{dist-esm → dist-es5}/ajaxUtils.js.map +0 -0
  64. /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
- }