@microsoft/applicationinsights-core-js 2.8.0-beta.2202-06 → 2.8.0-beta.2203-02

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 (122) hide show
  1. package/browser/applicationinsights-core-js.integrity.json +9 -9
  2. package/browser/applicationinsights-core-js.js +945 -479
  3. package/browser/applicationinsights-core-js.js.map +1 -1
  4. package/browser/applicationinsights-core-js.min.js +2 -2
  5. package/browser/applicationinsights-core-js.min.js.map +1 -1
  6. package/dist/applicationinsights-core-js.api.json +3904 -877
  7. package/dist/applicationinsights-core-js.api.md +264 -30
  8. package/dist/applicationinsights-core-js.d.ts +410 -89
  9. package/dist/applicationinsights-core-js.js +945 -479
  10. package/dist/applicationinsights-core-js.js.map +1 -1
  11. package/dist/applicationinsights-core-js.min.js +2 -2
  12. package/dist/applicationinsights-core-js.min.js.map +1 -1
  13. package/dist/applicationinsights-core-js.rollup.d.ts +410 -89
  14. package/dist-esm/JavaScriptSDK/AppInsightsCore.js +1 -1
  15. package/dist-esm/JavaScriptSDK/BaseCore.js +66 -23
  16. package/dist-esm/JavaScriptSDK/BaseCore.js.map +1 -1
  17. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js +44 -5
  18. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js.map +1 -1
  19. package/dist-esm/JavaScriptSDK/ChannelController.js +105 -73
  20. package/dist-esm/JavaScriptSDK/ChannelController.js.map +1 -1
  21. package/dist-esm/JavaScriptSDK/Constants.js +1 -1
  22. package/dist-esm/JavaScriptSDK/CookieMgr.js +3 -4
  23. package/dist-esm/JavaScriptSDK/CookieMgr.js.map +1 -1
  24. package/dist-esm/JavaScriptSDK/CoreUtils.js +6 -122
  25. package/dist-esm/JavaScriptSDK/CoreUtils.js.map +1 -1
  26. package/dist-esm/JavaScriptSDK/DataCacheHelper.js +93 -0
  27. package/dist-esm/JavaScriptSDK/DataCacheHelper.js.map +1 -0
  28. package/dist-esm/JavaScriptSDK/DbgExtensionUtils.js +1 -1
  29. package/dist-esm/JavaScriptSDK/DiagnosticLogger.js +12 -12
  30. package/dist-esm/JavaScriptSDK/DiagnosticLogger.js.map +1 -1
  31. package/dist-esm/JavaScriptSDK/EnvUtils.js +8 -7
  32. package/dist-esm/JavaScriptSDK/EnvUtils.js.map +1 -1
  33. package/dist-esm/JavaScriptSDK/EventHelpers.js +472 -0
  34. package/dist-esm/JavaScriptSDK/EventHelpers.js.map +1 -0
  35. package/dist-esm/JavaScriptSDK/HelperFuncs.js +32 -59
  36. package/dist-esm/JavaScriptSDK/HelperFuncs.js.map +1 -1
  37. package/dist-esm/JavaScriptSDK/InstrumentHooks.js +1 -1
  38. package/dist-esm/JavaScriptSDK/InternalConstants.js +28 -0
  39. package/dist-esm/JavaScriptSDK/InternalConstants.js.map +1 -0
  40. package/dist-esm/JavaScriptSDK/NotificationManager.js +8 -11
  41. package/dist-esm/JavaScriptSDK/NotificationManager.js.map +1 -1
  42. package/dist-esm/JavaScriptSDK/PerfManager.js +1 -1
  43. package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js +184 -110
  44. package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js.map +1 -1
  45. package/dist-esm/JavaScriptSDK/RandomHelper.js +3 -2
  46. package/dist-esm/JavaScriptSDK/RandomHelper.js.map +1 -1
  47. package/dist-esm/JavaScriptSDK/TelemetryHelpers.js +32 -13
  48. package/dist-esm/JavaScriptSDK/TelemetryHelpers.js.map +1 -1
  49. package/dist-esm/JavaScriptSDK/TelemetryInitializerPlugin.js +4 -6
  50. package/dist-esm/JavaScriptSDK/TelemetryInitializerPlugin.js.map +1 -1
  51. package/dist-esm/JavaScriptSDK.Enums/EventsDiscardedReason.js +1 -1
  52. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js +90 -96
  53. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js.map +1 -1
  54. package/dist-esm/JavaScriptSDK.Enums/SendRequestReason.js +1 -1
  55. package/dist-esm/JavaScriptSDK.Enums/TelemetryUnloadReason.js +8 -0
  56. package/dist-esm/JavaScriptSDK.Enums/TelemetryUnloadReason.js.map +1 -0
  57. package/dist-esm/JavaScriptSDK.Interfaces/IAppInsightsCore.js +1 -1
  58. package/dist-esm/JavaScriptSDK.Interfaces/IChannelControls.js +1 -1
  59. package/dist-esm/JavaScriptSDK.Interfaces/IConfiguration.js +1 -1
  60. package/dist-esm/JavaScriptSDK.Interfaces/ICookieMgr.js +1 -1
  61. package/dist-esm/JavaScriptSDK.Interfaces/IDbgExtension.js +1 -1
  62. package/dist-esm/JavaScriptSDK.Interfaces/IDiagnosticLogger.js +1 -1
  63. package/dist-esm/JavaScriptSDK.Interfaces/IInstrumentHooks.js +1 -1
  64. package/dist-esm/JavaScriptSDK.Interfaces/INotificationListener.js +1 -1
  65. package/dist-esm/JavaScriptSDK.Interfaces/INotificationManager.js +1 -1
  66. package/dist-esm/JavaScriptSDK.Interfaces/IPerfEvent.js +1 -1
  67. package/dist-esm/JavaScriptSDK.Interfaces/IPerfManager.js +1 -1
  68. package/dist-esm/JavaScriptSDK.Interfaces/IProcessTelemetryContext.js +1 -1
  69. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryInitializers.js +1 -1
  70. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryItem.js +1 -1
  71. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPlugin.js +1 -1
  72. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js +1 -2
  73. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js.map +1 -1
  74. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUnloadState.js +8 -0
  75. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUnloadState.js.map +1 -0
  76. package/dist-esm/applicationinsights-core-js.js +8 -4
  77. package/dist-esm/applicationinsights-core-js.js.map +1 -1
  78. package/package.json +1 -1
  79. package/src/JavaScriptSDK/BaseCore.ts +80 -24
  80. package/src/JavaScriptSDK/BaseTelemetryPlugin.ts +76 -5
  81. package/src/JavaScriptSDK/ChannelController.ts +107 -61
  82. package/src/JavaScriptSDK/CookieMgr.ts +4 -4
  83. package/src/JavaScriptSDK/CoreUtils.ts +6 -143
  84. package/src/JavaScriptSDK/DataCacheHelper.ts +106 -0
  85. package/src/JavaScriptSDK/DiagnosticLogger.ts +12 -11
  86. package/src/JavaScriptSDK/EnvUtils.ts +7 -6
  87. package/src/JavaScriptSDK/EventHelpers.ts +542 -0
  88. package/src/JavaScriptSDK/HelperFuncs.ts +35 -54
  89. package/src/JavaScriptSDK/InternalConstants.ts +26 -0
  90. package/src/JavaScriptSDK/NotificationManager.ts +7 -11
  91. package/src/JavaScriptSDK/ProcessTelemetryContext.ts +237 -124
  92. package/src/JavaScriptSDK/RandomHelper.ts +2 -1
  93. package/src/JavaScriptSDK/TelemetryHelpers.ts +47 -15
  94. package/src/JavaScriptSDK/TelemetryInitializerPlugin.ts +5 -15
  95. package/src/JavaScriptSDK.Enums/LoggingEnums.ts +184 -87
  96. package/src/JavaScriptSDK.Enums/TelemetryUnloadReason.ts +27 -0
  97. package/src/JavaScriptSDK.Interfaces/IAppInsightsCore.ts +20 -0
  98. package/src/JavaScriptSDK.Interfaces/IChannelControls.ts +9 -2
  99. package/src/JavaScriptSDK.Interfaces/IProcessTelemetryContext.ts +55 -16
  100. package/src/JavaScriptSDK.Interfaces/ITelemetryPlugin.ts +16 -9
  101. package/src/JavaScriptSDK.Interfaces/ITelemetryPluginChain.ts +9 -11
  102. package/src/JavaScriptSDK.Interfaces/ITelemetryUnloadState.ts +10 -0
  103. package/types/JavaScriptSDK/BaseCore.d.ts +4 -0
  104. package/types/JavaScriptSDK/BaseTelemetryPlugin.d.ts +20 -1
  105. package/types/JavaScriptSDK/ChannelController.d.ts +4 -0
  106. package/types/JavaScriptSDK/CoreUtils.d.ts +1 -42
  107. package/types/JavaScriptSDK/DataCacheHelper.d.ts +13 -0
  108. package/types/JavaScriptSDK/EventHelpers.d.ts +152 -0
  109. package/types/JavaScriptSDK/HelperFuncs.d.ts +8 -17
  110. package/types/JavaScriptSDK/InternalConstants.d.ts +20 -0
  111. package/types/JavaScriptSDK/ProcessTelemetryContext.d.ts +10 -3
  112. package/types/JavaScriptSDK/TelemetryHelpers.d.ts +8 -0
  113. package/types/JavaScriptSDK/TelemetryInitializerPlugin.d.ts +0 -7
  114. package/types/JavaScriptSDK.Enums/LoggingEnums.d.ts +91 -2
  115. package/types/JavaScriptSDK.Enums/TelemetryUnloadReason.d.ts +9 -0
  116. package/types/JavaScriptSDK.Interfaces/IAppInsightsCore.d.ts +17 -0
  117. package/types/JavaScriptSDK.Interfaces/IChannelControls.d.ts +9 -2
  118. package/types/JavaScriptSDK.Interfaces/IProcessTelemetryContext.d.ts +49 -14
  119. package/types/JavaScriptSDK.Interfaces/ITelemetryPlugin.d.ts +15 -8
  120. package/types/JavaScriptSDK.Interfaces/ITelemetryPluginChain.d.ts +9 -10
  121. package/types/JavaScriptSDK.Interfaces/ITelemetryUnloadState.d.ts +6 -0
  122. package/types/applicationinsights-core-js.d.ts +6 -3
