@microsoft/applicationinsights-channel-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.
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.cjs.js +5768 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.cjs.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.cjs.min.js +6 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.cjs.min.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.gbl.js +5772 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.gbl.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.gbl.min.js +6 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.gbl.min.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.integrity.json +66 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.js +5774 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.min.js +6 -0
- package/browser/es5/applicationinsights-channel-js.3.0.0-nightly3.2304-28.min.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.cjs.js +5768 -0
- package/browser/es5/applicationinsights-channel-js.3.cjs.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.cjs.min.js +6 -0
- package/browser/es5/applicationinsights-channel-js.3.cjs.min.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.gbl.js +5772 -0
- package/browser/es5/applicationinsights-channel-js.3.gbl.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.gbl.min.js +6 -0
- package/browser/es5/applicationinsights-channel-js.3.gbl.min.js.map +1 -0
- package/{dist/applicationinsights-channel-js.js → browser/es5/applicationinsights-channel-js.3.js} +875 -829
- package/browser/es5/applicationinsights-channel-js.3.js.map +1 -0
- package/browser/es5/applicationinsights-channel-js.3.min.js +6 -0
- package/browser/es5/applicationinsights-channel-js.3.min.js.map +1 -0
- package/{browser → dist/es5}/applicationinsights-channel-js.js +874 -828
- package/dist/es5/applicationinsights-channel-js.js.map +1 -0
- package/dist/es5/applicationinsights-channel-js.min.js +6 -0
- package/dist/es5/applicationinsights-channel-js.min.js.map +1 -0
- package/{dist-esm → dist-es5}/EnvelopeCreator.js +2 -2
- package/dist-es5/EnvelopeCreator.js.map +1 -0
- package/dist-es5/Interfaces.js +6 -0
- package/{dist-esm → dist-es5}/InternalConstants.js +1 -1
- package/{dist-esm → dist-es5}/Offline.js +8 -7
- package/dist-es5/Offline.js.map +1 -0
- package/{dist-esm → dist-es5}/SendBuffer.js +1 -1
- package/{dist-esm → dist-es5}/Sender.js +6 -4
- package/dist-es5/Sender.js.map +1 -0
- package/{dist-esm → dist-es5}/Serializer.js +1 -1
- package/{dist-esm → dist-es5}/TelemetryProcessors/Sample.js +1 -1
- package/{dist-esm → dist-es5}/TelemetryProcessors/SamplingScoreGenerators/HashCodeScoreGenerator.js +1 -1
- package/{dist-esm → dist-es5}/TelemetryProcessors/SamplingScoreGenerators/SamplingScoreGenerator.js +1 -1
- package/{dist-esm → dist-es5}/__DynamicConstants.js +2 -1
- package/dist-es5/__DynamicConstants.js.map +1 -0
- package/dist-es5/applicationinsights-channel-js.js +6 -0
- package/package.json +18 -17
- package/tsconfig.json +5 -4
- package/types/applicationinsights-channel-js.d.ts +284 -1
- package/{dist/applicationinsights-channel-js.d.ts → types/applicationinsights-channel-js.namespaced.d.ts} +1 -1
- package/browser/applicationinsights-channel-js.integrity.json +0 -26
- package/browser/applicationinsights-channel-js.js.map +0 -1
- package/browser/applicationinsights-channel-js.min.js +0 -6
- package/browser/applicationinsights-channel-js.min.js.map +0 -1
- package/dist/applicationinsights-channel-js.api.json +0 -1357
- package/dist/applicationinsights-channel-js.api.md +0 -60
- package/dist/applicationinsights-channel-js.js.map +0 -1
- package/dist/applicationinsights-channel-js.min.js +0 -6
- package/dist/applicationinsights-channel-js.min.js.map +0 -1
- package/dist/applicationinsights-channel-js.rollup.d.ts +0 -285
- package/dist-esm/EnvelopeCreator.js.map +0 -1
- package/dist-esm/Interfaces.js +0 -6
- package/dist-esm/Offline.js.map +0 -1
- package/dist-esm/Sender.js.map +0 -1
- package/dist-esm/__DynamicConstants.js.map +0 -1
- package/dist-esm/applicationinsights-channel-js.js +0 -6
- package/src/EnvelopeCreator.ts +0 -351
- package/src/Interfaces.ts +0 -114
- package/src/InternalConstants.ts +0 -11
- package/src/Offline.ts +0 -106
- package/src/SendBuffer.ts +0 -396
- package/src/Sender.ts +0 -1256
- package/src/Serializer.ts +0 -177
- package/src/TelemetryProcessors/Sample.ts +0 -49
- package/src/TelemetryProcessors/SamplingScoreGenerators/HashCodeScoreGenerator.ts +0 -37
- package/src/TelemetryProcessors/SamplingScoreGenerators/SamplingScoreGenerator.ts +0 -35
- package/src/__DynamicConstants.ts +0 -64
- package/src/applicationinsights-channel-js.ts +0 -1
- package/types/EnvelopeCreator.d.ts +0 -12
- package/types/Interfaces.d.ts +0 -95
- package/types/InternalConstants.d.ts +0 -1
- package/types/Offline.d.ts +0 -10
- package/types/SendBuffer.d.ts +0 -73
- package/types/Sender.d.ts +0 -84
- package/types/Serializer.d.ts +0 -9
- package/types/TelemetryProcessors/Sample.d.ts +0 -12
- package/types/TelemetryProcessors/SamplingScoreGenerators/HashCodeScoreGenerator.d.ts +0 -5
- package/types/TelemetryProcessors/SamplingScoreGenerators/SamplingScoreGenerator.d.ts +0 -5
- package/types/__DynamicConstants.d.ts +0 -52
- package/types/tsdoc-metadata.json +0 -11
- /package/{dist-esm → dist-es5}/Interfaces.js.map +0 -0
- /package/{dist-esm → dist-es5}/InternalConstants.js.map +0 -0
- /package/{dist-esm → dist-es5}/SendBuffer.js.map +0 -0
- /package/{dist-esm → dist-es5}/Serializer.js.map +0 -0
- /package/{dist-esm → dist-es5}/TelemetryProcessors/Sample.js.map +0 -0
- /package/{dist-esm → dist-es5}/TelemetryProcessors/SamplingScoreGenerators/HashCodeScoreGenerator.js.map +0 -0
- /package/{dist-esm → dist-es5}/TelemetryProcessors/SamplingScoreGenerators/SamplingScoreGenerator.js.map +0 -0
- /package/{dist-esm → dist-es5}/applicationinsights-channel-js.js.map +0 -0
package/src/Sender.ts
DELETED
|
@@ -1,1256 +0,0 @@
|
|
|
1
|
-
import dynamicProto from "@microsoft/dynamicproto-js";
|
|
2
|
-
import {
|
|
3
|
-
BreezeChannelIdentifier, DEFAULT_BREEZE_ENDPOINT, DEFAULT_BREEZE_PATH, DisabledPropertyName, Event, Exception, IConfig, IEnvelope,
|
|
4
|
-
ISample, Metric, PageView, PageViewPerformance, ProcessLegacy, RemoteDependencyData, RequestHeaders, SampleRate, Trace, eRequestHeaders,
|
|
5
|
-
isInternalApplicationInsightsEndpoint, utlCanUseSessionStorage
|
|
6
|
-
} from "@microsoft/applicationinsights-common";
|
|
7
|
-
import {
|
|
8
|
-
BaseTelemetryPlugin, IAppInsightsCore, IChannelControls, IConfigDefaults, IConfiguration, IDiagnosticLogger, INotificationManager,
|
|
9
|
-
IPlugin, IProcessTelemetryContext, IProcessTelemetryUnloadContext, ITelemetryItem, ITelemetryPluginChain, ITelemetryUnloadState,
|
|
10
|
-
SendRequestReason, _eInternalMessageId, _throwInternal, _warnToConsole, arrForEach, cfgDfBoolean, cfgDfValidate,
|
|
11
|
-
createProcessTelemetryContext, createUniqueNamespace, dateNow, dumpObj, eLoggingSeverity, getExceptionName, getIEVersion, getJSON,
|
|
12
|
-
getNavigator, getWindow, isArray, isBeaconsSupported, isFetchSupported, isNullOrUndefined, isXhrSupported, mergeEvtNamespace, objExtend,
|
|
13
|
-
objKeys, onConfigChange, useXDomainRequest
|
|
14
|
-
} from "@microsoft/applicationinsights-core-js";
|
|
15
|
-
import { ITimerHandler, isTruthy, objDeepFreeze, objDefine, scheduleTimeout } from "@nevware21/ts-utils";
|
|
16
|
-
import {
|
|
17
|
-
DependencyEnvelopeCreator, EventEnvelopeCreator, ExceptionEnvelopeCreator, MetricEnvelopeCreator, PageViewEnvelopeCreator,
|
|
18
|
-
PageViewPerformanceEnvelopeCreator, TraceEnvelopeCreator
|
|
19
|
-
} from "./EnvelopeCreator";
|
|
20
|
-
import { IBackendResponse, ISenderConfig, XDomainRequest as IXDomainRequest } from "./Interfaces";
|
|
21
|
-
import { IOfflineListener, createOfflineListener } from "./Offline";
|
|
22
|
-
import { ArraySendBuffer, ISendBuffer, SessionStorageSendBuffer } from "./SendBuffer";
|
|
23
|
-
import { Serializer } from "./Serializer";
|
|
24
|
-
import { Sample } from "./TelemetryProcessors/Sample";
|
|
25
|
-
|
|
26
|
-
const UNDEFINED_VALUE: undefined = undefined;
|
|
27
|
-
|
|
28
|
-
const FetchSyncRequestSizeLimitBytes = 65000; // approx 64kb (the current Edge, Firefox and Chrome max limit)
|
|
29
|
-
|
|
30
|
-
declare var XDomainRequest: {
|
|
31
|
-
prototype: IXDomainRequest;
|
|
32
|
-
new(): IXDomainRequest;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export type SenderFunction = (payload: string[], isAsync: boolean) => void;
|
|
36
|
-
|
|
37
|
-
function _getResponseText(xhr: XMLHttpRequest | IXDomainRequest) {
|
|
38
|
-
try {
|
|
39
|
-
return xhr.responseText;
|
|
40
|
-
} catch (e) {
|
|
41
|
-
// Best effort, as XHR may throw while XDR wont so just ignore
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const defaultAppInsightsChannelConfig: IConfigDefaults<ISenderConfig> = objDeepFreeze({
|
|
48
|
-
// Use the default value (handles empty string in the configuration)
|
|
49
|
-
endpointUrl: cfgDfValidate(isTruthy, DEFAULT_BREEZE_ENDPOINT + DEFAULT_BREEZE_PATH),
|
|
50
|
-
emitLineDelimitedJson: cfgDfBoolean(),
|
|
51
|
-
maxBatchInterval: 15000,
|
|
52
|
-
maxBatchSizeInBytes: 102400, // 100kb
|
|
53
|
-
disableTelemetry: cfgDfBoolean(),
|
|
54
|
-
enableSessionStorageBuffer: cfgDfBoolean(true),
|
|
55
|
-
isRetryDisabled: cfgDfBoolean(),
|
|
56
|
-
isBeaconApiDisabled: cfgDfBoolean(true),
|
|
57
|
-
disableXhr: cfgDfBoolean(),
|
|
58
|
-
onunloadDisableFetch: cfgDfBoolean(),
|
|
59
|
-
onunloadDisableBeacon: cfgDfBoolean(),
|
|
60
|
-
instrumentationKey: UNDEFINED_VALUE, // Channel doesn't need iKey, it should be set already
|
|
61
|
-
namePrefix: UNDEFINED_VALUE,
|
|
62
|
-
samplingPercentage: cfgDfValidate(_chkSampling, 100),
|
|
63
|
-
customHeaders: UNDEFINED_VALUE,
|
|
64
|
-
convertUndefined: UNDEFINED_VALUE,
|
|
65
|
-
eventsLimitInMem: 10000
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
function _chkSampling(value: number) {
|
|
69
|
-
return !isNaN(value) && value > 0 && value <= 100;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
type EnvelopeCreator = (logger: IDiagnosticLogger, telemetryItem: ITelemetryItem, customUndefinedValue?: any) => IEnvelope;
|
|
73
|
-
|
|
74
|
-
const EnvelopeTypeCreator: { [key:string] : EnvelopeCreator } = {
|
|
75
|
-
[Event.dataType]: EventEnvelopeCreator,
|
|
76
|
-
[Trace.dataType]: TraceEnvelopeCreator,
|
|
77
|
-
[PageView.dataType]: PageViewEnvelopeCreator,
|
|
78
|
-
[PageViewPerformance.dataType]: PageViewPerformanceEnvelopeCreator,
|
|
79
|
-
[Exception.dataType]: ExceptionEnvelopeCreator,
|
|
80
|
-
[Metric.dataType]: MetricEnvelopeCreator,
|
|
81
|
-
[RemoteDependencyData.dataType]: DependencyEnvelopeCreator
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
export class Sender extends BaseTelemetryPlugin implements IChannelControls {
|
|
85
|
-
|
|
86
|
-
public static constructEnvelope(orig: ITelemetryItem, iKey: string, logger: IDiagnosticLogger, convertUndefined?: any): IEnvelope {
|
|
87
|
-
let envelope: ITelemetryItem;
|
|
88
|
-
if (iKey !== orig.iKey && !isNullOrUndefined(iKey)) {
|
|
89
|
-
envelope = {
|
|
90
|
-
...orig,
|
|
91
|
-
iKey
|
|
92
|
-
};
|
|
93
|
-
} else {
|
|
94
|
-
envelope = orig;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
let creator: EnvelopeCreator = EnvelopeTypeCreator[envelope.baseType] || EventEnvelopeCreator;
|
|
98
|
-
|
|
99
|
-
return creator(logger, envelope, convertUndefined);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public readonly priority: number = 1001;
|
|
103
|
-
|
|
104
|
-
public readonly identifier: string = BreezeChannelIdentifier;
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* The configuration for this sender instance
|
|
108
|
-
*/
|
|
109
|
-
public readonly _senderConfig: ISenderConfig;
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* A method which will cause data to be send to the url
|
|
113
|
-
*/
|
|
114
|
-
public _sender: SenderFunction;
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* A send buffer object
|
|
118
|
-
*/
|
|
119
|
-
public _buffer: ISendBuffer;
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* AppId of this component parsed from some backend response.
|
|
123
|
-
*/
|
|
124
|
-
public _appId: string;
|
|
125
|
-
|
|
126
|
-
protected _sample: ISample;
|
|
127
|
-
|
|
128
|
-
constructor() {
|
|
129
|
-
super();
|
|
130
|
-
|
|
131
|
-
// Don't set the defaults here, set them in the _initDefaults() as this is also called during unload
|
|
132
|
-
let _consecutiveErrors: number; // How many times in a row a retryable error condition has occurred.
|
|
133
|
-
let _retryAt: number; // The time to retry at in milliseconds from 1970/01/01 (this makes the timer calculation easy).
|
|
134
|
-
let _lastSend: number; // The time of the last send operation.
|
|
135
|
-
let _paused: boolean; // Flag indicating that the sending should be paused
|
|
136
|
-
let _timeoutHandle: ITimerHandler; // Handle to the timer for delayed sending of batches of data.
|
|
137
|
-
let _serializer: Serializer;
|
|
138
|
-
let _stamp_specific_redirects: number;
|
|
139
|
-
let _headers: { [name: string]: string };
|
|
140
|
-
let _syncFetchPayload = 0; // Keep track of the outstanding sync fetch payload total (as sync fetch has limits)
|
|
141
|
-
let _fallbackSender: SenderFunction; // The sender to use if the payload size is too large
|
|
142
|
-
let _syncUnloadSender: SenderFunction; // The identified sender to use for the synchronous unload stage
|
|
143
|
-
let _offlineListener: IOfflineListener;
|
|
144
|
-
let _evtNamespace: string | string[];
|
|
145
|
-
let _endpointUrl: string;
|
|
146
|
-
let _orgEndpointUrl: string;
|
|
147
|
-
let _maxBatchSizeInBytes: number;
|
|
148
|
-
let _beaconSupported: boolean;
|
|
149
|
-
let _customHeaders: Array<{header: string, value: string}>;
|
|
150
|
-
let _disableTelemetry: boolean;
|
|
151
|
-
let _instrumentationKey: string;
|
|
152
|
-
let _convertUndefined: any;
|
|
153
|
-
let _isRetryDisabled: boolean;
|
|
154
|
-
let _maxBatchInterval: number;
|
|
155
|
-
let _sessionStorageUsed: boolean;
|
|
156
|
-
let _namePrefix: string;
|
|
157
|
-
|
|
158
|
-
dynamicProto(Sender, this, (_self, _base) => {
|
|
159
|
-
|
|
160
|
-
_initDefaults();
|
|
161
|
-
|
|
162
|
-
_self.pause = () => {
|
|
163
|
-
_clearScheduledTimer();
|
|
164
|
-
_paused = true;
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
_self.resume = () => {
|
|
168
|
-
if (_paused) {
|
|
169
|
-
_paused = false;
|
|
170
|
-
_retryAt = null;
|
|
171
|
-
|
|
172
|
-
// flush if we have exceeded the max-size already
|
|
173
|
-
_checkMaxSize();
|
|
174
|
-
_setupTimer();
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
_self.flush = (isAsync: boolean = true, callBack?: () => void, sendReason?: SendRequestReason) => {
|
|
179
|
-
if (!_paused) {
|
|
180
|
-
// Clear the normal schedule timer as we are going to try and flush ASAP
|
|
181
|
-
_clearScheduledTimer();
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
_self.triggerSend(isAsync, null, sendReason || SendRequestReason.ManualFlush);
|
|
185
|
-
} catch (e) {
|
|
186
|
-
_throwInternal(_self.diagLog(), eLoggingSeverity.CRITICAL,
|
|
187
|
-
_eInternalMessageId.FlushFailed,
|
|
188
|
-
"flush failed, telemetry will not be collected: " + getExceptionName(e),
|
|
189
|
-
{ exception: dumpObj(e) });
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
_self.onunloadFlush = () => {
|
|
195
|
-
if (!_paused) {
|
|
196
|
-
if (_beaconSupported) {
|
|
197
|
-
try {
|
|
198
|
-
_self.triggerSend(true, _doUnloadSend, SendRequestReason.Unload);
|
|
199
|
-
} catch (e) {
|
|
200
|
-
_throwInternal(_self.diagLog(), eLoggingSeverity.CRITICAL,
|
|
201
|
-
_eInternalMessageId.FailedToSendQueuedTelemetry,
|
|
202
|
-
"failed to flush with beacon sender on page unload, telemetry will not be collected: " + getExceptionName(e),
|
|
203
|
-
{ exception: dumpObj(e) });
|
|
204
|
-
}
|
|
205
|
-
} else {
|
|
206
|
-
_self.flush();
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
_self.addHeader = (name: string, value: string) => {
|
|
212
|
-
_headers[name] = value;
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
_self.initialize = (config: IConfiguration & IConfig, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?:ITelemetryPluginChain): void => {
|
|
216
|
-
if (_self.isInitialized()) {
|
|
217
|
-
_throwInternal(_self.diagLog(), eLoggingSeverity.CRITICAL, _eInternalMessageId.SenderNotInitialized, "Sender is already initialized");
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
_base.initialize(config, core, extensions, pluginChain);
|
|
221
|
-
let identifier = _self.identifier;
|
|
222
|
-
_serializer = new Serializer(core.logger);
|
|
223
|
-
_consecutiveErrors = 0;
|
|
224
|
-
_retryAt = null;
|
|
225
|
-
_lastSend = 0;
|
|
226
|
-
_self._sender = null;
|
|
227
|
-
_stamp_specific_redirects = 0;
|
|
228
|
-
let diagLog = _self.diagLog();
|
|
229
|
-
_evtNamespace = mergeEvtNamespace(createUniqueNamespace("Sender"), core.evtNamespace && core.evtNamespace());
|
|
230
|
-
_offlineListener = createOfflineListener(_evtNamespace);
|
|
231
|
-
|
|
232
|
-
// This function will be re-called whenever any referenced configuration is changed
|
|
233
|
-
_self._addHook(onConfigChange(config, (details) => {
|
|
234
|
-
let config = details.cfg;
|
|
235
|
-
let ctx = createProcessTelemetryContext(null, config, core);
|
|
236
|
-
let senderConfig = ctx.getExtCfg(identifier, defaultAppInsightsChannelConfig);
|
|
237
|
-
|
|
238
|
-
objDefine(_self, "_senderConfig", {
|
|
239
|
-
g: function() {
|
|
240
|
-
return senderConfig;
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
// Only update the endpoint if the original config !== the current config
|
|
245
|
-
// This is so any redirect endpointUrl is not overwritten
|
|
246
|
-
if (_orgEndpointUrl !== senderConfig.endpointUrl) {
|
|
247
|
-
if (_orgEndpointUrl) {
|
|
248
|
-
// TODO: add doc to remind users to flush before changing endpoint, otherwise all unsent payload will be sent to new endpoint
|
|
249
|
-
}
|
|
250
|
-
_endpointUrl = _orgEndpointUrl = senderConfig.endpointUrl;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
if (_customHeaders && _customHeaders !== senderConfig.customHeaders) {
|
|
254
|
-
// Removing any previously defined custom headers as they have changed
|
|
255
|
-
arrForEach(_customHeaders, customHeader => {
|
|
256
|
-
delete _headers[customHeader.header];
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
_maxBatchSizeInBytes = senderConfig.maxBatchSizeInBytes;
|
|
261
|
-
_beaconSupported = (senderConfig.onunloadDisableBeacon === false || senderConfig.isBeaconApiDisabled === false) && isBeaconsSupported();
|
|
262
|
-
|
|
263
|
-
let canUseSessionStorage = !!senderConfig.enableSessionStorageBuffer && utlCanUseSessionStorage();
|
|
264
|
-
let namePrefix = senderConfig.namePrefix;
|
|
265
|
-
|
|
266
|
-
//Note: emitLineDelimitedJson and eventsLimitInMem is directly accessed via config in senderBuffer
|
|
267
|
-
//Therefore, if canUseSessionStorage is not changed, we do not need to re initialize a new one
|
|
268
|
-
let shouldUpdate = (canUseSessionStorage !== _sessionStorageUsed)
|
|
269
|
-
|| (canUseSessionStorage && (_namePrefix !== namePrefix)); // prefixName is only used in session storage
|
|
270
|
-
|
|
271
|
-
if (_self._buffer) {
|
|
272
|
-
// case1 (Pre and Now enableSessionStorageBuffer settings are same)
|
|
273
|
-
// if namePrefix changes, transfer current buffer to new buffer
|
|
274
|
-
// else no action needed
|
|
275
|
-
|
|
276
|
-
//case2 (Pre and Now enableSessionStorageBuffer settings are changed)
|
|
277
|
-
// transfer current buffer to new buffer
|
|
278
|
-
|
|
279
|
-
if (shouldUpdate) {
|
|
280
|
-
try {
|
|
281
|
-
|
|
282
|
-
_self._buffer = _self._buffer.createNew(diagLog, senderConfig, canUseSessionStorage);
|
|
283
|
-
|
|
284
|
-
} catch (e) {
|
|
285
|
-
_throwInternal(_self.diagLog(), eLoggingSeverity.CRITICAL,
|
|
286
|
-
_eInternalMessageId.FailedAddingTelemetryToBuffer,
|
|
287
|
-
"failed to transfer telemetry to different buffer storage, telemetry will be lost: " + getExceptionName(e),
|
|
288
|
-
{ exception: dumpObj(e) });
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
_checkMaxSize();
|
|
292
|
-
} else {
|
|
293
|
-
_self._buffer = canUseSessionStorage
|
|
294
|
-
? new SessionStorageSendBuffer(diagLog, senderConfig) : new ArraySendBuffer(diagLog, senderConfig);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
_namePrefix = namePrefix;
|
|
298
|
-
_sessionStorageUsed = canUseSessionStorage;
|
|
299
|
-
|
|
300
|
-
_self._sample = new Sample(senderConfig.samplingPercentage, diagLog);
|
|
301
|
-
|
|
302
|
-
_instrumentationKey = senderConfig.instrumentationKey;
|
|
303
|
-
if(!_validateInstrumentationKey(_instrumentationKey, config)) {
|
|
304
|
-
_throwInternal(diagLog,
|
|
305
|
-
eLoggingSeverity.CRITICAL,
|
|
306
|
-
_eInternalMessageId.InvalidInstrumentationKey, "Invalid Instrumentation key " + _instrumentationKey);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
_customHeaders = senderConfig.customHeaders;
|
|
310
|
-
if (!isInternalApplicationInsightsEndpoint(_endpointUrl) && _customHeaders && _customHeaders.length > 0) {
|
|
311
|
-
arrForEach(_customHeaders, customHeader => {
|
|
312
|
-
this.addHeader(customHeader.header, customHeader.value);
|
|
313
|
-
});
|
|
314
|
-
} else {
|
|
315
|
-
_customHeaders = null;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
let sendPostFunc: SenderFunction = null;
|
|
319
|
-
if (!senderConfig.disableXhr && useXDomainRequest()) {
|
|
320
|
-
sendPostFunc = _xdrSender; // IE 8 and 9
|
|
321
|
-
} else if (!senderConfig.disableXhr && isXhrSupported()) {
|
|
322
|
-
sendPostFunc = _xhrSender;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (!sendPostFunc && isFetchSupported()) {
|
|
326
|
-
sendPostFunc = _fetchSender;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// always fallback to XHR
|
|
330
|
-
_fallbackSender = sendPostFunc || _xhrSender;
|
|
331
|
-
|
|
332
|
-
if (!senderConfig.isBeaconApiDisabled && isBeaconsSupported()) {
|
|
333
|
-
// Config is set to always used beacon sending
|
|
334
|
-
sendPostFunc = _beaconSender;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
_self._sender = sendPostFunc || _xhrSender;
|
|
338
|
-
|
|
339
|
-
if (!senderConfig.onunloadDisableFetch && isFetchSupported(true)) {
|
|
340
|
-
// Try and use the fetch with keepalive
|
|
341
|
-
_syncUnloadSender = _fetchKeepAliveSender;
|
|
342
|
-
} else if (isBeaconsSupported()) {
|
|
343
|
-
// Try and use sendBeacon
|
|
344
|
-
_syncUnloadSender = _beaconSender;
|
|
345
|
-
} else if (!senderConfig.disableXhr && useXDomainRequest()) {
|
|
346
|
-
_syncUnloadSender = _xdrSender; // IE 8 and 9
|
|
347
|
-
} else if (!senderConfig.disableXhr && isXhrSupported()) {
|
|
348
|
-
_syncUnloadSender = _xhrSender;
|
|
349
|
-
} else {
|
|
350
|
-
_syncUnloadSender = _fallbackSender;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
_disableTelemetry = senderConfig.disableTelemetry;
|
|
354
|
-
_convertUndefined = senderConfig.convertUndefined || UNDEFINED_VALUE;
|
|
355
|
-
_isRetryDisabled = senderConfig.isRetryDisabled;
|
|
356
|
-
_maxBatchInterval = senderConfig.maxBatchInterval;
|
|
357
|
-
}));
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
_self.processTelemetry = (telemetryItem: ITelemetryItem, itemCtx?: IProcessTelemetryContext) => {
|
|
361
|
-
itemCtx = _self._getTelCtx(itemCtx);
|
|
362
|
-
let diagLogger = itemCtx.diagLog();
|
|
363
|
-
|
|
364
|
-
try {
|
|
365
|
-
// if master off switch is set, don't send any data
|
|
366
|
-
if (_disableTelemetry) {
|
|
367
|
-
// Do not send/save data
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// validate input
|
|
372
|
-
if (!telemetryItem) {
|
|
373
|
-
_throwInternal(diagLogger, eLoggingSeverity.CRITICAL, _eInternalMessageId.CannotSendEmptyTelemetry, "Cannot send empty telemetry");
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// validate event
|
|
378
|
-
if (telemetryItem.baseData && !telemetryItem.baseType) {
|
|
379
|
-
_throwInternal(diagLogger, eLoggingSeverity.CRITICAL, _eInternalMessageId.InvalidEvent, "Cannot send telemetry without baseData and baseType");
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (!telemetryItem.baseType) {
|
|
384
|
-
// Default
|
|
385
|
-
telemetryItem.baseType = "EventData";
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// ensure a sender was constructed
|
|
389
|
-
if (!_self._sender) {
|
|
390
|
-
_throwInternal(diagLogger, eLoggingSeverity.CRITICAL, _eInternalMessageId.SenderNotInitialized, "Sender was not initialized");
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// check if this item should be sampled in, else add sampleRate tag
|
|
395
|
-
if (!_isSampledIn(telemetryItem)) {
|
|
396
|
-
// Item is sampled out, do not send it
|
|
397
|
-
_throwInternal(diagLogger, eLoggingSeverity.WARNING, _eInternalMessageId.TelemetrySampledAndNotSent,
|
|
398
|
-
"Telemetry item was sampled out and not sent", { SampleRate: _self._sample.sampleRate });
|
|
399
|
-
return;
|
|
400
|
-
} else {
|
|
401
|
-
telemetryItem[SampleRate] = _self._sample.sampleRate;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// construct an envelope that Application Insights endpoint can understand
|
|
405
|
-
// if ikey of telemetry is provided and not empty, envelope will use this iKey instead of senderConfig iKey
|
|
406
|
-
let defaultEnvelopeIkey = telemetryItem.iKey || _instrumentationKey;
|
|
407
|
-
let aiEnvelope = Sender.constructEnvelope(telemetryItem, defaultEnvelopeIkey, diagLogger, _convertUndefined);
|
|
408
|
-
if (!aiEnvelope) {
|
|
409
|
-
_throwInternal(diagLogger, eLoggingSeverity.CRITICAL, _eInternalMessageId.CreateEnvelopeError, "Unable to create an AppInsights envelope");
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
let doNotSendItem = false;
|
|
414
|
-
// this is for running in legacy mode, where customer may already have a custom initializer present
|
|
415
|
-
if (telemetryItem.tags && telemetryItem.tags[ProcessLegacy]) {
|
|
416
|
-
arrForEach(telemetryItem.tags[ProcessLegacy], (callBack: (env: IEnvelope) => boolean | void) => {
|
|
417
|
-
try {
|
|
418
|
-
if (callBack && callBack(aiEnvelope) === false) {
|
|
419
|
-
doNotSendItem = true;
|
|
420
|
-
_warnToConsole(diagLogger, "Telemetry processor check returns false");
|
|
421
|
-
}
|
|
422
|
-
} catch (e) {
|
|
423
|
-
// log error but dont stop executing rest of the telemetry initializers
|
|
424
|
-
// doNotSendItem = true;
|
|
425
|
-
_throwInternal(diagLogger,
|
|
426
|
-
eLoggingSeverity.CRITICAL, _eInternalMessageId.TelemetryInitializerFailed, "One of telemetry initializers failed, telemetry item will not be sent: " + getExceptionName(e),
|
|
427
|
-
{ exception: dumpObj(e) }, true);
|
|
428
|
-
}
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
delete telemetryItem.tags[ProcessLegacy];
|
|
432
|
-
}
|
|
433
|
-
if (doNotSendItem) {
|
|
434
|
-
return; // do not send, no need to execute next plugin
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// check if the incoming payload is too large, truncate if necessary
|
|
438
|
-
const payload: string = _serializer.serialize(aiEnvelope);
|
|
439
|
-
|
|
440
|
-
// flush if we would exceed the max-size limit by adding this item
|
|
441
|
-
const buffer = _self._buffer;
|
|
442
|
-
_checkMaxSize(payload);
|
|
443
|
-
|
|
444
|
-
// enqueue the payload
|
|
445
|
-
buffer.enqueue(payload);
|
|
446
|
-
|
|
447
|
-
// ensure an invocation timeout is set
|
|
448
|
-
_setupTimer();
|
|
449
|
-
|
|
450
|
-
} catch (e) {
|
|
451
|
-
_throwInternal(diagLogger,
|
|
452
|
-
eLoggingSeverity.WARNING,
|
|
453
|
-
_eInternalMessageId.FailedAddingTelemetryToBuffer,
|
|
454
|
-
"Failed adding telemetry to the sender's buffer, some telemetry will be lost: " + getExceptionName(e),
|
|
455
|
-
{ exception: dumpObj(e) });
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// hand off the telemetry item to the next plugin
|
|
459
|
-
_self.processNext(telemetryItem, itemCtx);
|
|
460
|
-
};
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* xhr state changes
|
|
464
|
-
*/
|
|
465
|
-
_self._xhrReadyStateChange = (xhr: XMLHttpRequest, payload: string[], countOfItemsInPayload: number) => {
|
|
466
|
-
if (xhr.readyState === 4) {
|
|
467
|
-
_checkResponsStatus(xhr.status, payload, xhr.responseURL, countOfItemsInPayload, _formatErrorMessageXhr(xhr), _getResponseText(xhr) || xhr.response);
|
|
468
|
-
}
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
/**
|
|
472
|
-
* Immediately send buffered data
|
|
473
|
-
* @param async - {boolean} - Indicates if the events should be sent asynchronously
|
|
474
|
-
* @param forcedSender - {SenderFunction} - Indicates the forcedSender, undefined if not passed
|
|
475
|
-
*/
|
|
476
|
-
_self.triggerSend = (async = true, forcedSender?: SenderFunction, sendReason?: SendRequestReason) => {
|
|
477
|
-
if (!_paused) {
|
|
478
|
-
try {
|
|
479
|
-
const buffer = _self._buffer;
|
|
480
|
-
|
|
481
|
-
// Send data only if disableTelemetry is false
|
|
482
|
-
if (!_disableTelemetry) {
|
|
483
|
-
|
|
484
|
-
if (buffer.count() > 0) {
|
|
485
|
-
const payload = buffer.getItems();
|
|
486
|
-
|
|
487
|
-
_notifySendRequest(sendReason||SendRequestReason.Undefined, async);
|
|
488
|
-
|
|
489
|
-
// invoke send
|
|
490
|
-
if (forcedSender) {
|
|
491
|
-
forcedSender.call(this, payload, async);
|
|
492
|
-
} else {
|
|
493
|
-
_self._sender(payload, async);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// update lastSend time to enable throttling
|
|
498
|
-
_lastSend = +new Date;
|
|
499
|
-
} else {
|
|
500
|
-
buffer.clear();
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
_clearScheduledTimer();
|
|
504
|
-
} catch (e) {
|
|
505
|
-
/* Ignore this error for IE under v10 */
|
|
506
|
-
let ieVer = getIEVersion();
|
|
507
|
-
if (!ieVer || ieVer > 9) {
|
|
508
|
-
_throwInternal(_self.diagLog(),
|
|
509
|
-
eLoggingSeverity.CRITICAL,
|
|
510
|
-
_eInternalMessageId.TransmissionFailed,
|
|
511
|
-
"Telemetry transmission failed, some telemetry will be lost: " + getExceptionName(e),
|
|
512
|
-
{ exception: dumpObj(e) });
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
};
|
|
517
|
-
|
|
518
|
-
_self._doTeardown = (unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState) => {
|
|
519
|
-
_self.onunloadFlush();
|
|
520
|
-
_offlineListener.unload();
|
|
521
|
-
_initDefaults();
|
|
522
|
-
};
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* error handler
|
|
526
|
-
*/
|
|
527
|
-
_self._onError = (payload: string[], message: string, event?: ErrorEvent) => {
|
|
528
|
-
_throwInternal(_self.diagLog(),
|
|
529
|
-
eLoggingSeverity.WARNING,
|
|
530
|
-
_eInternalMessageId.OnError,
|
|
531
|
-
"Failed to send telemetry.",
|
|
532
|
-
{ message });
|
|
533
|
-
|
|
534
|
-
_self._buffer.clearSent(payload);
|
|
535
|
-
};
|
|
536
|
-
|
|
537
|
-
/**
|
|
538
|
-
* partial success handler
|
|
539
|
-
*/
|
|
540
|
-
_self._onPartialSuccess = (payload: string[], results: IBackendResponse) => {
|
|
541
|
-
const failed: string[] = [];
|
|
542
|
-
const retry: string[] = [];
|
|
543
|
-
|
|
544
|
-
// Iterate through the reversed array of errors so that splicing doesn't have invalid indexes after the first item.
|
|
545
|
-
const errors = results.errors.reverse();
|
|
546
|
-
for (const error of errors) {
|
|
547
|
-
const extracted = payload.splice(error.index, 1)[0];
|
|
548
|
-
if (_isRetriable(error.statusCode)) {
|
|
549
|
-
retry.push(extracted);
|
|
550
|
-
} else {
|
|
551
|
-
// All other errors, including: 402 (Monthly quota exceeded) and 439 (Too many requests and refresh cache).
|
|
552
|
-
failed.push(extracted);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
if (payload.length > 0) {
|
|
557
|
-
_self._onSuccess(payload, results.itemsAccepted);
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
if (failed.length > 0) {
|
|
561
|
-
_self._onError(failed, _formatErrorMessageXhr(null, ["partial success", results.itemsAccepted, "of", results.itemsReceived].join(" ")));
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
if (retry.length > 0) {
|
|
565
|
-
_resendPayload(retry);
|
|
566
|
-
|
|
567
|
-
_throwInternal(_self.diagLog(),
|
|
568
|
-
eLoggingSeverity.WARNING,
|
|
569
|
-
_eInternalMessageId.TransmissionFailed, "Partial success. " +
|
|
570
|
-
"Delivered: " + payload.length + ", Failed: " + failed.length +
|
|
571
|
-
". Will retry to send " + retry.length + " our of " + results.itemsReceived + " items");
|
|
572
|
-
}
|
|
573
|
-
};
|
|
574
|
-
|
|
575
|
-
/**
|
|
576
|
-
* success handler
|
|
577
|
-
*/
|
|
578
|
-
_self._onSuccess = (payload: string[], countOfItemsInPayload: number) => {
|
|
579
|
-
_self._buffer.clearSent(payload);
|
|
580
|
-
};
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
* xdr state changes
|
|
584
|
-
*/
|
|
585
|
-
_self._xdrOnLoad = (xdr: IXDomainRequest, payload: string[]) => {
|
|
586
|
-
const responseText = _getResponseText(xdr);
|
|
587
|
-
if (xdr && (responseText + "" === "200" || responseText === "")) {
|
|
588
|
-
_consecutiveErrors = 0;
|
|
589
|
-
_self._onSuccess(payload, 0);
|
|
590
|
-
} else {
|
|
591
|
-
const results = _parseResponse(responseText);
|
|
592
|
-
|
|
593
|
-
if (results && results.itemsReceived && results.itemsReceived > results.itemsAccepted
|
|
594
|
-
&& !_isRetryDisabled) {
|
|
595
|
-
_self._onPartialSuccess(payload, results);
|
|
596
|
-
} else {
|
|
597
|
-
_self._onError(payload, _formatErrorMessageXdr(xdr));
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
|
|
602
|
-
function _isSampledIn(envelope: ITelemetryItem): boolean {
|
|
603
|
-
return _self._sample.isSampledIn(envelope);
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
function _checkMaxSize(incomingPayload?: string): boolean {
|
|
607
|
-
let incomingSize = incomingPayload? incomingPayload.length : 0;
|
|
608
|
-
if ((_self._buffer.size() + incomingSize) > _maxBatchSizeInBytes) {
|
|
609
|
-
_self.triggerSend(true, null, SendRequestReason.MaxBatchSize);
|
|
610
|
-
return true;
|
|
611
|
-
}
|
|
612
|
-
return false;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
function _checkResponsStatus(status: number, payload: string[], responseUrl: string, countOfItemsInPayload: number, errorMessage: string, res: any) {
|
|
616
|
-
let response: IBackendResponse = null;
|
|
617
|
-
|
|
618
|
-
if (!_self._appId) {
|
|
619
|
-
response = _parseResponse(res);
|
|
620
|
-
if (response && response.appId) {
|
|
621
|
-
_self._appId = response.appId;
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
if ((status < 200 || status >= 300) && status !== 0) {
|
|
626
|
-
|
|
627
|
-
// Update End Point url if permanent redirect or moved permanently
|
|
628
|
-
// Updates the end point url before retry
|
|
629
|
-
if(status === 301 || status === 307 || status === 308) {
|
|
630
|
-
if(!_checkAndUpdateEndPointUrl(responseUrl)) {
|
|
631
|
-
_self._onError(payload, errorMessage);
|
|
632
|
-
return;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
if (!_isRetryDisabled && _isRetriable(status)) {
|
|
636
|
-
_resendPayload(payload);
|
|
637
|
-
_throwInternal(_self.diagLog(),
|
|
638
|
-
eLoggingSeverity.WARNING,
|
|
639
|
-
_eInternalMessageId.TransmissionFailed, ". " +
|
|
640
|
-
"Response code " + status + ". Will retry to send " + payload.length + " items.");
|
|
641
|
-
} else {
|
|
642
|
-
_self._onError(payload, errorMessage);
|
|
643
|
-
}
|
|
644
|
-
} else if (_offlineListener && !_offlineListener.isOnline()) { // offline
|
|
645
|
-
// Note: Don't check for status == 0, since adblock gives this code
|
|
646
|
-
if (!_isRetryDisabled) {
|
|
647
|
-
const offlineBackOffMultiplier = 10; // arbritrary number
|
|
648
|
-
_resendPayload(payload, offlineBackOffMultiplier);
|
|
649
|
-
|
|
650
|
-
_throwInternal(_self.diagLog(),
|
|
651
|
-
eLoggingSeverity.WARNING,
|
|
652
|
-
_eInternalMessageId.TransmissionFailed, `. Offline - Response Code: ${status}. Offline status: ${!_offlineListener.isOnline()}. Will retry to send ${payload.length} items.`);
|
|
653
|
-
}
|
|
654
|
-
} else {
|
|
655
|
-
|
|
656
|
-
// check if the xhr's responseURL or fetch's response.url is same as endpoint url
|
|
657
|
-
// TODO after 10 redirects force send telemetry with 'redirect=false' as query parameter.
|
|
658
|
-
_checkAndUpdateEndPointUrl(responseUrl);
|
|
659
|
-
|
|
660
|
-
if (status === 206) {
|
|
661
|
-
if (!response) {
|
|
662
|
-
response = _parseResponse(res);
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
if (response && !_isRetryDisabled) {
|
|
666
|
-
_self._onPartialSuccess(payload, response);
|
|
667
|
-
} else {
|
|
668
|
-
_self._onError(payload, errorMessage);
|
|
669
|
-
}
|
|
670
|
-
} else {
|
|
671
|
-
_consecutiveErrors = 0;
|
|
672
|
-
_self._onSuccess(payload, countOfItemsInPayload);
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
function _checkAndUpdateEndPointUrl(responseUrl: string) {
|
|
678
|
-
// Maximum stamp specific redirects allowed(uncomment this when breeze is ready with not allowing redirects feature)
|
|
679
|
-
if(_stamp_specific_redirects >= 10) {
|
|
680
|
-
// _self._senderConfig.endpointUrl = () => Sender._getDefaultAppInsightsChannelConfig().endpointUrl()+"/?redirect=false";
|
|
681
|
-
// _stamp_specific_redirects = 0;
|
|
682
|
-
return false;
|
|
683
|
-
}
|
|
684
|
-
if(!isNullOrUndefined(responseUrl) && responseUrl !== "") {
|
|
685
|
-
if(responseUrl !== _endpointUrl) {
|
|
686
|
-
_endpointUrl = responseUrl;
|
|
687
|
-
++_stamp_specific_redirects;
|
|
688
|
-
return true;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
return false;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
function _doUnloadSend(payload: string[], isAsync: boolean) {
|
|
695
|
-
if (_syncUnloadSender) {
|
|
696
|
-
// We are unloading so always call the sender with sync set to false
|
|
697
|
-
_syncUnloadSender(payload, false);
|
|
698
|
-
} else {
|
|
699
|
-
// Fallback to the previous beacon Sender (which causes a CORB warning on chrome now)
|
|
700
|
-
_beaconSender(payload, isAsync);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
function _doBeaconSend(payload: string[]) {
|
|
705
|
-
const nav = getNavigator();
|
|
706
|
-
const buffer = _self._buffer;
|
|
707
|
-
const url = _endpointUrl;
|
|
708
|
-
const batch = _self._buffer.batchPayloads(payload);
|
|
709
|
-
|
|
710
|
-
// Chrome only allows CORS-safelisted values for the sendBeacon data argument
|
|
711
|
-
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=720283
|
|
712
|
-
const plainTextBatch = new Blob([batch], { type: "text/plain;charset=UTF-8" });
|
|
713
|
-
|
|
714
|
-
// The sendBeacon method returns true if the user agent is able to successfully queue the data for transfer. Otherwise it returns false.
|
|
715
|
-
const queued = nav.sendBeacon(url, plainTextBatch);
|
|
716
|
-
if (queued) {
|
|
717
|
-
buffer.markAsSent(payload);
|
|
718
|
-
// no response from beaconSender, clear buffer
|
|
719
|
-
_self._onSuccess(payload, payload.length);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
return queued;
|
|
723
|
-
}
|
|
724
|
-
/**
|
|
725
|
-
* Send Beacon API request
|
|
726
|
-
* @param payload - {string} - The data payload to be sent.
|
|
727
|
-
* @param isAsync - {boolean} - not used
|
|
728
|
-
* Note: Beacon API does not support custom headers and we are not able to get
|
|
729
|
-
* appId from the backend for the correct correlation.
|
|
730
|
-
*/
|
|
731
|
-
function _beaconSender(payload: string[], isAsync: boolean) {
|
|
732
|
-
if (isArray(payload) && payload.length > 0) {
|
|
733
|
-
// The sendBeacon method returns true if the user agent is able to successfully queue the data for transfer. Otherwise it returns false.
|
|
734
|
-
if (!_doBeaconSend(payload)) {
|
|
735
|
-
// Failed to send entire payload so try and split data and try to send as much events as possible
|
|
736
|
-
let droppedPayload: string[] = [];
|
|
737
|
-
for (let lp = 0; lp < payload.length; lp++) {
|
|
738
|
-
const thePayload = payload[lp];
|
|
739
|
-
|
|
740
|
-
if (!_doBeaconSend([thePayload])) {
|
|
741
|
-
// Can't send anymore, so split the batch and drop the rest
|
|
742
|
-
droppedPayload.push(thePayload);
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
if (droppedPayload.length > 0) {
|
|
747
|
-
_fallbackSender && _fallbackSender(droppedPayload, true);
|
|
748
|
-
_throwInternal(_self.diagLog(), eLoggingSeverity.WARNING, _eInternalMessageId.TransmissionFailed, ". " + "Failed to send telemetry with Beacon API, retried with normal sender.");
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
/**
|
|
755
|
-
* Send XMLHttpRequest
|
|
756
|
-
* @param payload - {string} - The data payload to be sent.
|
|
757
|
-
* @param isAsync - {boolean} - Indicates if the request should be sent asynchronously
|
|
758
|
-
*/
|
|
759
|
-
function _xhrSender(payload: string[], isAsync: boolean) {
|
|
760
|
-
const xhr = new XMLHttpRequest();
|
|
761
|
-
const endPointUrl = _endpointUrl;
|
|
762
|
-
try {
|
|
763
|
-
xhr[DisabledPropertyName] = true;
|
|
764
|
-
} catch(e) {
|
|
765
|
-
// If the environment has locked down the XMLHttpRequest (preventExtensions and/or freeze), this would
|
|
766
|
-
// cause the request to fail and we no telemetry would be sent
|
|
767
|
-
}
|
|
768
|
-
xhr.open("POST", endPointUrl, isAsync);
|
|
769
|
-
xhr.setRequestHeader("Content-type", "application/json");
|
|
770
|
-
|
|
771
|
-
// append Sdk-Context request header only in case of breeze endpoint
|
|
772
|
-
if (isInternalApplicationInsightsEndpoint(endPointUrl)) {
|
|
773
|
-
xhr.setRequestHeader(RequestHeaders[eRequestHeaders.sdkContextHeader], RequestHeaders[eRequestHeaders.sdkContextHeaderAppIdRequest]);
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
arrForEach(objKeys(_headers), (headerName) => {
|
|
777
|
-
xhr.setRequestHeader(headerName, _headers[headerName]);
|
|
778
|
-
});
|
|
779
|
-
|
|
780
|
-
xhr.onreadystatechange = () => _self._xhrReadyStateChange(xhr, payload, payload.length);
|
|
781
|
-
xhr.onerror = (event: ErrorEvent|any) => _self._onError(payload, _formatErrorMessageXhr(xhr), event);
|
|
782
|
-
|
|
783
|
-
// compose an array of payloads
|
|
784
|
-
const batch = _self._buffer.batchPayloads(payload);
|
|
785
|
-
xhr.send(batch);
|
|
786
|
-
|
|
787
|
-
_self._buffer.markAsSent(payload);
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
function _fetchKeepAliveSender(payload: string[], isAsync: boolean) {
|
|
791
|
-
if (isArray(payload)) {
|
|
792
|
-
let payloadSize = payload.length;
|
|
793
|
-
for (let lp = 0; lp < payload.length; lp++) {
|
|
794
|
-
payloadSize += payload[lp].length;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
if ((_syncFetchPayload + payloadSize) <= FetchSyncRequestSizeLimitBytes) {
|
|
798
|
-
_doFetchSender(payload, false);
|
|
799
|
-
} else if (isBeaconsSupported()) {
|
|
800
|
-
// Fallback to beacon sender as we at least get told which events can't be scheduled
|
|
801
|
-
_beaconSender(payload, isAsync);
|
|
802
|
-
} else {
|
|
803
|
-
// Payload is going to be too big so just try and send via XHR
|
|
804
|
-
_fallbackSender && _fallbackSender(payload, true);
|
|
805
|
-
_throwInternal(_self.diagLog(), eLoggingSeverity.WARNING, _eInternalMessageId.TransmissionFailed, ". " + "Failed to send telemetry with Beacon API, retried with xhrSender.");
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
/**
|
|
811
|
-
* Send fetch API request
|
|
812
|
-
* @param payload - {string} - The data payload to be sent.
|
|
813
|
-
* @param isAsync - {boolean} - not used
|
|
814
|
-
*/
|
|
815
|
-
function _fetchSender(payload: string[], isAsync: boolean) {
|
|
816
|
-
_doFetchSender(payload, true);
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
/**
|
|
820
|
-
* Send fetch API request
|
|
821
|
-
* @param payload - {string} - The data payload to be sent.
|
|
822
|
-
* @param isAsync - {boolean} - For fetch this identifies whether we are "unloading" (false) or a normal request
|
|
823
|
-
*/
|
|
824
|
-
function _doFetchSender(payload: string[], isAsync: boolean) {
|
|
825
|
-
const endPointUrl = _endpointUrl;
|
|
826
|
-
const batch = _self._buffer.batchPayloads(payload);
|
|
827
|
-
const plainTextBatch = new Blob([batch], { type: "application/json" });
|
|
828
|
-
let requestHeaders = new Headers();
|
|
829
|
-
let batchLength = batch.length;
|
|
830
|
-
let ignoreResponse = false;
|
|
831
|
-
let responseHandled = false;
|
|
832
|
-
|
|
833
|
-
// append Sdk-Context request header only in case of breeze endpoint
|
|
834
|
-
if (isInternalApplicationInsightsEndpoint(endPointUrl)) {
|
|
835
|
-
requestHeaders.append(RequestHeaders[eRequestHeaders.sdkContextHeader], RequestHeaders[eRequestHeaders.sdkContextHeaderAppIdRequest]);
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
arrForEach(objKeys(_headers), (headerName) => {
|
|
839
|
-
requestHeaders.append(headerName, _headers[headerName]);
|
|
840
|
-
});
|
|
841
|
-
|
|
842
|
-
const init: RequestInit = {
|
|
843
|
-
method: "POST",
|
|
844
|
-
headers: requestHeaders,
|
|
845
|
-
body: plainTextBatch,
|
|
846
|
-
[DisabledPropertyName]: true // Mark so we don't attempt to track this request
|
|
847
|
-
};
|
|
848
|
-
|
|
849
|
-
if (!isAsync) {
|
|
850
|
-
init.keepalive = true;
|
|
851
|
-
// As a sync request (during unload), it is unlikely that we will get a chance to process the response so
|
|
852
|
-
// just like beacon send assume that the events have been accepted and processed
|
|
853
|
-
ignoreResponse = true;
|
|
854
|
-
_syncFetchPayload += batchLength;
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
const request = new Request(endPointUrl, init);
|
|
858
|
-
try {
|
|
859
|
-
// Also try and tag the request (just in case the value in init is not copied over)
|
|
860
|
-
request[DisabledPropertyName] = true;
|
|
861
|
-
} catch(e) {
|
|
862
|
-
// If the environment has locked down the XMLHttpRequest (preventExtensions and/or freeze), this would
|
|
863
|
-
// cause the request to fail and we no telemetry would be sent
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
_self._buffer.markAsSent(payload);
|
|
867
|
-
|
|
868
|
-
try {
|
|
869
|
-
fetch(request).then(response => {
|
|
870
|
-
if (!isAsync) {
|
|
871
|
-
_syncFetchPayload -= batchLength;
|
|
872
|
-
batchLength = 0;
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
if (!responseHandled) {
|
|
876
|
-
responseHandled = true;
|
|
877
|
-
|
|
878
|
-
/**
|
|
879
|
-
* The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500.
|
|
880
|
-
* Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure
|
|
881
|
-
* or if anything prevented the request from completing.
|
|
882
|
-
*/
|
|
883
|
-
if (!response.ok) {
|
|
884
|
-
_self._onError(payload, response.statusText)
|
|
885
|
-
} else {
|
|
886
|
-
response.text().then(text => {
|
|
887
|
-
_checkResponsStatus(response.status, payload, response.url, payload.length, response.statusText, text);
|
|
888
|
-
});
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
}).catch((error: Error) => {
|
|
892
|
-
if (!isAsync) {
|
|
893
|
-
_syncFetchPayload -= batchLength;
|
|
894
|
-
batchLength = 0;
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
if (!responseHandled) {
|
|
898
|
-
responseHandled = true;
|
|
899
|
-
_self._onError(payload, error.message)
|
|
900
|
-
}
|
|
901
|
-
});
|
|
902
|
-
} catch (e) {
|
|
903
|
-
if (!responseHandled) {
|
|
904
|
-
_self._onError(payload, dumpObj(e));
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
if (ignoreResponse && !responseHandled) {
|
|
909
|
-
// Assume success during unload processing as we most likely won't get the response
|
|
910
|
-
responseHandled = true;
|
|
911
|
-
_self._onSuccess(payload, payload.length);
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
/**
|
|
916
|
-
* Parses the response from the backend.
|
|
917
|
-
* @param response - XMLHttpRequest or XDomainRequest response
|
|
918
|
-
*/
|
|
919
|
-
function _parseResponse(response: any): IBackendResponse {
|
|
920
|
-
try {
|
|
921
|
-
if (response && response !== "") {
|
|
922
|
-
const result = getJSON().parse(response);
|
|
923
|
-
|
|
924
|
-
if (result && result.itemsReceived && result.itemsReceived >= result.itemsAccepted &&
|
|
925
|
-
result.itemsReceived - result.itemsAccepted === result.errors.length) {
|
|
926
|
-
return result;
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
} catch (e) {
|
|
930
|
-
_throwInternal(_self.diagLog(),
|
|
931
|
-
eLoggingSeverity.CRITICAL,
|
|
932
|
-
_eInternalMessageId.InvalidBackendResponse,
|
|
933
|
-
"Cannot parse the response. " + getExceptionName(e),
|
|
934
|
-
{
|
|
935
|
-
response
|
|
936
|
-
});
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
return null;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
/**
|
|
943
|
-
* Resend payload. Adds payload back to the send buffer and setup a send timer (with exponential backoff).
|
|
944
|
-
* @param payload
|
|
945
|
-
*/
|
|
946
|
-
function _resendPayload(payload: string[], linearFactor: number = 1) {
|
|
947
|
-
if (!payload || payload.length === 0) {
|
|
948
|
-
return;
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
const buffer = _self._buffer;
|
|
952
|
-
buffer.clearSent(payload);
|
|
953
|
-
_consecutiveErrors++;
|
|
954
|
-
|
|
955
|
-
for (const item of payload) {
|
|
956
|
-
buffer.enqueue(item);
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
// setup timer
|
|
960
|
-
_setRetryTime(linearFactor);
|
|
961
|
-
_setupTimer();
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
/**
|
|
965
|
-
* Calculates the time to wait before retrying in case of an error based on
|
|
966
|
-
* http://en.wikipedia.org/wiki/Exponential_backoff
|
|
967
|
-
*/
|
|
968
|
-
function _setRetryTime(linearFactor: number) {
|
|
969
|
-
const SlotDelayInSeconds = 10;
|
|
970
|
-
let delayInSeconds: number;
|
|
971
|
-
|
|
972
|
-
if (_consecutiveErrors <= 1) {
|
|
973
|
-
delayInSeconds = SlotDelayInSeconds;
|
|
974
|
-
} else {
|
|
975
|
-
const backOffSlot = (Math.pow(2, _consecutiveErrors) - 1) / 2;
|
|
976
|
-
// tslint:disable-next-line:insecure-random
|
|
977
|
-
let backOffDelay = Math.floor(Math.random() * backOffSlot * SlotDelayInSeconds) + 1;
|
|
978
|
-
backOffDelay = linearFactor * backOffDelay;
|
|
979
|
-
delayInSeconds = Math.max(Math.min(backOffDelay, 3600), SlotDelayInSeconds);
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
// TODO: Log the backoff time like the C# version does.
|
|
983
|
-
const retryAfterTimeSpan = dateNow() + (delayInSeconds * 1000);
|
|
984
|
-
|
|
985
|
-
// TODO: Log the retry at time like the C# version does.
|
|
986
|
-
_retryAt = retryAfterTimeSpan;
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
/**
|
|
990
|
-
* Sets up the timer which triggers actually sending the data.
|
|
991
|
-
*/
|
|
992
|
-
function _setupTimer() {
|
|
993
|
-
if (!_timeoutHandle && !_paused) {
|
|
994
|
-
const retryInterval = _retryAt ? Math.max(0, _retryAt - dateNow()) : 0;
|
|
995
|
-
const timerValue = Math.max(_maxBatchInterval, retryInterval);
|
|
996
|
-
|
|
997
|
-
_timeoutHandle = scheduleTimeout(() => {
|
|
998
|
-
_timeoutHandle = null;
|
|
999
|
-
_self.triggerSend(true, null, SendRequestReason.NormalSchedule);
|
|
1000
|
-
}, timerValue);
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
function _clearScheduledTimer() {
|
|
1005
|
-
_timeoutHandle && _timeoutHandle.cancel();
|
|
1006
|
-
_timeoutHandle = null;
|
|
1007
|
-
_retryAt = null;
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
/**
|
|
1011
|
-
* Checks if the SDK should resend the payload after receiving this status code from the backend.
|
|
1012
|
-
* @param statusCode
|
|
1013
|
-
*/
|
|
1014
|
-
function _isRetriable(statusCode: number): boolean {
|
|
1015
|
-
return statusCode === 401 // Unauthorized
|
|
1016
|
-
|| statusCode === 403 // Forbidden
|
|
1017
|
-
|| statusCode === 408 // Timeout
|
|
1018
|
-
|| statusCode === 429 // Too many requests.
|
|
1019
|
-
|| statusCode === 500 // Internal server error.
|
|
1020
|
-
|| statusCode === 502 // Bad Gateway.
|
|
1021
|
-
|| statusCode === 503 // Service unavailable.
|
|
1022
|
-
|| statusCode === 504; // Gateway timeout.
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
function _formatErrorMessageXhr(xhr: XMLHttpRequest, message?: string): string {
|
|
1026
|
-
if (xhr) {
|
|
1027
|
-
return "XMLHttpRequest,Status:" + xhr.status + ",Response:" + _getResponseText(xhr) || xhr.response || "";
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
return message;
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
/**
|
|
1034
|
-
* Send XDomainRequest
|
|
1035
|
-
* @param payload - {string} - The data payload to be sent.
|
|
1036
|
-
* @param isAsync - {boolean} - Indicates if the request should be sent asynchronously
|
|
1037
|
-
*
|
|
1038
|
-
* Note: XDomainRequest does not support sync requests. This 'isAsync' parameter is added
|
|
1039
|
-
* to maintain consistency with the xhrSender's contract
|
|
1040
|
-
* Note: XDomainRequest does not support custom headers and we are not able to get
|
|
1041
|
-
* appId from the backend for the correct correlation.
|
|
1042
|
-
*/
|
|
1043
|
-
function _xdrSender(payload: string[], isAsync: boolean) {
|
|
1044
|
-
const buffer = _self._buffer;
|
|
1045
|
-
let _window = getWindow();
|
|
1046
|
-
const xdr = new XDomainRequest();
|
|
1047
|
-
// NOTE: xdr may send previous retry payload to new endpoint since we are not able to check response URL
|
|
1048
|
-
xdr.onload = () => _self._xdrOnLoad(xdr, payload);
|
|
1049
|
-
xdr.onerror = (event: ErrorEvent|any) => _self._onError(payload, _formatErrorMessageXdr(xdr), event);
|
|
1050
|
-
|
|
1051
|
-
// XDomainRequest requires the same protocol as the hosting page.
|
|
1052
|
-
// If the protocol doesn't match, we can't send the telemetry :(.
|
|
1053
|
-
const hostingProtocol = _window && _window.location && _window.location.protocol || "";
|
|
1054
|
-
if (_endpointUrl.lastIndexOf(hostingProtocol, 0) !== 0) {
|
|
1055
|
-
_throwInternal(_self.diagLog(),
|
|
1056
|
-
eLoggingSeverity.WARNING,
|
|
1057
|
-
_eInternalMessageId.TransmissionFailed, ". " +
|
|
1058
|
-
"Cannot send XDomain request. The endpoint URL protocol doesn't match the hosting page protocol.");
|
|
1059
|
-
|
|
1060
|
-
buffer.clear();
|
|
1061
|
-
return;
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
const endpointUrl = _endpointUrl.replace(/^(https?:)/, "");
|
|
1065
|
-
xdr.open("POST", endpointUrl);
|
|
1066
|
-
|
|
1067
|
-
// compose an array of payloads
|
|
1068
|
-
const batch = buffer.batchPayloads(payload);
|
|
1069
|
-
xdr.send(batch);
|
|
1070
|
-
|
|
1071
|
-
buffer.markAsSent(payload);
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
function _formatErrorMessageXdr(xdr: IXDomainRequest, message?: string): string {
|
|
1075
|
-
if (xdr) {
|
|
1076
|
-
return "XDomainRequest,Response:" + _getResponseText(xdr) || "";
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
return message;
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
// Using function lookups for backward compatibility as the getNotifyMgr() did not exist until after v2.5.6
|
|
1083
|
-
function _getNotifyMgr() : INotificationManager {
|
|
1084
|
-
const func = "getNotifyMgr";
|
|
1085
|
-
if (_self.core[func]) {
|
|
1086
|
-
return _self.core[func]();
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
// using _self.core['_notificationManager'] for backward compatibility
|
|
1090
|
-
return _self.core["_notificationManager"];
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
function _notifySendRequest(sendRequest: SendRequestReason, isAsync: boolean) {
|
|
1094
|
-
let manager = _getNotifyMgr();
|
|
1095
|
-
if (manager && manager.eventsSendRequest) {
|
|
1096
|
-
try {
|
|
1097
|
-
manager.eventsSendRequest(sendRequest, isAsync);
|
|
1098
|
-
} catch (e) {
|
|
1099
|
-
_throwInternal(_self.diagLog(), eLoggingSeverity.CRITICAL,
|
|
1100
|
-
_eInternalMessageId.NotificationException,
|
|
1101
|
-
"send request notification failed: " + getExceptionName(e),
|
|
1102
|
-
{ exception: dumpObj(e) });
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
/**
|
|
1108
|
-
* Validate UUID Format
|
|
1109
|
-
* Specs taken from https://tools.ietf.org/html/rfc4122 and breeze repo
|
|
1110
|
-
*/
|
|
1111
|
-
function _validateInstrumentationKey(instrumentationKey: string, config: IConfiguration & IConfig) :boolean {
|
|
1112
|
-
let disableValidation = config.disableInstrumentationKeyValidation;
|
|
1113
|
-
const disableIKeyValidationFlag = isNullOrUndefined(disableValidation) ? false : disableValidation;
|
|
1114
|
-
if(disableIKeyValidationFlag) {
|
|
1115
|
-
return true;
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
const UUID_Regex = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
|
|
1119
|
-
const regexp = new RegExp(UUID_Regex);
|
|
1120
|
-
return regexp.test(instrumentationKey);
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
function _initDefaults() {
|
|
1124
|
-
_self._sender = null;
|
|
1125
|
-
_self._buffer = null;
|
|
1126
|
-
_self._appId = null;
|
|
1127
|
-
_self._sample = null;
|
|
1128
|
-
_headers = {};
|
|
1129
|
-
_offlineListener = null;
|
|
1130
|
-
_consecutiveErrors = 0;
|
|
1131
|
-
_retryAt = null;
|
|
1132
|
-
_lastSend = null;
|
|
1133
|
-
_paused = false;
|
|
1134
|
-
_timeoutHandle = null;
|
|
1135
|
-
_serializer = null;
|
|
1136
|
-
_stamp_specific_redirects = 0;
|
|
1137
|
-
_syncFetchPayload = 0;
|
|
1138
|
-
_fallbackSender = null;
|
|
1139
|
-
_syncUnloadSender = null;
|
|
1140
|
-
_evtNamespace = null;
|
|
1141
|
-
_endpointUrl = null;
|
|
1142
|
-
_orgEndpointUrl = null;
|
|
1143
|
-
_maxBatchSizeInBytes = 0;
|
|
1144
|
-
_beaconSupported = false;
|
|
1145
|
-
_customHeaders = null;
|
|
1146
|
-
_disableTelemetry = false;
|
|
1147
|
-
_instrumentationKey = null;
|
|
1148
|
-
_convertUndefined = UNDEFINED_VALUE;
|
|
1149
|
-
_isRetryDisabled = false;
|
|
1150
|
-
_sessionStorageUsed = null;
|
|
1151
|
-
_namePrefix = UNDEFINED_VALUE;
|
|
1152
|
-
|
|
1153
|
-
objDefine(_self, "_senderConfig", {
|
|
1154
|
-
g: function() {
|
|
1155
|
-
return objExtend({}, defaultAppInsightsChannelConfig);
|
|
1156
|
-
}
|
|
1157
|
-
});
|
|
1158
|
-
}
|
|
1159
|
-
});
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
/**
|
|
1163
|
-
* Pause the sending (transmission) of events, this will cause all events to be batched only until the maximum limits are
|
|
1164
|
-
* hit at which point new events are dropped. Will also cause events to NOT be sent during page unload, so if Session storage
|
|
1165
|
-
* is disabled events will be lost.
|
|
1166
|
-
* SessionStorage Limit is 2000 events, In-Memory (Array) Storage is 10,000 events (can be configured via the eventsLimitInMem).
|
|
1167
|
-
*/
|
|
1168
|
-
public pause(): void {
|
|
1169
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
/**
|
|
1173
|
-
* Resume the sending (transmission) of events, this will restart the timer and any batched events will be sent using the normal
|
|
1174
|
-
* send interval.
|
|
1175
|
-
*/
|
|
1176
|
-
public resume(): void {
|
|
1177
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
/**
|
|
1181
|
-
* Flush the batched events immediately (not synchronously).
|
|
1182
|
-
* Will not flush if the Sender has been paused.
|
|
1183
|
-
*/
|
|
1184
|
-
public flush() {
|
|
1185
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
/**
|
|
1189
|
-
* Flush the batched events synchronously (if possible -- based on configuration).
|
|
1190
|
-
* Will not flush if the Send has been paused.
|
|
1191
|
-
*/
|
|
1192
|
-
public onunloadFlush() {
|
|
1193
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1194
|
-
}
|
|
1195
|
-
|
|
1196
|
-
public initialize(config: IConfiguration & IConfig, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?:ITelemetryPluginChain): void {
|
|
1197
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
public processTelemetry(telemetryItem: ITelemetryItem, itemCtx?: IProcessTelemetryContext) {
|
|
1201
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1202
|
-
}
|
|
1203
|
-
|
|
1204
|
-
/**
|
|
1205
|
-
* xhr state changes
|
|
1206
|
-
*/
|
|
1207
|
-
public _xhrReadyStateChange(xhr: XMLHttpRequest, payload: string[], countOfItemsInPayload: number) {
|
|
1208
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
/**
|
|
1212
|
-
* Immediately send buffered data
|
|
1213
|
-
* @param async - {boolean} - Indicates if the events should be sent asynchronously
|
|
1214
|
-
* @param forcedSender - {SenderFunction} - Indicates the forcedSender, undefined if not passed
|
|
1215
|
-
*/
|
|
1216
|
-
public triggerSend(async = true, forcedSender?: SenderFunction, sendReason?: SendRequestReason) {
|
|
1217
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
/**
|
|
1221
|
-
* error handler
|
|
1222
|
-
*/
|
|
1223
|
-
public _onError(payload: string[], message: string, event?: ErrorEvent) {
|
|
1224
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
/**
|
|
1228
|
-
* partial success handler
|
|
1229
|
-
*/
|
|
1230
|
-
public _onPartialSuccess(payload: string[], results: IBackendResponse) {
|
|
1231
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
/**
|
|
1235
|
-
* success handler
|
|
1236
|
-
*/
|
|
1237
|
-
public _onSuccess(payload: string[], countOfItemsInPayload: number) {
|
|
1238
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
/**
|
|
1242
|
-
* xdr state changes
|
|
1243
|
-
*/
|
|
1244
|
-
public _xdrOnLoad(xdr: IXDomainRequest, payload: string[]) {
|
|
1245
|
-
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
/**
|
|
1249
|
-
* Add header to request
|
|
1250
|
-
* @param name - Header name.
|
|
1251
|
-
* @param value - Header value.
|
|
1252
|
-
*/
|
|
1253
|
-
public addHeader(name: string, value: string) {
|
|
1254
|
-
// @DynamicProtoStub - DO NOT add any code as this will be removed during packaging
|
|
1255
|
-
}
|
|
1256
|
-
}
|