@microsoft/applicationinsights-core-js 2.8.0-beta.2203-02 → 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.
Files changed (107) hide show
  1. package/browser/applicationinsights-core-js.integrity.json +9 -9
  2. package/browser/applicationinsights-core-js.js +319 -29
  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 +2458 -250
  7. package/dist/applicationinsights-core-js.api.md +87 -7
  8. package/dist/applicationinsights-core-js.d.ts +192 -7
  9. package/dist/applicationinsights-core-js.js +319 -29
  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 +195 -10
  14. package/dist-esm/JavaScriptSDK/AppInsightsCore.js +1 -1
  15. package/dist-esm/JavaScriptSDK/BaseCore.js +205 -13
  16. package/dist-esm/JavaScriptSDK/BaseCore.js.map +1 -1
  17. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js +37 -3
  18. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js.map +1 -1
  19. package/dist-esm/JavaScriptSDK/ChannelController.js +14 -2
  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 -2
  23. package/dist-esm/JavaScriptSDK/CookieMgr.js.map +1 -1
  24. package/dist-esm/JavaScriptSDK/CoreUtils.js +1 -1
  25. package/dist-esm/JavaScriptSDK/DataCacheHelper.js +1 -1
  26. package/dist-esm/JavaScriptSDK/DbgExtensionUtils.js +1 -1
  27. package/dist-esm/JavaScriptSDK/DiagnosticLogger.js +14 -1
  28. package/dist-esm/JavaScriptSDK/DiagnosticLogger.js.map +1 -1
  29. package/dist-esm/JavaScriptSDK/EnvUtils.js +1 -1
  30. package/dist-esm/JavaScriptSDK/EventHelpers.js +18 -13
  31. package/dist-esm/JavaScriptSDK/EventHelpers.js.map +1 -1
  32. package/dist-esm/JavaScriptSDK/HelperFuncs.js +3 -13
  33. package/dist-esm/JavaScriptSDK/HelperFuncs.js.map +1 -1
  34. package/dist-esm/JavaScriptSDK/InstrumentHooks.js +1 -1
  35. package/dist-esm/JavaScriptSDK/InternalConstants.js +1 -1
  36. package/dist-esm/JavaScriptSDK/NotificationManager.js +1 -1
  37. package/dist-esm/JavaScriptSDK/PerfManager.js +1 -1
  38. package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js +71 -6
  39. package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js.map +1 -1
  40. package/dist-esm/JavaScriptSDK/RandomHelper.js +1 -1
  41. package/dist-esm/JavaScriptSDK/TelemetryHelpers.js +1 -1
  42. package/dist-esm/JavaScriptSDK/TelemetryInitializerPlugin.js +3 -2
  43. package/dist-esm/JavaScriptSDK/TelemetryInitializerPlugin.js.map +1 -1
  44. package/dist-esm/JavaScriptSDK/UnloadHandlerContainer.js +33 -0
  45. package/dist-esm/JavaScriptSDK/UnloadHandlerContainer.js.map +1 -0
  46. package/dist-esm/JavaScriptSDK.Enums/EventsDiscardedReason.js +1 -1
  47. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js +1 -1
  48. package/dist-esm/JavaScriptSDK.Enums/SendRequestReason.js +1 -1
  49. package/dist-esm/JavaScriptSDK.Enums/TelemetryUnloadReason.js +1 -1
  50. package/dist-esm/JavaScriptSDK.Enums/TelemetryUpdateReason.js +8 -0
  51. package/dist-esm/JavaScriptSDK.Enums/TelemetryUpdateReason.js.map +1 -0
  52. package/dist-esm/JavaScriptSDK.Interfaces/IAppInsightsCore.js +1 -1
  53. package/dist-esm/JavaScriptSDK.Interfaces/IChannelControls.js +1 -1
  54. package/dist-esm/JavaScriptSDK.Interfaces/IConfiguration.js +1 -1
  55. package/dist-esm/JavaScriptSDK.Interfaces/ICookieMgr.js +1 -1
  56. package/dist-esm/JavaScriptSDK.Interfaces/IDbgExtension.js +1 -1
  57. package/dist-esm/JavaScriptSDK.Interfaces/IDiagnosticLogger.js +1 -1
  58. package/dist-esm/JavaScriptSDK.Interfaces/IInstrumentHooks.js +1 -1
  59. package/dist-esm/JavaScriptSDK.Interfaces/INotificationListener.js +1 -1
  60. package/dist-esm/JavaScriptSDK.Interfaces/INotificationManager.js +1 -1
  61. package/dist-esm/JavaScriptSDK.Interfaces/IPerfEvent.js +1 -1
  62. package/dist-esm/JavaScriptSDK.Interfaces/IPerfManager.js +1 -1
  63. package/dist-esm/JavaScriptSDK.Interfaces/IProcessTelemetryContext.js +1 -1
  64. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryInitializers.js +1 -1
  65. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryItem.js +1 -1
  66. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPlugin.js +1 -1
  67. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js +1 -1
  68. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUnloadState.js +1 -1
  69. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUpdateState.js +8 -0
  70. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUpdateState.js.map +1 -0
  71. package/dist-esm/applicationinsights-core-js.js +3 -2
  72. package/dist-esm/applicationinsights-core-js.js.map +1 -1
  73. package/package.json +1 -1
  74. package/src/JavaScriptSDK/BaseCore.ts +272 -14
  75. package/src/JavaScriptSDK/BaseTelemetryPlugin.ts +70 -4
  76. package/src/JavaScriptSDK/ChannelController.ts +18 -1
  77. package/src/JavaScriptSDK/CookieMgr.ts +3 -1
  78. package/src/JavaScriptSDK/DiagnosticLogger.ts +14 -0
  79. package/src/JavaScriptSDK/EventHelpers.ts +18 -12
  80. package/src/JavaScriptSDK/HelperFuncs.ts +4 -2
  81. package/src/JavaScriptSDK/ProcessTelemetryContext.ts +87 -10
  82. package/src/JavaScriptSDK/TelemetryInitializerPlugin.ts +3 -1
  83. package/src/JavaScriptSDK/UnloadHandlerContainer.ts +46 -0
  84. package/src/JavaScriptSDK.Enums/SendRequestReason.ts +5 -0
  85. package/src/JavaScriptSDK.Enums/TelemetryUnloadReason.ts +3 -3
  86. package/src/JavaScriptSDK.Enums/TelemetryUpdateReason.ts +27 -0
  87. package/src/JavaScriptSDK.Interfaces/IAppInsightsCore.ts +29 -2
  88. package/src/JavaScriptSDK.Interfaces/IInstrumentHooks.ts +11 -6
  89. package/src/JavaScriptSDK.Interfaces/IProcessTelemetryContext.ts +25 -2
  90. package/src/JavaScriptSDK.Interfaces/ITelemetryPlugin.ts +12 -1
  91. package/src/JavaScriptSDK.Interfaces/ITelemetryUpdateState.ts +34 -0
  92. package/types/JavaScriptSDK/BaseCore.d.ts +27 -2
  93. package/types/JavaScriptSDK/BaseTelemetryPlugin.d.ts +23 -1
  94. package/types/JavaScriptSDK/DiagnosticLogger.d.ts +10 -0
  95. package/types/JavaScriptSDK/EventHelpers.d.ts +4 -2
  96. package/types/JavaScriptSDK/HelperFuncs.d.ts +2 -1
  97. package/types/JavaScriptSDK/ProcessTelemetryContext.d.ts +11 -1
  98. package/types/JavaScriptSDK/UnloadHandlerContainer.d.ts +11 -0
  99. package/types/JavaScriptSDK.Enums/SendRequestReason.d.ts +4 -0
  100. package/types/JavaScriptSDK.Enums/TelemetryUnloadReason.d.ts +13 -1
  101. package/types/JavaScriptSDK.Enums/TelemetryUpdateReason.d.ts +20 -0
  102. package/types/JavaScriptSDK.Interfaces/IAppInsightsCore.d.ts +24 -1
  103. package/types/JavaScriptSDK.Interfaces/IInstrumentHooks.d.ts +5 -0
  104. package/types/JavaScriptSDK.Interfaces/IProcessTelemetryContext.d.ts +23 -2
  105. package/types/JavaScriptSDK.Interfaces/ITelemetryPlugin.d.ts +11 -1
  106. package/types/JavaScriptSDK.Interfaces/ITelemetryUpdateState.d.ts +22 -0
  107. package/types/applicationinsights-core-js.d.ts +6 -2