@@ -14,8 +14,8 @@ import { INotificationListener } from "../JavaScriptSDK.Interfaces/INotification
14
14
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
15
15
  import { IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
16
16
  import { createProcessTelemetryContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
17
- import { initializePlugins, sortPlugins } from "./TelemetryHelpers";
18
- import { LoggingSeverity } from "../JavaScriptSDK.Enums/LoggingEnums";
17
+ import { initializePlugins, sortPlugins, _getPluginState } from "./TelemetryHelpers";
18
+ import { eLoggingSeverity } from "../JavaScriptSDK.Enums/LoggingEnums";
19
19
  import { IPerfManager } from "../JavaScriptSDK.Interfaces/IPerfManager";
20
20
  import { getGblPerfMgr, PerfManager } from "./PerfManager";
21
21
  import { ICookieMgr } from "../JavaScriptSDK.Interfaces/ICookieMgr";
@@ -25,9 +25,11 @@ import { strExtensionConfig, strIKey } from "./Constants";
25
25
  import { DiagnosticLogger, _InternalLogMessage } from "./DiagnosticLogger";
26
26
  import { getDebugListener } from "./DbgExtensionUtils";
27
27
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
28
- import { ChannelControllerPriority, createChannelControllerPlugin, createChannelQueues, IChannelController, _IInternalChannels } from "./ChannelController";
28
+ import { ChannelControllerPriority, createChannelControllerPlugin, createChannelQueues, IChannelController, IInternalChannelController, _IInternalChannels } from "./ChannelController";
29
29
  import { ITelemetryInitializerHandler, TelemetryInitializerFunction } from "../JavaScriptSDK.Interfaces/ITelemetryInitializers";
30
30
  import { TelemetryInitializerPlugin } from "./TelemetryInitializerPlugin";
31
+ import { createUniqueNamespace } from "./DataCacheHelper";
32
+ import { strAddNotificationListener, strDisabled, strEventsDiscarded, strEventsSendRequest, strEventsSent, strRemoveNotificationListener, strTeardown } from "./InternalConstants";
31
33
 
32
34
  const strValidationError = "Plugins must provide initialize method";
33
35
  const strNotificationManager = "_notificationManager";
@@ -80,6 +82,16 @@ function _validateExtensions(logger: IDiagnosticLogger, channelPriority: number,
80
82
  };
81
83
  }
82
84
 
85
+ function _createDummyNotificationManager(): INotificationManager {
86
+ return objCreateFn({
87
+ [strAddNotificationListener]: (listener: INotificationListener) => { },
88
+ [strRemoveNotificationListener]: (listener: INotificationListener) => { },
89
+ [strEventsSent]: (events: ITelemetryItem[]) => { },
90
+ [strEventsDiscarded]: (events: ITelemetryItem[], reason: number) => { },
91
+ [strEventsSendRequest]: (sendReason: number, isAsync: boolean) => { }
92
+ });
93
+ }
94
+
83
95
  export class BaseCore implements IAppInsightsCore {
84
96
  public static defaultConfig: IConfiguration;
85
97
  public config: IConfiguration;
@@ -104,6 +116,7 @@ export class BaseCore implements IAppInsightsCore {
104
116
  let _channelQueue: _IInternalChannels[];
105
117
  let _telemetryInitializerPlugin: TelemetryInitializerPlugin;
106
118
  let _internalLogsEventName: string;
119
+ let _evtNamespace: string;
107
120
  let _debugListener: INotificationListener;
108
121
 
109
122
  /**
@@ -183,27 +196,19 @@ export class BaseCore implements IAppInsightsCore {
183
196
 
184
197
  if (_self.isInitialized()) {
185
198
  // Process the telemetry plugin chain
186
- _self.getProcessTelContext().processNext(telemetryItem);
199
+ _createTelCtx().processNext(telemetryItem);
187
200
  } else {
188
201
  // Queue events until all extensions are initialized
189
202
  _eventQueue.push(telemetryItem);
190
203
  }
191
204
  };
192
205
 
193
- _self.getProcessTelContext = (): IProcessTelemetryContext => {
194
- return createProcessTelemetryContext(_getPluginChain(), _self.config, _self);
195
- };
206
+ _self.getProcessTelContext = _createTelCtx;
196
207
 
197
208
  _self.getNotifyMgr = (): INotificationManager => {
198
209
  if (!_notificationManager) {
199
210
  // Create Dummy notification manager
200
- _notificationManager = objCreateFn({
201
- addNotificationListener: (listener: INotificationListener) => { },
202
- removeNotificationListener: (listener: INotificationListener) => { },
203
- eventsSent: (events: ITelemetryItem[]) => { },
204
- eventsDiscarded: (events: ITelemetryItem[], reason: number) => { },
205
- eventsSendRequest: (sendReason: number, isAsync: boolean) => { }
206
- });
211
+ _notificationManager = _createDummyNotificationManager();
207
212
 
208
213
  // For backward compatibility only
209
214
  _self[strNotificationManager] = _notificationManager;
@@ -270,7 +275,7 @@ export class BaseCore implements IAppInsightsCore {
270
275
  _eventQueue = [];
271
276
 
272
277
  arrForEach(eventQueue, (event: ITelemetryItem) => {
273
- _self.getProcessTelContext().processNext(event);
278
+ _createTelCtx().processNext(event);
274
279
  });
275
280
  }
276
281
  };
@@ -311,11 +316,15 @@ export class BaseCore implements IAppInsightsCore {
311
316
 
312
317
  _self.getPlugin = _getPlugin;
313
318
 
319
+ _self.evtNamespace = (): string => {
320
+ return _evtNamespace;
321
+ };
322
+
314
323
  function _initDefaults() {
315
324
  _isInitialized = false;
316
325
 
317
326
  // Use a default logger so initialization errors are not dropped on the floor with full logging
318
- _self.logger = new DiagnosticLogger({ loggingLevelConsole: LoggingSeverity.CRITICAL });
327
+ _self.logger = new DiagnosticLogger({ loggingLevelConsole: eLoggingSeverity.CRITICAL });
319
328
  _self.config = null;
320
329
  _self._extensions = [];
321
330
 
@@ -332,6 +341,11 @@ export class BaseCore implements IAppInsightsCore {
332
341
  _channelConfig = null;
333
342
  _channelQueue = null;
334
343
  _internalLogsEventName = null;
344
+ _evtNamespace = createUniqueNamespace("AIBaseCore", true);
345
+ }
346
+
347
+ function _createTelCtx(): IProcessTelemetryContext {
348
+ return createProcessTelemetryContext(_getPluginChain(), _self.config, _self);
335
349
  }
336
350
 
337
351
  // Initialize or Re-initialize the plugins
@@ -347,7 +361,25 @@ export class BaseCore implements IAppInsightsCore {
347
361
 
348
362
  // Initialize the Channel Queues and the channel plugins first
349
363
  _channelQueue = objFreeze(createChannelQueues(_channelConfig, allExtensions, config, _self));
350
- _channelControl = createChannelControllerPlugin(_channelQueue, _self);
364
+ if (_channelControl) {
365
+ // During add / remove of a plugin this may get called again, so don't re-add if already present
366
+ // But we also want the controller as the last, so remove if already present
367
+ // And reusing the existing instance, just in case an installed plugin has a reference and
368
+ // is using it.
369
+ let idx = allExtensions.indexOf(_channelControl);
370
+ if (idx !== -1) {
371
+ allExtensions.splice(idx, 1);
372
+ }
373
+
374
+ idx = _coreExtensions.indexOf(_channelControl);
375
+ if (idx !== -1) {
376
+ _coreExtensions.splice(idx, 1);
377
+ }
378
+
379
+ (_channelControl as IInternalChannelController)._setQueue(_channelQueue);
380
+ } else {
381
+ _channelControl = createChannelControllerPlugin(_channelQueue, _self);
382
+ }
351
383
 
352
384
  // Add on "channelController" as the last "plugin"
353
385
  allExtensions.push(_channelControl);
@@ -359,7 +391,7 @@ export class BaseCore implements IAppInsightsCore {
359
391
  // Initialize the controls
360
392
  _channelControl.initialize(config, _self, allExtensions);
361
393
 
362
- initializePlugins(_self.getProcessTelContext(), allExtensions);
394
+ initializePlugins(_createTelCtx(), allExtensions);
363
395
 
364
396
  // Now reset the extensions to just those being managed by Basecore
365
397
  _self._extensions = objFreeze(sortPlugins(_coreExtensions || [])).slice();
@@ -370,15 +402,27 @@ export class BaseCore implements IAppInsightsCore {
370
402
  let thePlugin: IPlugin = null;
371
403
 
372
404
  arrForEach(_self._extensions, (ext: any) => {
373
- if (ext.identifier === pluginIdentifier) {
405
+ if (ext.identifier === pluginIdentifier && ext !== _channelControl && ext !== _telemetryInitializerPlugin) {
374
406
  thePlugin = ext;
375
407
  return -1;
376
408
  }
377
409
  });
378
410
 
411
+ if (!thePlugin && _channelControl) {
412
+ // Check the channel Controller
413
+ thePlugin = _channelControl.getChannel(pluginIdentifier);
414
+ }
415
+
379
416
  if (thePlugin) {
380
417
  theExt = {
381
- plugin: thePlugin as T
418
+ plugin: thePlugin as T,
419
+ setEnabled: (enabled: boolean) => {
420
+ _getPluginState(thePlugin)[strDisabled] = !enabled;
421
+ },
422
+ isEnabled: () => {
423
+ let pluginState = _getPluginState(thePlugin);
424
+ return !pluginState[strTeardown] && !pluginState[strDisabled];
425
+ }
382
426
  }
383
427
  }
384
428
 
@@ -389,8 +433,11 @@ export class BaseCore implements IAppInsightsCore {
389
433
  if (!_pluginChain) {
390
434
  // copy the collection of extensions
391
435
  let extensions = (_coreExtensions || []).slice();
392
-
393
- extensions.push(_telemetryInitializerPlugin);
436
+
437
+ // During add / remove this may get called again, so don't readd if already present
438
+ if (extensions.indexOf(_telemetryInitializerPlugin) === -1) {
439
+ extensions.push(_telemetryInitializerPlugin);
440
+ }
394
441
 
395
442
  _pluginChain = createTelemetryProxyChain(sortPlugins(extensions), _self.config, _self);
396
443
  }
@@ -420,13 +467,13 @@ export class BaseCore implements IAppInsightsCore {
420
467
 
421
468
  if (config.disableDbgExt === true && _debugListener) {
422
469
  // Remove any previously loaded debug listener
423
- _notificationManager.removeNotificationListener(_debugListener);
470
+ _notificationManager[strRemoveNotificationListener](_debugListener);
424
471
  _debugListener = null;
425
472
  }
426
473
 
427
474
  if (_notificationManager && !_debugListener && config.disableDbgExt !== true) {
428
475
  _debugListener = getDebugListener(config);
429
- _notificationManager.addNotificationListener(_debugListener);
476
+ _notificationManager[strAddNotificationListener](_debugListener);
430
477
  }
431
478
  }
432
479
 
@@ -543,6 +590,15 @@ export class BaseCore implements IAppInsightsCore {
543
590
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
544
591
  return null;
545
592
  }
593
+
594
+ /**
595
+ * Returns the unique event namespace that should be used
596
+ */
597
+ public evtNamespace(): string {
598
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
599
+ return null;
600
+ }
601
+
546
602
  protected releaseQueue() {
547
603
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
548
604
  }
@@ -9,12 +9,15 @@ import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
9
9
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
10
10
  import { IPlugin, ITelemetryPlugin } from "../JavaScriptSDK.Interfaces/ITelemetryPlugin";
11
11
  import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
12
- import { IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
12
+ import { IProcessTelemetryContext, IProcessTelemetryUnloadContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
13
13
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
14
- import { createProcessTelemetryContext } from "./ProcessTelemetryContext";
15
- import { isArray, isFunction, isNullOrUndefined, setValue } from "./HelperFuncs";
14
+ import { createProcessTelemetryContext, createProcessTelemetryUnloadContext } from "./ProcessTelemetryContext";
15
+ import { arrForEach, isArray, isFunction, isNullOrUndefined, setValue } from "./HelperFuncs";
16
16
  import { strExtensionConfig } from "./Constants";
17
17
  import { IInstrumentHook } from "../JavaScriptSDK.Interfaces/IInstrumentHooks";
18
+ import { ITelemetryUnloadState } from "../JavaScriptSDK.Interfaces/ITelemetryUnloadState";
19
+ import { TelemetryUnloadReason } from "../JavaScriptSDK.Enums/TelemetryUnloadReason";
20
+ import { strDoTeardown, strIsInitialized, strSetNextPlugin } from "./InternalConstants";
18
21
 
19
22
  let strGetPlugin = "getPlugin";
20
23
 
@@ -73,6 +76,16 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
73
76
  */
74
77
  protected setInitialized: (isInitialized: boolean) => void;
75
78
 
79
+ /**
80
+ * Teardown / Unload hook to allow implementations to perform some additional unload operations before the BaseTelemetryPlugin
81
+ * finishes it's removal.
82
+ * @param unloadCtx - This is the context that should be used during unloading.
83
+ * @param unloadState - The details / state of the unload process, it holds details like whether it should be unloaded synchronously or asynchronously and the reason for the unload.
84
+ * @param asyncCallback - An optional callback that the plugin must call if it returns true to inform the caller that it has completed any async unload/teardown operations.
85
+ * @returns boolean - true if the plugin has or will call asyncCallback, this allows the plugin to perform any asynchronous operations.
86
+ */
87
+ protected _doTeardown?: (unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState, asyncCallback?: () => void) => void | boolean;
88
+
76
89
  constructor() {
77
90
  let _self = this; // Setting _self here as it's used outside of the dynamicProto as well
78
91
 
@@ -90,6 +103,51 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
90
103
  _setDefaults(config, core, pluginChain);
91
104
  _isinitialized = true;
92
105
  }
106
+
107
+ _self.teardown = (unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState) => {
108
+ // If this plugin has already been torn down (not operational) or is not initialized (core is not set)
109
+ // or the core being used for unload was not the same core used for initialization.
110
+ if (!_self.core || (unloadCtx && _self.core !== unloadCtx.core())) {
111
+ // Do Nothing
112
+ return;
113
+ }
114
+
115
+ let result: void | boolean;
116
+ let unloadDone = false;
117
+ let theUnloadCtx = unloadCtx || createProcessTelemetryUnloadContext(null, {}, _self.core, _nextPlugin && _nextPlugin[strGetPlugin] ? _nextPlugin[strGetPlugin]() : _nextPlugin);
118
+ let theUnloadState: ITelemetryUnloadState = unloadState || {
119
+ reason: TelemetryUnloadReason.ManualTeardown,
120
+ isAsync: false
121
+ };
122
+
123
+
124
+ function _unloadCallback() {
125
+ if (!unloadDone) {
126
+ unloadDone = true;
127
+
128
+ // Remove all instrumentation hooks
129
+ arrForEach(_hooks, (fn) => {
130
+ fn.rm();
131
+ });
132
+ _hooks = [];
133
+
134
+ if (result === true) {
135
+ theUnloadCtx.processNext(theUnloadState);
136
+ }
137
+
138
+ _initDefaults();
139
+ }
140
+ }
141
+
142
+ if (!_self[strDoTeardown] || _self[strDoTeardown](theUnloadCtx, theUnloadState, _unloadCallback) !== true) {
143
+ _unloadCallback();
144
+ } else {
145
+ // Tell the caller that we will be calling processNext()
146
+ result = true;
147
+ }
148
+
149
+ return result;
150
+ };
93
151
 
94
152
  _self._addHook = (hooks: IInstrumentHook | IInstrumentHook[]) => {
95
153
  if (hooks) {
@@ -108,7 +166,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
108
166
  return _getTelCtx(itemCtx).diagLog();
109
167
  }
110
168
 
111
- _self.isInitialized = () => {
169
+ _self[strIsInitialized] = () => {
112
170
  return _isinitialized;
113
171
  }
114
172
 
@@ -121,7 +179,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
121
179
  // should use processNext() function. If you require access to the plugin use the
122
180
  // IProcessTelemetryContext.getNext().getPlugin() while in the pipeline, Note getNext() may return null.
123
181
 
124
- _self.setNextPlugin = (next: ITelemetryPlugin | ITelemetryPluginChain) => {
182
+ _self[strSetNextPlugin] = (next: ITelemetryPlugin | ITelemetryPluginChain) => {
125
183
  _nextPlugin = next;
126
184
  };
127
185
 
@@ -189,6 +247,19 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
189
247
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
190
248
  }
191
249
 
250
+ /**
251
+ * Tear down the plugin and remove any hooked value, the plugin should be removed so that it is no longer initialized and
252
+ * therefore could be re-initialized after being torn down. The plugin should ensure that once this has been called any further
253
+ * processTelemetry calls are ignored and it just calls the processNext() with the provided context.
254
+ * @param unloadCtx - This is the context that should be used during unloading.
255
+ * @param unloadState - The details / state of the unload process, it holds details like whether it should be unloaded synchronously or asynchronously and the reason for the unload.
256
+ * @returns boolean - true if the plugin has or will call processNext(), this for backward compatibility as previously teardown was synchronous and returned nothing.
257
+ */
258
+ public teardown(unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState): void | boolean {
259
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
260
+ return false;
261
+ }
262
+
192
263
  public abstract processTelemetry(env: ITelemetryItem, itemCtx?: IProcessTelemetryContext): void;
193
264
 
194
265
  /**
@@ -2,14 +2,17 @@
2
2
  // // Licensed under the MIT License.
3
3
 
4
4
  import { SendRequestReason } from "../JavaScriptSDK.Enums/SendRequestReason";
5
+ import { TelemetryUnloadReason } from "../JavaScriptSDK.Enums/TelemetryUnloadReason";
5
6
  import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore";
6
7
  import { IChannelControls } from "../JavaScriptSDK.Interfaces/IChannelControls";
7
8
  import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
8
- import { IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
9
+ import { IBaseProcessingContext, IProcessTelemetryContext, IProcessTelemetryUnloadContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
9
10
  import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
10
11
  import { IPlugin } from "../JavaScriptSDK.Interfaces/ITelemetryPlugin";
11
12
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
13
+ import { ITelemetryUnloadState } from "../JavaScriptSDK.Interfaces/ITelemetryUnloadState";
12
14
  import { arrForEach, isArray, objFreeze, throwError } from "./HelperFuncs";
15
+ import { strPause, strProcessNext, strResume, strTeardown } from "./InternalConstants";
13
16
  import { createProcessTelemetryContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
14
17
  import { initializePlugins } from "./TelemetryHelpers";
15
18
 
@@ -17,7 +20,13 @@ export const ChannelControllerPriority = 500;
17
20
  const ChannelValidationMessage = "Channel has invalid priority - ";
18
21
 
19
22
  export interface IChannelController extends IChannelControls {
20
- flush(isAsync: boolean, callBack: (flushComplete?: boolean) => void, sendReason: SendRequestReason, cbTimeout?: number): void
23
+ flush(isAsync: boolean, callBack: (flushComplete?: boolean) => void, sendReason: SendRequestReason, cbTimeout?: number): void;
24
+
25
+ getChannel<T extends IPlugin = IPlugin>(pluginIdentifier: string): T;
26
+ }
27
+
28
+ export interface IInternalChannelController extends IChannelController {
29
+ _setQueue: (channels: _IInternalChannels[]) => void;
21
30
  }
22
31
 
23
32
  export interface _IInternalChannels {
@@ -46,31 +55,29 @@ function _addChannelQueue(channelQueue: _IInternalChannels[], queue: IChannelCon
46
55
 
47
56
  export function createChannelControllerPlugin(channelQueue: _IInternalChannels[], core: IAppInsightsCore): IChannelController {
48
57
 
49
- function _getTelCtx(itemCtx: IProcessTelemetryContext) {
50
- if (!itemCtx) {
51
- // For some reason the previous plugin didn't pass down the itemCtx (perhaps an old plugin)
52
- itemCtx = createProcessTelemetryContext(null, core.config, core, null)
53
- }
54
-
55
- return itemCtx;
58
+ function _getTelCtx() {
59
+ return createProcessTelemetryContext(null, core.config, core, null)
56
60
  }
57
61
 
58
- function _processChannelQueue(itemCtx: IProcessTelemetryContext, processFn: (chainCtx: IProcessTelemetryContext) => void, onComplete?: () => void) {
59
- if (channelQueue && channelQueue.length > 0) {
60
- let waiting = channelQueue.length;
61
- arrForEach(channelQueue, (channels) => {
62
+ function _processChannelQueue<T extends IBaseProcessingContext>(theChannels: _IInternalChannels[], itemCtx: T, processFn: (chainCtx: T) => void, onComplete: () => void) {
63
+ let waiting = theChannels ? (theChannels.length + 1) : 1;
64
+
65
+ function _runChainOnComplete() {
66
+ waiting --;
67
+
68
+ if (waiting === 0) {
69
+ onComplete && onComplete();
70
+ onComplete = null;
71
+ }
72
+ }
73
+
74
+ if (waiting > 0) {
75
+ arrForEach(theChannels, (channels) => {
62
76
  // pass on to first item in queue
63
77
  if (channels && channels.queue.length > 0) {
64
78
  let channelChain = channels.chain;
65
- let chainCtx = _getTelCtx(itemCtx).createNew(channelChain);
66
- chainCtx.onComplete(() => {
67
- waiting --;
68
-
69
- if (waiting === 0) {
70
- onComplete && onComplete();
71
- onComplete = null;
72
- }
73
- });
79
+ let chainCtx = itemCtx.createNew(channelChain) as T;
80
+ chainCtx.onComplete(_runChainOnComplete);
74
81
 
75
82
  // Cause this chain to start processing
76
83
  processFn(chainCtx);
@@ -78,17 +85,55 @@ export function createChannelControllerPlugin(channelQueue: _IInternalChannels[]
78
85
  waiting --;
79
86
  }
80
87
  });
88
+ }
81
89
 
82
- if (waiting === 0) {
83
- onComplete && onComplete();
84
- }
85
- } else {
86
- onComplete && onComplete();
90
+ _runChainOnComplete();
91
+ }
92
+
93
+ function _doTeardown(unloadCtx: IProcessTelemetryUnloadContext, unloadState: ITelemetryUnloadState) {
94
+ let theUnloadState: ITelemetryUnloadState = unloadState || {
95
+ reason: TelemetryUnloadReason.ManualTeardown,
96
+ isAsync: false
97
+ };
98
+
99
+ _processChannelQueue(channelQueue, unloadCtx, (chainCtx: IProcessTelemetryUnloadContext) => {
100
+ chainCtx[strProcessNext](theUnloadState);
101
+ }, () => {
102
+ unloadCtx[strProcessNext](theUnloadState);
103
+ isInitialized = false;
104
+ });
105
+
106
+ return true;
107
+ }
108
+
109
+ function _getChannel<T extends IPlugin = IPlugin>(pluginIdentifier: string): T {
110
+ let thePlugin: T = null;
111
+
112
+ if (channelQueue && channelQueue.length > 0) {
113
+ arrForEach(channelQueue, (channels) => {
114
+ // pass on to first item in queue
115
+ if (channels && channels.queue.length > 0) {
116
+ arrForEach(channels.queue, (ext: any) => {
117
+ if (ext.identifier === pluginIdentifier) {
118
+ thePlugin = ext;
119
+ // Cause arrForEach to stop iterating
120
+ return -1;
121
+ }
122
+ });
123
+
124
+ if (thePlugin) {
125
+ // Cause arrForEach to stop iterating
126
+ return -1;
127
+ }
128
+ }
129
+ });
87
130
  }
131
+
132
+ return thePlugin;
88
133
  }
89
134
 
90
135
  let isInitialized = false;
91
- let channelController: IChannelController = {
136
+ let channelController: IInternalChannelController = {
92
137
  identifier: "ChannelControllerPlugin",
93
138
  priority: ChannelControllerPriority,
94
139
  initialize: (config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?: ITelemetryPluginChain) => {
@@ -101,41 +146,38 @@ export function createChannelControllerPlugin(channelQueue: _IInternalChannels[]
101
146
  },
102
147
  isInitialized: () => { return isInitialized },
103
148
  processTelemetry: (item: ITelemetryItem, itemCtx: IProcessTelemetryContext) => {
104
- _processChannelQueue(itemCtx, (chainCtx: IProcessTelemetryContext) => {
105
- chainCtx.processNext(item);
149
+ _processChannelQueue(channelQueue, itemCtx || _getTelCtx(), (chainCtx: IProcessTelemetryContext) => {
150
+ chainCtx[strProcessNext](item);
106
151
  }, () => {
107
- itemCtx.processNext(item);
108
- });
109
- },
110
- pause: () => {
111
- _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
112
- chainCtx.iterate<IChannelControls>((plugin) => {
113
- plugin.pause && plugin.pause();
114
- });
152
+ itemCtx[strProcessNext](item);
115
153
  });
116
154
  },
117
- resume: () => {
118
- _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
155
+ [strPause]: () => {
156
+ _processChannelQueue(channelQueue, _getTelCtx(), (chainCtx: IProcessTelemetryContext) => {
119
157
  chainCtx.iterate<IChannelControls>((plugin) => {
120
- plugin.resume && plugin.resume();
158
+ plugin[strPause] && plugin[strPause]();
121
159
  });
122
- });
160
+ }, null);
123
161
  },
124
- teardown: () => {
125
- _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
162
+ [strResume]: () => {
163
+ _processChannelQueue(channelQueue, _getTelCtx(), (chainCtx: IProcessTelemetryContext) => {
126
164
  chainCtx.iterate<IChannelControls>((plugin) => {
127
- plugin.teardown && plugin.teardown();
165
+ plugin[strResume] && plugin[strResume]();
128
166
  });
129
- });
167
+ }, null);
130
168
  },
169
+ [strTeardown]: _doTeardown,
170
+ getChannel: _getChannel,
131
171
  flush: (isAsync: boolean, callBack: (flushComplete?: boolean) => void, sendReason: SendRequestReason, cbTimeout?: number) => {
172
+ // Setting waiting to one so that we don't call the callBack until we finish iterating
173
+ let waiting = 1;
132
174
  let doneIterating = false;
133
- let waiting = 0;
134
175
  let cbTimer: any = null;
135
176
 
136
177
  cbTimeout = cbTimeout || 5000;
137
178
 
138
179
  function doCallback() {
180
+ waiting--;
139
181
  if (doneIterating && waiting === 0) {
140
182
  if (cbTimer) {
141
183
  clearTimeout(cbTimer);
@@ -147,36 +189,40 @@ export function createChannelControllerPlugin(channelQueue: _IInternalChannels[]
147
189
  }
148
190
  }
149
191
 
150
- // Setting waiting to one so that we don't call the callBack until we finish iterating
151
- waiting = 1;
152
- _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
192
+ _processChannelQueue(channelQueue, _getTelCtx(), (chainCtx: IProcessTelemetryContext) => {
153
193
  chainCtx.iterate<IChannelControls>((plugin) => {
154
194
  if (plugin.flush) {
155
195
  waiting ++;
156
196
 
197
+ let handled = false;
157
198
  // Not all channels will call this callback for every scenario
158
199
  if (!plugin.flush(isAsync, () => {
159
- waiting--;
200
+ handled = true;
160
201
  doCallback();
161
202
  }, sendReason)) {
162
- // If any channel doesn't return true we should assume that the callback will never be called, so use a timeout
163
- // to allow the channel some time to "finish" before triggering any followup function (such as unloading)
164
- if (cbTimer == null) {
165
- cbTimer = setTimeout(() => {
166
- cbTimer = null;
167
- callBack && callBack(false);
168
- // Make sure we don't call the callback more than once
169
- callBack = null;
170
- }, cbTimeout);
203
+ if (!handled) {
204
+ // If any channel doesn't return true and it didn't call the callback, then we should assume that the callback
205
+ // will never be called, so use a timeout to allow the channel(s) some time to "finish" before triggering any
206
+ // followup function (such as unloading)
207
+ if (isAsync && cbTimer == null) {
208
+ cbTimer = setTimeout(() => {
209
+ cbTimer = null;
210
+ doCallback();
211
+ }, cbTimeout);
212
+ } else {
213
+ doCallback();
214
+ }
171
215
  }
172
216
  }
173
217
  }
174
218
  });
175
219
  }, () => {
176
- waiting--;
177
220
  doneIterating = true;
178
221
  doCallback();
179
222
  });
223
+ },
224
+ _setQueue: (queue: _IInternalChannels[]) => {
225
+ channelQueue = queue;
180
226
  }
181
227
  };
182
228
 
@@ -2,7 +2,7 @@
2
2
  // Licensed under the MIT License.
3
3
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
4
4
  import { ICookieMgr, ICookieMgrConfig } from "../JavaScriptSDK.Interfaces/ICookieMgr";
5
- import { _InternalMessageId, LoggingSeverity } from "../JavaScriptSDK.Enums/LoggingEnums";
5
+ import { _eInternalMessageId, eLoggingSeverity } from "../JavaScriptSDK.Enums/LoggingEnums";
6
6
  import { dumpObj, getDocument, getLocation, getNavigator, isIE } from "./EnvUtils";
7
7
  import {
8
8
  arrForEach, dateNow, getExceptionName, isFunction, isNotNullOrUndefined, isNullOrUndefined, isString, isTruthy, isUndefined,
@@ -10,6 +10,7 @@ import {
10
10
  } from "./HelperFuncs";
11
11
  import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
12
12
  import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore";
13
+ import { strEmpty } from "./InternalConstants";
13
14
 
14
15
  const strToGMTString = "toGMTString";
15
16
  const strToUTCString = "toUTCString";
@@ -19,7 +20,6 @@ const strEnabled = "enabled";
19
20
  const strIsCookieUseDisabled = "isCookieUseDisabled";
20
21
  const strDisableCookiesUsage = "disableCookiesUsage";
21
22
  const strConfigCookieMgr = "_ckMgr";
22
- const strEmpty = "";
23
23
 
24
24
  let _supportsCookies: boolean = null;
25
25
  let _allowUaSameSite: boolean = null;
@@ -253,8 +253,8 @@ export function areCookiesSupported(logger?: IDiagnosticLogger): any {
253
253
  _supportsCookies = doc[strCookie] !== undefined;
254
254
  } catch (e) {
255
255
  logger && logger.throwInternal(
256
- LoggingSeverity.WARNING,
257
- _InternalMessageId.CannotAccessCookie,
256
+ eLoggingSeverity.WARNING,
257
+ _eInternalMessageId.CannotAccessCookie,
258
258
  "Cannot access document.cookie - " + getExceptionName(e),
259
259
  { exception: dumpObj(e) });
260
260
  }