@microsoft/applicationinsights-channel-js 2.8.0-beta.2203-04 → 2.8.0-beta.2203-05

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/src/Sender.ts CHANGED
@@ -17,10 +17,11 @@ import {
17
17
  ITelemetryItem, IProcessTelemetryContext, IConfiguration,
18
18
  _InternalMessageId, LoggingSeverity, IDiagnosticLogger, IAppInsightsCore, IPlugin,
19
19
  getWindow, getNavigator, getJSON, BaseTelemetryPlugin, ITelemetryPluginChain, INotificationManager,
20
- SendRequestReason, objForEachKey, isNullOrUndefined, arrForEach, dateNow, dumpObj, getExceptionName, getIEVersion, throwError, objKeys,
21
- isBeaconsSupported, isFetchSupported, useXDomainRequest, isXhrSupported, isArray
20
+ SendRequestReason, objForEachKey, isNullOrUndefined, arrForEach, dateNow, dumpObj, getExceptionName, getIEVersion, objKeys,
21
+ isBeaconsSupported, isFetchSupported, useXDomainRequest, isXhrSupported, isArray, createUniqueNamespace, mergeEvtNamespace,
22
+ IProcessTelemetryUnloadContext, ITelemetryUnloadState, _throwInternal
22
23
  } from "@microsoft/applicationinsights-core-js";
23
- import { Offline } from "./Offline";
24
+ import { createOfflineListener, IOfflineListener } from "./Offline";
24
25
  import { Sample } from "./TelemetryProcessors/Sample"
25
26
  import dynamicProto from "@microsoft/dynamicproto-js";
26
27
 
@@ -103,7 +104,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
103
104
  /**
104
105
  * The configuration for this sender instance
105
106
  */
106
- public readonly _senderConfig: ISenderConfig;
107
+ public readonly _senderConfig: ISenderConfig = _getDefaultAppInsightsChannelConfig();
107
108
 
108
109
  /**
109
110
  * A method which will cause data to be send to the url
@@ -125,57 +126,24 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
125
126
  constructor() {
126
127
  super();
127
128
 
128
- /**
129
- * How many times in a row a retryable error condition has occurred.
130
- */
131
- let _consecutiveErrors: number;
132
-
133
- /**
134
- * The time to retry at in milliseconds from 1970/01/01 (this makes the timer calculation easy).
135
- */
136
- let _retryAt: number;
137
-
138
- /**
139
- * The time of the last send operation.
140
- */
141
- let _lastSend: number;
142
-
143
- /**
144
- * Flag indicating that the sending should be paused
145
- */
146
- let _paused = false;
147
-
148
- /**
149
- * Handle to the timer for delayed sending of batches of data.
150
- */
151
- let _timeoutHandle: any;
152
-
129
+ // Don't set the defaults here, set them in the _initDefaults() as this is also called during unload
130
+ let _consecutiveErrors: number; // How many times in a row a retryable error condition has occurred.
131
+ let _retryAt: number; // The time to retry at in milliseconds from 1970/01/01 (this makes the timer calculation easy).
132
+ let _lastSend: number; // The time of the last send operation.
133
+ let _paused: boolean; // Flag indicating that the sending should be paused
134
+ let _timeoutHandle: any; // Handle to the timer for delayed sending of batches of data.
153
135
  let _serializer: Serializer;
154
-
155
136
  let _stamp_specific_redirects: number;