@@ -12,27 +12,36 @@ import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
12
12
  import { INotificationManager } from "../JavaScriptSDK.Interfaces/INotificationManager";
13
13
  import { INotificationListener } from "../JavaScriptSDK.Interfaces/INotificationListener";
14
14
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
15
- import { IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
16
- import { createProcessTelemetryContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
15
+ import { IProcessTelemetryContext, IProcessTelemetryUpdateContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
16
+ import { createProcessTelemetryContext, createProcessTelemetryUnloadContext, createProcessTelemetryUpdateContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
17
17
  import { initializePlugins, sortPlugins, _getPluginState } from "./TelemetryHelpers";
18
- import { eLoggingSeverity } from "../JavaScriptSDK.Enums/LoggingEnums";
18
+ import { eLoggingSeverity, _eInternalMessageId } 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";
22
22
  import { createCookieMgr } from "./CookieMgr";
23
- import { arrForEach, isNullOrUndefined, toISOString, getSetValue, setValue, throwError, isNotTruthy, isFunction, objFreeze, proxyFunctions } from "./HelperFuncs";
23
+ import { arrForEach, isNullOrUndefined, toISOString, getSetValue, setValue, throwError, isNotTruthy, isFunction, objFreeze, proxyFunctionAs, proxyFunctions } from "./HelperFuncs";
24
24
  import { strExtensionConfig, strIKey } from "./Constants";
25
- import { DiagnosticLogger, _InternalLogMessage } from "./DiagnosticLogger";
25
+ import { DiagnosticLogger, _InternalLogMessage, _throwInternal } from "./DiagnosticLogger";
26
26
  import { getDebugListener } from "./DbgExtensionUtils";
27
27
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
28
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
31
  import { createUniqueNamespace } from "./DataCacheHelper";
32
+ import { createUnloadHandlerContainer, IUnloadHandlerContainer, UnloadHandler } from "./UnloadHandlerContainer";
33
+ import { TelemetryUpdateReason } from "../JavaScriptSDK.Enums/TelemetryUpdateReason";
34
+ import { ITelemetryUpdateState } from "../JavaScriptSDK.Interfaces/ITelemetryUpdateState";
35
+ import { ITelemetryUnloadState } from "../JavaScriptSDK.Interfaces/ITelemetryUnloadState";
36
+ import { TelemetryUnloadReason } from "../JavaScriptSDK.Enums/TelemetryUnloadReason";
37
+ import { SendRequestReason } from "../JavaScriptSDK.Enums/SendRequestReason";
32
38
  import { strAddNotificationListener, strDisabled, strEventsDiscarded, strEventsSendRequest, strEventsSent, strRemoveNotificationListener, strTeardown } from "./InternalConstants";
33
39
 
34
40
  const strValidationError = "Plugins must provide initialize method";
35
41
  const strNotificationManager = "_notificationManager";
42
+ const strSdkUnloadingError = "SDK is still unloading...";
43
+ const strSdkNotInitialized = "SDK is not initialized";
44
+ const strPluginUnloadFailed = "Failed to unload plugin";
36
45
 
37
46
  /**
38
47
  * Helper to create the default performance manager
@@ -82,6 +91,19 @@ function _validateExtensions(logger: IDiagnosticLogger, channelPriority: number,
82
91
  };
83
92
  }
84
93
 
94
+ function _isPluginPresent(thePlugin: IPlugin, plugins: IPlugin[]) {
95
+ let exists = false;
96
+
97
+ arrForEach(plugins, (plugin) => {
98
+ if (plugin === thePlugin) {
99
+ exists = true;
100
+ return -1;
101
+ }
102
+ });
103
+
104
+ return exists;
105
+ }
106
+
85
107
  function _createDummyNotificationManager(): INotificationManager {
86
108
  return objCreateFn({
87
109
  [strAddNotificationListener]: (listener: INotificationListener) => { },
@@ -114,9 +136,11 @@ export class BaseCore implements IAppInsightsCore {
114
136
  let _channelControl: IChannelController;
115
137
  let _channelConfig: IChannelControls[][];
116
138
  let _channelQueue: _IInternalChannels[];
139
+ let _isUnloading: boolean;
117
140
  let _telemetryInitializerPlugin: TelemetryInitializerPlugin;
118
141
  let _internalLogsEventName: string;
119
142
  let _evtNamespace: string;
143
+ let _unloadHandlers: IUnloadHandlerContainer;
120
144
  let _debugListener: INotificationListener;
121
145
 
122
146
  /**
@@ -132,6 +156,10 @@ export class BaseCore implements IAppInsightsCore {
132
156
  _self.isInitialized = () => _isInitialized;
133
157
 
134
158
  _self.initialize = (config: IConfiguration, extensions: IPlugin[], logger?: IDiagnosticLogger, notificationManager?: INotificationManager): void => {
159
+ if (_isUnloading) {
160
+ throwError(strSdkUnloadingError);
161
+ }
162
+
135
163
  // Make sure core is only initialized once
136
164
  if (_self.isInitialized()) {
137
165
  throwError("Core should not be initialized more than once");
@@ -153,8 +181,7 @@ export class BaseCore implements IAppInsightsCore {
153
181
  config.extensions = isNullOrUndefined(config.extensions) ? [] : config.extensions;
154
182
 
155
183
  // add notification to the extensions in the config so other plugins can access it
156
- let extConfig = getSetValue(config, strExtensionConfig);
157
- extConfig.NotificationManager = notificationManager;
184
+ _initExtConfig(config);
158
185
 
159
186
  if (logger) {
160
187
  _self.logger = logger;
@@ -165,7 +192,7 @@ export class BaseCore implements IAppInsightsCore {
165
192
  _configExtensions.push(...extensions, ...config.extensions);
166
193
  _channelConfig = (config||{}).channels;
167
194
 
168
- _initPluginChain(config);
195
+ _initPluginChain(config, null);
169
196
 
170
197
  if (_self.getTransmissionControls().length === 0) {
171
198
  throwError("No channels available");
@@ -194,7 +221,7 @@ export class BaseCore implements IAppInsightsCore {
194
221
  // Common Schema 4.0
195
222
  setValue(telemetryItem, "ver", "4.0", null, isNullOrUndefined);
196
223
 
197
- if (_self.isInitialized()) {
224
+ if (!_isUnloading && _self.isInitialized()) {
198
225
  // Process the telemetry plugin chain
199
226
  _createTelCtx().processNext(telemetryItem);
200
227
  } else {
@@ -223,9 +250,9 @@ export class BaseCore implements IAppInsightsCore {
223
250
  * called.
224
251
  * @param {INotificationListener} listener - An INotificationListener object.
225
252
  */
226
- _self.addNotificationListener = (listener: INotificationListener): void => {
253
+ _self[strAddNotificationListener] = (listener: INotificationListener): void => {
227
254
  if (_notificationManager) {
228
- _notificationManager.addNotificationListener(listener);
255
+ _notificationManager[strAddNotificationListener](listener);
229
256
  }
230
257
  };
231
258
 
@@ -233,9 +260,9 @@ export class BaseCore implements IAppInsightsCore {
233
260
  * Removes all instances of the listener.
234
261
  * @param {INotificationListener} listener - INotificationListener to remove.
235
262
  */
236
- _self.removeNotificationListener = (listener: INotificationListener): void => {
263
+ _self[strRemoveNotificationListener] = (listener: INotificationListener): void => {
237
264
  if (_notificationManager) {
238
- _notificationManager.removeNotificationListener(listener);
265
+ _notificationManager[strRemoveNotificationListener](listener);
239
266
  }
240
267
  }
241
268
 
@@ -314,12 +341,110 @@ export class BaseCore implements IAppInsightsCore {
314
341
  // Add addTelemetryInitializer
315
342
  proxyFunctions(_self, () => _telemetryInitializerPlugin, [ "addTelemetryInitializer" ]);
316
343
 
344
+ _self.unload = (isAsync: boolean = true, unloadComplete?: (unloadState: ITelemetryUnloadState) => void, cbTimeout?: number): void => {
345
+ if (!_isInitialized) {
346
+ // The SDK is not initialized
347
+ throwError(strSdkNotInitialized);
348
+ }
349
+
350
+ // Check if the SDK still unloading so throw
351
+ if (_isUnloading) {
352
+ // The SDK is already unloading
353
+ throwError(strSdkUnloadingError);
354
+ }
355
+
356
+ let unloadState: ITelemetryUnloadState = {
357
+ reason: TelemetryUnloadReason.SdkUnload,
358
+ isAsync: isAsync,
359
+ flushComplete: false
360
+ }
361
+
362
+ let processUnloadCtx = createProcessTelemetryUnloadContext(_getPluginChain(), _self.config, _self);
363
+ processUnloadCtx.onComplete(() => {
364
+ _initDefaults();
365
+ unloadComplete && unloadComplete(unloadState);
366
+ }, _self);
367
+
368
+ function _doUnload(flushComplete: boolean) {
369
+ unloadState.flushComplete = flushComplete;
370
+ _isUnloading = true;
371
+
372
+ // Run all of the unload handlers first (before unloading the plugins)
373
+ _unloadHandlers.run(processUnloadCtx, unloadState);
374
+
375
+ // Stop polling the internal logs
376
+ _self.stopPollingInternalLogs();
377
+
378
+ // Start unloading the components, from this point onwards the SDK should be considered to be in an unstable state
379
+ processUnloadCtx.processNext(unloadState);
380
+ }
381
+
382
+ if (_channelControl) {
383
+ _channelControl.flush(isAsync, _doUnload, SendRequestReason.SdkUnload, cbTimeout);
384
+ } else {
385
+ _doUnload(true);
386
+ }
387
+ };
388
+
317
389
  _self.getPlugin = _getPlugin;
318
390
 
391
+ _self.addPlugin = <T extends IPlugin = ITelemetryPlugin>(plugin: T, replaceExisting: boolean, isAsync: boolean = true, addCb?: (added?: boolean) => void): void => {
392
+ if (!plugin) {
393
+ addCb && addCb(false);
394
+ _logOrThrowError(strValidationError);
395
+ return;
396
+ }
397
+
398
+ let existingPlugin = _getPlugin(plugin.identifier);
399
+ if (existingPlugin && !replaceExisting) {
400
+ addCb && addCb(false);
401
+
402
+ _logOrThrowError("Plugin [" + plugin.identifier + "] is already loaded!");
403
+ return;
404
+ }
405
+
406
+ let updateState: ITelemetryUpdateState = {
407
+ reason: TelemetryUpdateReason.PluginAdded
408
+ };
409
+
410
+ function _addPlugin(removed: boolean) {
411
+ _configExtensions.push(plugin);
412
+ updateState.added = [plugin];
413
+
414
+ // Re-Initialize the plugin chain
415
+ _initPluginChain(_self.config, updateState);
416
+ addCb && addCb(true);
417
+ }
418
+
419
+ if (existingPlugin) {
420
+ let removedPlugins: IPlugin[] = [existingPlugin.plugin];
421
+ let unloadState: ITelemetryUnloadState = {
422
+ reason: TelemetryUnloadReason.PluginReplace,
423
+ isAsync: isAsync
424
+ };
425
+
426
+ _removePlugins(removedPlugins, unloadState, (removed) => {
427
+ if (!removed) {
428
+ // Previous plugin was successfully removed or was not installed
429
+ addCb && addCb(false);
430
+ } else {
431
+ updateState.removed = removedPlugins
432
+ updateState.reason |= TelemetryUpdateReason.PluginRemoved;
433
+ _addPlugin(true);
434
+ }
435
+ });
436
+ } else {
437
+ _addPlugin(false);
438
+ }
439
+ };
440
+
319
441
  _self.evtNamespace = (): string => {
320
442
  return _evtNamespace;
321
443
  };
322
444
 
445
+ // Create the addUnloadCb
446
+ proxyFunctionAs(_self, "addUnloadCb", () => _unloadHandlers, "add");
447
+
323
448
  function _initDefaults() {
324
449
  _isInitialized = false;
325
450
 
@@ -340,8 +465,10 @@ export class BaseCore implements IAppInsightsCore {
340
465
  _channelControl = null;
341
466
  _channelConfig = null;
342
467
  _channelQueue = null;
468
+ _isUnloading = false;
343
469
  _internalLogsEventName = null;
344
470
  _evtNamespace = createUniqueNamespace("AIBaseCore", true);
471
+ _unloadHandlers = createUnloadHandlerContainer();
345
472
  }
346
473
 
347
474
  function _createTelCtx(): IProcessTelemetryContext {
@@ -349,7 +476,7 @@ export class BaseCore implements IAppInsightsCore {
349
476
  }
350
477
 
351
478
  // Initialize or Re-initialize the plugins
352
- function _initPluginChain(config: IConfiguration) {
479
+ function _initPluginChain(config: IConfiguration, updateState: ITelemetryUpdateState) {
353
480
  // Extension validation
354
481
  let theExtensions = _validateExtensions(_self.logger, ChannelControllerPriority, _configExtensions);
355
482
 
@@ -395,6 +522,10 @@ export class BaseCore implements IAppInsightsCore {
395
522
 
396
523
  // Now reset the extensions to just those being managed by Basecore
397
524
  _self._extensions = objFreeze(sortPlugins(_coreExtensions || [])).slice();
525
+
526
+ if (updateState) {
527
+ _doUpdate(updateState);
528
+ }
398
529
  }
399
530
 
400
531
  function _getPlugin<T extends IPlugin = IPlugin>(pluginIdentifier: string): ILoadedPlugin<T> {
@@ -422,6 +553,25 @@ export class BaseCore implements IAppInsightsCore {
422
553
  isEnabled: () => {
423
554
  let pluginState = _getPluginState(thePlugin);
424
555
  return !pluginState[strTeardown] && !pluginState[strDisabled];
556
+ },
557
+ remove: (isAsync: boolean = true, removeCb?: (removed?: boolean) => void): void => {
558
+ let pluginsToRemove: IPlugin[] = [thePlugin];
559
+ let unloadState: ITelemetryUnloadState = {
560
+ reason: TelemetryUnloadReason.PluginUnload,
561
+ isAsync: isAsync
562
+ };
563
+
564
+ _removePlugins(pluginsToRemove, unloadState, (removed) => {
565
+ if (removed) {
566
+ // Re-Initialize the plugin chain
567
+ _initPluginChain(_self.config, {
568
+ reason: TelemetryUpdateReason.PluginRemoved,
569
+ removed: pluginsToRemove
570
+ });
571
+ }
572
+
573
+ removeCb && removeCb(removed);
574
+ });
425
575
  }
426
576
  }
427
577
  }
@@ -445,6 +595,55 @@ export class BaseCore implements IAppInsightsCore {
445
595
  return _pluginChain;
446
596
  }
447
597
 
598
+ function _removePlugins(thePlugins: IPlugin[], unloadState: ITelemetryUnloadState, removeComplete: (removed: boolean) => void) {
599
+
600
+ if (thePlugins && thePlugins.length > 0) {
601
+ let unloadChain = createTelemetryProxyChain(thePlugins, _self.config, _self);
602
+ let unloadCtx = createProcessTelemetryUnloadContext(unloadChain, _self.config, _self);
603
+
604
+ unloadCtx.onComplete(() => {
605
+ let removed = false;
606
+
607
+ // Remove the listed config extensions
608
+ let newConfigExtensions: IPlugin[] = [];
609
+ arrForEach(_configExtensions, (plugin, idx) => {
610
+ if (!_isPluginPresent(plugin, thePlugins)) {
611
+ newConfigExtensions.push(plugin);
612
+ } else {
613
+ removed = true;
614
+ }
615
+ });
616
+
617
+ _configExtensions = newConfigExtensions;
618
+
619
+ // Re-Create the channel config
620
+ let newChannelConfig: IChannelControls[][] = [];
621
+ if (_channelConfig) {
622
+ arrForEach(_channelConfig, (queue, idx) => {
623
+ let newQueue: IChannelControls[] = [];
624
+ arrForEach(queue, (channel) => {
625
+ if (!_isPluginPresent(channel, thePlugins)) {
626
+ newQueue.push(channel);
627
+ } else {
628
+ removed = true;
629
+ }
630
+ });
631
+
632
+ newChannelConfig.push(newQueue);
633
+ });
634
+
635
+ _channelConfig = newChannelConfig;
636
+ }
637
+
638
+ removeComplete && removeComplete(removed);
639
+ });
640
+
641
+ unloadCtx.processNext(unloadState);
642
+ } else {
643
+ removeComplete(false);
644
+ }
645
+ }
646
+
448
647
  function _flushInternalLogs() {
449
648
  let queue: _InternalLogMessage[] = _self.logger ? _self.logger.queue : [];
450
649
  if (queue) {
@@ -488,6 +687,29 @@ export class BaseCore implements IAppInsightsCore {
488
687
  setValue(_self.config, "createPerfMgr", _createPerfManager);
489
688
  }
490
689
  }
690
+
691
+ function _initExtConfig(config: IConfiguration) {
692
+ let extConfig = getSetValue(config, strExtensionConfig);
693
+ extConfig.NotificationManager = _notificationManager;
694
+ }
695
+
696
+ function _doUpdate(updateState: ITelemetryUpdateState): void {
697
+ let updateCtx = createProcessTelemetryUpdateContext(_getPluginChain(), _self.config, _self);
698
+
699
+ if (!_self._updateHook || _self._updateHook(updateCtx, updateState) !== true) {
700
+ updateCtx.processNext(updateState);
701
+ }
702
+ }
703
+
704
+ function _logOrThrowError(message: string) {
705
+ let logger = _self.logger;
706
+ if (logger) {
707
+ // there should always be a logger
708
+ _throwInternal(logger, eLoggingSeverity.WARNING, _eInternalMessageId.PluginException, message);
709
+ } else {
710
+ throwError(message);
711
+ }
712
+ }
491
713
  });
492
714
  }
493
715
 
@@ -586,11 +808,28 @@ export class BaseCore implements IAppInsightsCore {
586
808
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
587
809
  }
588
810
 
811
+ /**
812
+ * Unload and Tear down the SDK and any initialized plugins, after calling this the SDK will be considered
813
+ * to be un-initialized and non-operational, re-initializing the SDK should only be attempted if the previous
814
+ * unload call return `true` stating that all plugins reported that they also unloaded, the recommended
815
+ * approach is to create a new instance and initialize that instance.
816
+ * This is due to possible unexpected side effects caused by plugins not supporting unload / teardown, unable
817
+ * to successfully remove any global references or they may just be completing the unload process asynchronously.
818
+ */
819
+ public unload(isAsync?: boolean, unloadComplete?: (unloadState: ITelemetryUnloadState) => void, cbTimeout?: number): void {
820
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
821
+ return null;
822
+ }
823
+
589
824
  public getPlugin<T extends IPlugin = IPlugin>(pluginIdentifier: string): ILoadedPlugin<T> {
590
825
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
591
826
  return null;
592
827
  }
593
828
 
829
+ public addPlugin<T extends IPlugin = ITelemetryPlugin>(plugin: T, replaceExisting: boolean, doAsync: boolean, addCb?: (added?: boolean) => void): void {
830
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
831
+ }
832
+
594
833
  /**
595
834
  * Returns the unique event namespace that should be used
596
835
  */
@@ -599,7 +838,26 @@ export class BaseCore implements IAppInsightsCore {
599
838
  return null;
600
839
  }
601
840
 
841
+ /**
842
+ * Add an unload handler that will be called when the SDK is being unloaded
843
+ * @param handler - the handler
844
+ */
845
+ public addUnloadCb(handler: UnloadHandler): void {
846
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
847
+ }
848
+
602
849
  protected releaseQueue() {
603
850
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
604
851
  }
852
+
853
+ /**
854
+ * Hook for Core extensions to allow them to update their own configuration before updating all of the plugins.
855
+ * @param updateCtx - The plugin update context
856
+ * @param updateState - The Update State
857
+ * @returns boolean - True means the extension class will call updateState otherwise the Core will
858
+ */
859
+ protected _updateHook?(updateCtx: IProcessTelemetryUpdateContext, updateState: ITelemetryUpdateState): void | boolean {
860
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
861
+ return false;
862
+ }
605
863
  }
@@ -9,14 +9,17 @@ 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, IProcessTelemetryUnloadContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
12
+ import { IProcessTelemetryContext, IProcessTelemetryUnloadContext, IProcessTelemetryUpdateContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
13
13
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
14
- import { createProcessTelemetryContext, createProcessTelemetryUnloadContext } from "./ProcessTelemetryContext";
15
- import { arrForEach, isArray, isFunction, isNullOrUndefined, setValue } from "./HelperFuncs";
14
+ import { createProcessTelemetryContext, createProcessTelemetryUnloadContext, createProcessTelemetryUpdateContext } from "./ProcessTelemetryContext";
15
+ import { arrForEach, isArray, isFunction, isNullOrUndefined, proxyFunctionAs, setValue } from "./HelperFuncs";
16
16
  import { strExtensionConfig } from "./Constants";
17
+ import { createUnloadHandlerContainer, IUnloadHandlerContainer, UnloadHandler } from "./UnloadHandlerContainer";
17
18
  import { IInstrumentHook } from "../JavaScriptSDK.Interfaces/IInstrumentHooks";
18
19
  import { ITelemetryUnloadState } from "../JavaScriptSDK.Interfaces/ITelemetryUnloadState";
19
20
  import { TelemetryUnloadReason } from "../JavaScriptSDK.Enums/TelemetryUnloadReason";
21
+ import { ITelemetryUpdateState } from "../JavaScriptSDK.Interfaces/ITelemetryUpdateState";
22
+ import { TelemetryUpdateReason } from "../JavaScriptSDK.Enums/TelemetryUpdateReason";
20
23
  import { strDoTeardown, strIsInitialized, strSetNextPlugin } from "./InternalConstants";
21
24
 
22
25
  let strGetPlugin = "getPlugin";
@@ -86,6 +89,15 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
86
89
  */
87
90
  protected _doTeardown?: (unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState, asyncCallback?: () => void) => void | boolean;
88
91
 
92
+ /**
93
+ * Extension hook to allow implementations to perform some additional update operations before the BaseTelemetryPlugin finishes it's removal
94
+ * @param updateCtx - This is the context that should be used during updating.
95
+ * @param updateState - The details / state of the update process, it holds details like the current and previous configuration.
96
+ * @param asyncCallback - An optional callback that the plugin must call if it returns true to inform the caller that it has completed any async update operations.
97
+ * @returns boolean - true if the plugin has or will call asyncCallback, this allows the plugin to perform any asynchronous operations.
98
+ */
99
+ protected _doUpdate?: (updateCtx?: IProcessTelemetryUpdateContext, updateState?: ITelemetryUpdateState, asyncCallback?: () => void) => void | boolean;
100
+
89
101
  constructor() {
90
102
  let _self = this; // Setting _self here as it's used outside of the dynamicProto as well
91
103
 
@@ -93,6 +105,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
93
105
  let _isinitialized: boolean;
94
106
  let _rootCtx: IProcessTelemetryContext; // Used as the root context, holding the current config and initialized core
95
107
  let _nextPlugin: ITelemetryPlugin | ITelemetryPluginChain; // Used for backward compatibility where plugins don't call the main pipeline
108
+ let _unloadHandlerContainer: IUnloadHandlerContainer;
96
109
  let _hooks: IInstrumentHook[];
97
110
 
98
111
  _initDefaults();
@@ -120,11 +133,12 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
120
133
  isAsync: false
121
134
  };
122
135
 
123
-
124
136
  function _unloadCallback() {
125
137
  if (!unloadDone) {
126
138
  unloadDone = true;
127
139
 
140
+ _unloadHandlerContainer.run(theUnloadCtx, unloadState);
141
+
128
142
  // Remove all instrumentation hooks
129
143
  arrForEach(_hooks, (fn) => {
130
144
  fn.rm();
@@ -148,6 +162,37 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
148
162
 
149
163
  return result;
150
164
  };
165
+
166
+ _self.update = (updateCtx: IProcessTelemetryUpdateContext, updateState: ITelemetryUpdateState) => {
167
+ // If this plugin has already been torn down (not operational) or is not initialized (core is not set)
168
+ // or the core being used for unload was not the same core used for initialization.
169
+ if (!_self.core || (updateCtx && _self.core !== updateCtx.core())) {
170
+ // Do Nothing
171
+ return;
172
+ }
173
+
174
+ let result: void | boolean;
175
+ let updateDone = false;
176
+ let theUpdateCtx = updateCtx || createProcessTelemetryUpdateContext(null, {}, _self.core, _nextPlugin && _nextPlugin[strGetPlugin] ? _nextPlugin[strGetPlugin]() : _nextPlugin);
177
+ let theUpdateState: ITelemetryUpdateState = updateState || {
178
+ reason: TelemetryUpdateReason.Unknown
179
+ };
180
+
181
+ function _updateCallback() {
182
+ if (!updateDone) {
183
+ updateDone = true;
184
+ _setDefaults(theUpdateCtx.getCfg(), theUpdateCtx.core(), theUpdateCtx.getNext());
185
+ }
186
+ }
187
+
188
+ if (!_self._doUpdate || _self._doUpdate(theUpdateCtx, theUpdateState, _updateCallback) !== true) {
189
+ _updateCallback();
190
+ } else {
191
+ result = true;
192
+ }
193
+
194
+ return result;
195
+ };
151
196
 
152
197
  _self._addHook = (hooks: IInstrumentHook | IInstrumentHook[]) => {
153
198
  if (hooks) {
@@ -158,6 +203,8 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
158
203
  }
159
204
  }
160
205
  };
206
+
207
+ proxyFunctionAs(_self, "_addUnloadCb", () => _unloadHandlerContainer, "add");
161
208
  });
162
209
 
163
210
  // These are added after the dynamicProto so that are not moved to the prototype
@@ -240,6 +287,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
240
287
  _rootCtx = null;
241
288
  _nextPlugin = null;
242
289
  _hooks = [];
290
+ _unloadHandlerContainer = createUnloadHandlerContainer();
243
291
  }
244
292
  }
245
293
 
@@ -262,6 +310,24 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
262
310
 
263
311
  public abstract processTelemetry(env: ITelemetryItem, itemCtx?: IProcessTelemetryContext): void;
264
312
 
313
+ /**
314
+ * The the plugin should re-evaluate configuration and update any cached configuration settings.
315
+ * @param updateCtx - This is the context that should be used during updating.
316
+ * @param updateState - The details / state of the update process, it holds details like the current and previous configuration.
317
+ * @returns boolean - true if the plugin has or will call updateCtx.processNext(), this allows the plugin to perform any asynchronous operations.
318
+ */
319
+ public update(updateCtx: IProcessTelemetryUpdateContext, updateState: ITelemetryUpdateState): void | boolean{
320
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
321
+ }
322
+
323
+ /**
324
+ * Add an unload handler that will be called when the SDK is being unloaded
325
+ * @param handler - the handler
326
+ */
327
+ protected _addUnloadCb(handler: UnloadHandler): void {
328
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
329
+ }
330
+
265
331
  /**
266
332
  * Add this hook so that it is automatically removed during unloading
267
333
  * @param hooks - The single hook or an array of IInstrumentHook objects
@@ -3,14 +3,16 @@
3
3
 
4
4
  import { SendRequestReason } from "../JavaScriptSDK.Enums/SendRequestReason";
5
5
  import { TelemetryUnloadReason } from "../JavaScriptSDK.Enums/TelemetryUnloadReason";
6
+ import { TelemetryUpdateReason } from "../JavaScriptSDK.Enums/TelemetryUpdateReason";
6
7
  import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore";
7
8
  import { IChannelControls } from "../JavaScriptSDK.Interfaces/IChannelControls";
8
9
  import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
9
- import { IBaseProcessingContext, IProcessTelemetryContext, IProcessTelemetryUnloadContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
10
+ import { IBaseProcessingContext, IProcessTelemetryContext, IProcessTelemetryUnloadContext, IProcessTelemetryUpdateContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
10
11
  import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
11
12
  import { IPlugin } from "../JavaScriptSDK.Interfaces/ITelemetryPlugin";
12
13
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
13
14
  import { ITelemetryUnloadState } from "../JavaScriptSDK.Interfaces/ITelemetryUnloadState";
15
+ import { ITelemetryUpdateState } from "../JavaScriptSDK.Interfaces/ITelemetryUpdateState";
14
16
  import { arrForEach, isArray, objFreeze, throwError } from "./HelperFuncs";
15
17
  import { strPause, strProcessNext, strResume, strTeardown } from "./InternalConstants";
16
18
  import { createProcessTelemetryContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
@@ -90,6 +92,20 @@ export function createChannelControllerPlugin(channelQueue: _IInternalChannels[]
90
92
  _runChainOnComplete();
91
93
  }
92
94
 
95
+ function _doUpdate(updateCtx: IProcessTelemetryUpdateContext, updateState: ITelemetryUpdateState) {
96
+ let theUpdateState: ITelemetryUpdateState = updateState || {
97
+ reason: TelemetryUpdateReason.Unknown
98
+ };
99
+
100
+ _processChannelQueue(channelQueue, updateCtx, (chainCtx: IProcessTelemetryUpdateContext) => {
101
+ chainCtx[strProcessNext](theUpdateState);
102
+ }, () => {
103
+ updateCtx[strProcessNext](theUpdateState);
104
+ });
105
+
106
+ return true;
107
+ }
108
+
93
109
  function _doTeardown(unloadCtx: IProcessTelemetryUnloadContext, unloadState: ITelemetryUnloadState) {
94
110
  let theUnloadState: ITelemetryUnloadState = unloadState || {
95
111
  reason: TelemetryUnloadReason.ManualTeardown,
@@ -152,6 +168,7 @@ export function createChannelControllerPlugin(channelQueue: _IInternalChannels[]
152
168
  itemCtx[strProcessNext](item);
153
169
  });
154
170
  },
171
+ update: _doUpdate,
155
172
  [strPause]: () => {
156
173
  _processChannelQueue(channelQueue, _getTelCtx(), (chainCtx: IProcessTelemetryContext) => {
157
174
  chainCtx.iterate<IChannelControls>((plugin) => {
@@ -11,6 +11,7 @@ import {
11
11
  import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
12
12
  import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore";
13
13
  import { strEmpty } from "./InternalConstants";
14
+ import { _throwInternal } from "./DiagnosticLogger";
14
15
 
15
16
  const strToGMTString = "toGMTString";
16
17
  const strToUTCString = "toUTCString";
@@ -252,7 +253,8 @@ export function areCookiesSupported(logger?: IDiagnosticLogger): any {
252
253
  let doc = _doc || {} as Document;
253
254
  _supportsCookies = doc[strCookie] !== undefined;
254
255
  } catch (e) {
255
- logger && logger.throwInternal(
256
+ _throwInternal(
257
+ logger,
256
258
  eLoggingSeverity.WARNING,
257
259
  _eInternalMessageId.CannotAccessCookie,
258
260
  "Cannot access document.cookie - " + getExceptionName(e),
@@ -320,3 +320,17 @@ export class DiagnosticLogger implements IDiagnosticLogger {
320
320
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
321
321
  }
322
322
  }
323
+
324
+ /**
325
+ * This is a helper method which will call throwInternal on the passed logger, will throw exceptions in
326
+ * debug mode or attempt to log the error as a console warning. This helper is provided mostly to better
327
+ * support minification as logger.throwInternal() will not compress the publish "throwInternal" used throughout
328
+ * the code.
329
+ * @param logger - The Diagnostic Logger instance to use.
330
+ * @param severity {LoggingSeverity} - The severity of the log message
331
+ * @param message {_InternalLogMessage} - The log message.
332
+ */
333
+ export function _throwInternal(logger: IDiagnosticLogger, severity: LoggingSeverity, msgId: _InternalMessageId, msg: string, properties?: Object, isUserAct = false) {
334
+ (logger || new DiagnosticLogger()).throwInternal(severity, msgId, msg, properties, isUserAct);
335
+ }
336
+