156
-
157
- let _headers: { [name: string]: string } = {};
158
-
159
- // Keep track of the outstanding sync fetch payload total (as sync fetch has limits)
160
- let _syncFetchPayload = 0;
161
-
162
- /**
163
- * The sender to use if the payload size is too large
164
- */
165
- let _fallbackSender: SenderFunction;
166
-
167
- /**
168
- * The identified sender to use for the synchronous unload stage
169
- */
170
- let _syncUnloadSender: SenderFunction;
171
-
172
- this._senderConfig = _getDefaultAppInsightsChannelConfig();
137
+ let _headers: { [name: string]: string };
138
+ let _syncFetchPayload = 0; // Keep track of the outstanding sync fetch payload total (as sync fetch has limits)
139
+ let _fallbackSender: SenderFunction; // The sender to use if the payload size is too large
140
+ let _syncUnloadSender: SenderFunction; // The identified sender to use for the synchronous unload stage
141
+ let _offlineListener: IOfflineListener;
142
+ let _evtNamespace: string | string[];
173
143
 
174
144
  dynamicProto(Sender, this, (_self, _base) => {
175
145
 
176
- function _notImplemented() {
177
- throwError("Method not implemented.");
178
- }
146
+ _initDefaults();
179
147
 
180
148
  _self.pause = () => {
181
149
  _clearScheduledTimer();
@@ -204,7 +172,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
204
172
  try {
205
173
  _self.triggerSend(isAsync, null, sendReason || SendRequestReason.ManualFlush);
206
174
  } catch (e) {
207
- _self.diagLog().throwInternal(LoggingSeverity.CRITICAL,
175
+ _throwInternal(_self.diagLog(),LoggingSeverity.CRITICAL,
208
176
  _InternalMessageId.FlushFailed,
209
177
  "flush failed, telemetry will not be collected: " + getExceptionName(e),
210
178
  { exception: dumpObj(e) });
@@ -218,7 +186,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
218
186
  try {
219
187
  _self.triggerSend(true, _doUnloadSend, SendRequestReason.Unload);
220
188
  } catch (e) {
221
- _self.diagLog().throwInternal(LoggingSeverity.CRITICAL,
189
+ _throwInternal(_self.diagLog(),LoggingSeverity.CRITICAL,
222
190
  _InternalMessageId.FailedToSendQueuedTelemetry,
223
191
  "failed to flush with beacon sender on page unload, telemetry will not be collected: " + getExceptionName(e),
224
192
  { exception: dumpObj(e) });
@@ -229,8 +197,6 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
229
197
  }
230
198
  };
231
199
 
232
- _self.teardown = _notImplemented;
233
-
234
200
  _self.addHeader = (name: string, value: string) => {
235
201
  _headers[name] = value;
236
202
  };
@@ -246,6 +212,8 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
246
212
  _self._sender = null;
247
213
  _stamp_specific_redirects = 0;
248
214
  let diagLog = _self.diagLog();
215
+ _evtNamespace = mergeEvtNamespace(createUniqueNamespace("Sender"), core.evtNamespace && core.evtNamespace());
216
+ _offlineListener = createOfflineListener(_evtNamespace);
249
217
 
250
218
  const defaultConfig = _getDefaultAppInsightsChannelConfig();
251
219
  objForEachKey(defaultConfig, (field, value) => {
@@ -257,7 +225,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
257
225
  _self._sample = new Sample(_self._senderConfig.samplingPercentage(), diagLog);
258
226
 
259
227
  if(!_validateInstrumentationKey(config)) {
260
- diagLog.throwInternal(
228
+ _throwInternal(diagLog,
261
229
  LoggingSeverity.CRITICAL,
262
230
  _InternalMessageId.InvalidInstrumentationKey, "Invalid Instrumentation key "+config.instrumentationKey);
263
231
  }
@@ -317,13 +285,13 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
317
285
 
318
286
  // validate input
319
287
  if (!telemetryItem) {
320
- itemCtx.diagLog().throwInternal(LoggingSeverity.CRITICAL, _InternalMessageId.CannotSendEmptyTelemetry, "Cannot send empty telemetry");
288
+ _throwInternal(itemCtx.diagLog(), LoggingSeverity.CRITICAL, _InternalMessageId.CannotSendEmptyTelemetry, "Cannot send empty telemetry");
321
289
  return;
322
290
  }
323
291
 
324
292
  // validate event
325
293
  if (telemetryItem.baseData && !telemetryItem.baseType) {
326
- itemCtx.diagLog().throwInternal(LoggingSeverity.CRITICAL, _InternalMessageId.InvalidEvent, "Cannot send telemetry without baseData and baseType");
294
+ _throwInternal(itemCtx.diagLog(), LoggingSeverity.CRITICAL, _InternalMessageId.InvalidEvent, "Cannot send telemetry without baseData and baseType");
327
295
  return;
328
296
  }
329
297
 
@@ -334,14 +302,14 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
334
302
 
335
303
  // ensure a sender was constructed
336
304
  if (!_self._sender) {
337
- itemCtx.diagLog().throwInternal(LoggingSeverity.CRITICAL, _InternalMessageId.SenderNotInitialized, "Sender was not initialized");
305
+ _throwInternal(itemCtx.diagLog(), LoggingSeverity.CRITICAL, _InternalMessageId.SenderNotInitialized, "Sender was not initialized");
338
306
  return;
339
307
  }
340
308
 
341
309
  // check if this item should be sampled in, else add sampleRate tag
342
310
  if (!_isSampledIn(telemetryItem)) {
343
311
  // Item is sampled out, do not send it
344
- itemCtx.diagLog().throwInternal(LoggingSeverity.WARNING, _InternalMessageId.TelemetrySampledAndNotSent,
312
+ _throwInternal(itemCtx.diagLog(), LoggingSeverity.WARNING, _InternalMessageId.TelemetrySampledAndNotSent,
345
313
  "Telemetry item was sampled out and not sent", { SampleRate: _self._sample.sampleRate });
346
314
  return;
347
315
  } else {
@@ -354,7 +322,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
354
322
  let defaultEnvelopeIkey = telemetryItem.iKey || _self._senderConfig.instrumentationKey();
355
323
  let aiEnvelope = Sender.constructEnvelope(telemetryItem, defaultEnvelopeIkey, itemCtx.diagLog(), convertUndefined);
356
324
  if (!aiEnvelope) {
357
- itemCtx.diagLog().throwInternal(LoggingSeverity.CRITICAL, _InternalMessageId.CreateEnvelopeError, "Unable to create an AppInsights envelope");
325
+ _throwInternal(itemCtx.diagLog(), LoggingSeverity.CRITICAL, _InternalMessageId.CreateEnvelopeError, "Unable to create an AppInsights envelope");
358
326
  return;
359
327
  }
360
328
 
@@ -370,7 +338,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
370
338
  } catch (e) {
371
339
  // log error but dont stop executing rest of the telemetry initializers
372
340
  // doNotSendItem = true;
373
- itemCtx.diagLog().throwInternal(
341
+ _throwInternal(itemCtx.diagLog(),
374
342
  LoggingSeverity.CRITICAL, _InternalMessageId.TelemetryInitializerFailed, "One of telemetry initializers failed, telemetry item will not be sent: " + getExceptionName(e),
375
343
  { exception: dumpObj(e) }, true);
376
344
  }
@@ -400,7 +368,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
400
368
  _setupTimer();
401
369
 
402
370
  } catch (e) {
403
- itemCtx.diagLog().throwInternal(
371
+ _throwInternal(itemCtx.diagLog(),
404
372
  LoggingSeverity.WARNING,
405
373
  _InternalMessageId.FailedAddingTelemetryToBuffer,
406
374
  "Failed adding telemetry to the sender's buffer, some telemetry will be lost: " + getExceptionName(e),
@@ -457,7 +425,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
457
425
  /* Ignore this error for IE under v10 */
458
426
  let ieVer = getIEVersion();
459
427
  if (!ieVer || ieVer > 9) {
460
- _self.diagLog().throwInternal(
428
+ _throwInternal(_self.diagLog(),
461
429
  LoggingSeverity.CRITICAL,
462
430
  _InternalMessageId.TransmissionFailed,
463
431
  "Telemetry transmission failed, some telemetry will be lost: " + getExceptionName(e),
@@ -467,11 +435,17 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
467
435
  }
468
436
  };
469
437
 
438
+ _self._doTeardown = (unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState) => {
439
+ _self.onunloadFlush();
440
+ _offlineListener.unload();
441
+ _initDefaults();
442
+ };
443
+
470
444
  /**
471
445
  * error handler
472
446
  */
473
447
  _self._onError = (payload: string[], message: string, event?: ErrorEvent) => {
474
- _self.diagLog().throwInternal(
448
+ _throwInternal(_self.diagLog(),
475
449
  LoggingSeverity.WARNING,
476
450
  _InternalMessageId.OnError,
477
451
  "Failed to send telemetry.",
@@ -510,7 +484,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
510
484
  if (retry.length > 0) {
511
485
  _resendPayload(retry);
512
486
 
513
- _self.diagLog().throwInternal(
487
+ _throwInternal(_self.diagLog(),
514
488
  LoggingSeverity.WARNING,
515
489
  _InternalMessageId.TransmissionFailed, "Partial success. " +
516
490
  "Delivered: " + payload.length + ", Failed: " + failed.length +
@@ -572,22 +546,22 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
572
546
 
573
547
  if (!_self._senderConfig.isRetryDisabled() && _isRetriable(status)) {
574
548
  _resendPayload(payload);
575
- _self.diagLog().throwInternal(
549
+ _throwInternal(_self.diagLog(),
576
550
  LoggingSeverity.WARNING,
577
551
  _InternalMessageId.TransmissionFailed, ". " +
578
552
  "Response code " + status + ". Will retry to send " + payload.length + " items.");
579
553
  } else {
580
554
  _self._onError(payload, errorMessage);
581
555
  }
582
- } else if (Offline.isOffline()) { // offline
556
+ } else if (_offlineListener && !_offlineListener.isOnline()) { // offline
583
557
  // Note: Don't check for status == 0, since adblock gives this code
584
558
  if (!_self._senderConfig.isRetryDisabled()) {
585
559
  const offlineBackOffMultiplier = 10; // arbritrary number
586
560
  _resendPayload(payload, offlineBackOffMultiplier);
587
561
 
588
- _self.diagLog().throwInternal(
562
+ _throwInternal(_self.diagLog(),
589
563
  LoggingSeverity.WARNING,
590
- _InternalMessageId.TransmissionFailed, `. Offline - Response Code: ${status}. Offline status: ${Offline.isOffline()}. Will retry to send ${payload.length} items.`);
564
+ _InternalMessageId.TransmissionFailed, `. Offline - Response Code: ${status}. Offline status: ${!_offlineListener.isOnline()}. Will retry to send ${payload.length} items.`);
591
565
  }
592
566
  } else {
593
567
 
@@ -682,8 +656,8 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
682
656
  }
683
657
 
684
658
  if (droppedPayload.length > 0) {
685
- _fallbackSender(droppedPayload, true);
686
- _self.diagLog().throwInternal(LoggingSeverity.WARNING, _InternalMessageId.TransmissionFailed, ". " + "Failed to send telemetry with Beacon API, retried with normal sender.");
659
+ _fallbackSender && _fallbackSender(droppedPayload, true);
660
+ _throwInternal(_self.diagLog(),LoggingSeverity.WARNING, _InternalMessageId.TransmissionFailed, ". " + "Failed to send telemetry with Beacon API, retried with normal sender.");
687
661
  }
688
662
  }
689
663
  }
@@ -740,7 +714,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
740
714
  } else {
741
715
  // Payload is going to be too big so just try and send via XHR
742
716
  _fallbackSender && _fallbackSender(payload, true);
743
- _self.diagLog().throwInternal(LoggingSeverity.WARNING, _InternalMessageId.TransmissionFailed, ". " + "Failed to send telemetry with Beacon API, retried with xhrSender.");
717
+ _throwInternal(_self.diagLog(),LoggingSeverity.WARNING, _InternalMessageId.TransmissionFailed, ". " + "Failed to send telemetry with Beacon API, retried with xhrSender.");
744
718
  }
745
719
  }
746
720
  }
@@ -865,7 +839,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
865
839
  }
866
840
  }
867
841
  } catch (e) {
868
- _self.diagLog().throwInternal(
842
+ _throwInternal(_self.diagLog(),
869
843
  LoggingSeverity.CRITICAL,
870
844
  _InternalMessageId.InvalidBackendResponse,
871
845
  "Cannot parse the response. " + getExceptionName(e),
@@ -985,7 +959,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
985
959
  // If the protocol doesn't match, we can't send the telemetry :(.
986
960
  const hostingProtocol = _window && _window.location && _window.location.protocol || "";
987
961
  if (_self._senderConfig.endpointUrl().lastIndexOf(hostingProtocol, 0) !== 0) {
988
- _self.diagLog().throwInternal(
962
+ _throwInternal(_self.diagLog(),
989
963
  LoggingSeverity.WARNING,
990
964
  _InternalMessageId.TransmissionFailed, ". " +
991
965
  "Cannot send XDomain request. The endpoint URL protocol doesn't match the hosting page protocol.");
@@ -1029,7 +1003,7 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
1029
1003
  try {
1030
1004
  manager.eventsSendRequest(sendRequest, isAsync);
1031
1005
  } catch (e) {
1032
- _self.diagLog().throwInternal(LoggingSeverity.CRITICAL,
1006
+ _throwInternal(_self.diagLog(),LoggingSeverity.CRITICAL,
1033
1007
  _InternalMessageId.NotificationException,
1034
1008
  "send request notification failed: " + getExceptionName(e),
1035
1009
  { exception: dumpObj(e) });
@@ -1051,6 +1025,25 @@ export class Sender extends BaseTelemetryPlugin implements IChannelControlsAI {
1051
1025
  return regexp.test(config.instrumentationKey);
1052
1026
  }
1053
1027
 
1028
+ function _initDefaults() {
1029
+ _self._sender = null;
1030
+ _self._buffer = null;
1031
+ _self._appId = null;
1032
+ _self._sample = null;
1033
+ _headers = {};
1034
+ _offlineListener = null;
1035
+ _consecutiveErrors = 0;
1036
+ _retryAt = null;
1037
+ _lastSend = null;
1038
+ _paused = false;
1039
+ _timeoutHandle = null;
1040
+ _serializer = null;
1041
+ _stamp_specific_redirects = 0;
1042
+ _syncFetchPayload = 0;
1043
+ _fallbackSender = null;
1044
+ _syncUnloadSender = null;
1045
+ _evtNamespace = null;
1046
+ }
1054
1047
  });
1055
1048
  }
1056
1049
 
@@ -1,13 +1,10 @@
1
+ export interface IOfflineListener {
2
+ isOnline: () => boolean;
3
+ isListening: () => boolean;
4
+ unload: () => void;
5
+ }
1
6
  /**
2
- * @description Monitors browser for offline events
3
- * @export default - Offline: Static instance of OfflineListener
4
- * @class OfflineListener
7
+ * Create a new OfflineListener instance to monitor browser online / offline events
8
+ * @param parentEvtNamespace - The parent event namespace to append to any specific events for this instance
5
9
  */
6
- export declare class OfflineListener {
7
- static Offline: OfflineListener;
8
- isListening: boolean;
9
- constructor();
10
- isOnline(): boolean;
11
- isOffline(): boolean;
12
- }
13
- export declare const Offline: OfflineListener;
10
+ export declare function createOfflineListener(parentEvtNamespace?: string | string[]): IOfflineListener;