@microsoft/applicationinsights-core-js 2.8.0-beta.2202-07 → 2.8.0-beta.2203-03

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 (128) hide show
  1. package/browser/applicationinsights-core-js.integrity.json +9 -9
  2. package/browser/applicationinsights-core-js.js +1137 -484
  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 +6529 -2784
  7. package/dist/applicationinsights-core-js.api.md +290 -30
  8. package/dist/applicationinsights-core-js.d.ts +481 -89
  9. package/dist/applicationinsights-core-js.js +1137 -484
  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 +481 -89
  14. package/dist-esm/JavaScriptSDK/AppInsightsCore.js +1 -1
  15. package/dist-esm/JavaScriptSDK/BaseCore.js +248 -32
  16. package/dist-esm/JavaScriptSDK/BaseCore.js.map +1 -1
  17. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js +50 -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 +195 -107
  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/UnloadHandlerContainer.js +32 -0
  52. package/dist-esm/JavaScriptSDK/UnloadHandlerContainer.js.map +1 -0
  53. package/dist-esm/JavaScriptSDK.Enums/EventsDiscardedReason.js +1 -1
  54. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js +90 -96
  55. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js.map +1 -1
  56. package/dist-esm/JavaScriptSDK.Enums/SendRequestReason.js +1 -1
  57. package/dist-esm/JavaScriptSDK.Enums/TelemetryUnloadReason.js +8 -0
  58. package/dist-esm/JavaScriptSDK.Enums/TelemetryUnloadReason.js.map +1 -0
  59. package/dist-esm/JavaScriptSDK.Interfaces/IAppInsightsCore.js +1 -1
  60. package/dist-esm/JavaScriptSDK.Interfaces/IChannelControls.js +1 -1
  61. package/dist-esm/JavaScriptSDK.Interfaces/IConfiguration.js +1 -1
  62. package/dist-esm/JavaScriptSDK.Interfaces/ICookieMgr.js +1 -1
  63. package/dist-esm/JavaScriptSDK.Interfaces/IDbgExtension.js +1 -1
  64. package/dist-esm/JavaScriptSDK.Interfaces/IDiagnosticLogger.js +1 -1
  65. package/dist-esm/JavaScriptSDK.Interfaces/IInstrumentHooks.js +1 -1
  66. package/dist-esm/JavaScriptSDK.Interfaces/INotificationListener.js +1 -1
  67. package/dist-esm/JavaScriptSDK.Interfaces/INotificationManager.js +1 -1
  68. package/dist-esm/JavaScriptSDK.Interfaces/IPerfEvent.js +1 -1
  69. package/dist-esm/JavaScriptSDK.Interfaces/IPerfManager.js +1 -1
  70. package/dist-esm/JavaScriptSDK.Interfaces/IProcessTelemetryContext.js +1 -1
  71. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryInitializers.js +1 -1
  72. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryItem.js +1 -1
  73. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPlugin.js +1 -1
  74. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js +1 -2
  75. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js.map +1 -1
  76. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUnloadState.js +8 -0
  77. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUnloadState.js.map +1 -0
  78. package/dist-esm/applicationinsights-core-js.js +9 -4
  79. package/dist-esm/applicationinsights-core-js.js.map +1 -1
  80. package/package.json +1 -1
  81. package/src/JavaScriptSDK/BaseCore.ts +312 -33
  82. package/src/JavaScriptSDK/BaseTelemetryPlugin.ts +90 -5
  83. package/src/JavaScriptSDK/ChannelController.ts +107 -61
  84. package/src/JavaScriptSDK/CookieMgr.ts +4 -4
  85. package/src/JavaScriptSDK/CoreUtils.ts +6 -143
  86. package/src/JavaScriptSDK/DataCacheHelper.ts +106 -0
  87. package/src/JavaScriptSDK/DiagnosticLogger.ts +12 -11
  88. package/src/JavaScriptSDK/EnvUtils.ts +7 -6
  89. package/src/JavaScriptSDK/EventHelpers.ts +542 -0
  90. package/src/JavaScriptSDK/HelperFuncs.ts +35 -54
  91. package/src/JavaScriptSDK/InternalConstants.ts +26 -0
  92. package/src/JavaScriptSDK/NotificationManager.ts +7 -11
  93. package/src/JavaScriptSDK/ProcessTelemetryContext.ts +248 -121
  94. package/src/JavaScriptSDK/RandomHelper.ts +2 -1
  95. package/src/JavaScriptSDK/TelemetryHelpers.ts +47 -15
  96. package/src/JavaScriptSDK/TelemetryInitializerPlugin.ts +5 -15
  97. package/src/JavaScriptSDK/UnloadHandlerContainer.ts +44 -0
  98. package/src/JavaScriptSDK.Enums/LoggingEnums.ts +184 -87
  99. package/src/JavaScriptSDK.Enums/SendRequestReason.ts +5 -0
  100. package/src/JavaScriptSDK.Enums/TelemetryUnloadReason.ts +27 -0
  101. package/src/JavaScriptSDK.Interfaces/IAppInsightsCore.ts +49 -2
  102. package/src/JavaScriptSDK.Interfaces/IChannelControls.ts +9 -2
  103. package/src/JavaScriptSDK.Interfaces/IProcessTelemetryContext.ts +55 -16
  104. package/src/JavaScriptSDK.Interfaces/ITelemetryPlugin.ts +16 -9
  105. package/src/JavaScriptSDK.Interfaces/ITelemetryPluginChain.ts +9 -11
  106. package/src/JavaScriptSDK.Interfaces/ITelemetryUnloadState.ts +10 -0
  107. package/types/JavaScriptSDK/BaseCore.d.ts +21 -1
  108. package/types/JavaScriptSDK/BaseTelemetryPlugin.d.ts +26 -1
  109. package/types/JavaScriptSDK/ChannelController.d.ts +4 -0
  110. package/types/JavaScriptSDK/CoreUtils.d.ts +1 -42
  111. package/types/JavaScriptSDK/DataCacheHelper.d.ts +13 -0
  112. package/types/JavaScriptSDK/EventHelpers.d.ts +152 -0
  113. package/types/JavaScriptSDK/HelperFuncs.d.ts +8 -17
  114. package/types/JavaScriptSDK/InternalConstants.d.ts +20 -0
  115. package/types/JavaScriptSDK/ProcessTelemetryContext.d.ts +12 -3
  116. package/types/JavaScriptSDK/TelemetryHelpers.d.ts +8 -0
  117. package/types/JavaScriptSDK/TelemetryInitializerPlugin.d.ts +0 -7
  118. package/types/JavaScriptSDK/UnloadHandlerContainer.d.ts +11 -0
  119. package/types/JavaScriptSDK.Enums/LoggingEnums.d.ts +91 -2
  120. package/types/JavaScriptSDK.Enums/SendRequestReason.d.ts +4 -0
  121. package/types/JavaScriptSDK.Enums/TelemetryUnloadReason.d.ts +21 -0
  122. package/types/JavaScriptSDK.Interfaces/IAppInsightsCore.d.ts +41 -1
  123. package/types/JavaScriptSDK.Interfaces/IChannelControls.d.ts +9 -2
  124. package/types/JavaScriptSDK.Interfaces/IProcessTelemetryContext.d.ts +49 -14
  125. package/types/JavaScriptSDK.Interfaces/ITelemetryPlugin.d.ts +15 -8
  126. package/types/JavaScriptSDK.Interfaces/ITelemetryPluginChain.d.ts +9 -10
  127. package/types/JavaScriptSDK.Interfaces/ITelemetryUnloadState.d.ts +6 -0
  128. package/types/applicationinsights-core-js.d.ts +7 -3
@@ -13,24 +13,33 @@ import { INotificationManager } from "../JavaScriptSDK.Interfaces/INotificationM
13
13
  import { INotificationListener } from "../JavaScriptSDK.Interfaces/INotificationListener";
14
14
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
15
15
  import { IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
16
- import { createProcessTelemetryContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
17
- import { initializePlugins, sortPlugins } from "./TelemetryHelpers";
18
- import { LoggingSeverity } from "../JavaScriptSDK.Enums/LoggingEnums";
16
+ import { createProcessTelemetryContext, createProcessTelemetryUnloadContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
17
+ import { initializePlugins, sortPlugins, _getPluginState } from "./TelemetryHelpers";
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
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 { createUnloadHandlerContainer, IUnloadHandlerContainer, UnloadHandler } from "./UnloadHandlerContainer";
33
+ import { ITelemetryUnloadState } from "../JavaScriptSDK.Interfaces/ITelemetryUnloadState";
34
+ import { TelemetryUnloadReason } from "../JavaScriptSDK.Enums/TelemetryUnloadReason";
35
+ import { SendRequestReason } from "../JavaScriptSDK.Enums/SendRequestReason";
36
+ import { strAddNotificationListener, strDisabled, strEventsDiscarded, strEventsSendRequest, strEventsSent, strRemoveNotificationListener, strTeardown } from "./InternalConstants";
31
37
 
32
38
  const strValidationError = "Plugins must provide initialize method";
33
39
  const strNotificationManager = "_notificationManager";
40
+ const strSdkUnloadingError = "SDK is still unloading...";
41
+ const strSdkNotInitialized = "SDK is not initialized";
42
+ const strPluginUnloadFailed = "Failed to unload plugin";
34
43
 
35
44
  /**
36
45
  * Helper to create the default performance manager
@@ -80,6 +89,29 @@ function _validateExtensions(logger: IDiagnosticLogger, channelPriority: number,
80
89
  };
81
90
  }
82
91
 
92
+ function _isPluginPresent(thePlugin: IPlugin, plugins: IPlugin[]) {
93
+ let exists = false;
94
+
95
+ arrForEach(plugins, (plugin) => {
96
+ if (plugin === thePlugin) {
97
+ exists = true;
98
+ return -1;
99
+ }
100
+ });
101
+
102
+ return exists;
103
+ }
104
+
105
+ function _createDummyNotificationManager(): INotificationManager {
106
+ return objCreateFn({
107
+ [strAddNotificationListener]: (listener: INotificationListener) => { },
108
+ [strRemoveNotificationListener]: (listener: INotificationListener) => { },
109
+ [strEventsSent]: (events: ITelemetryItem[]) => { },
110
+ [strEventsDiscarded]: (events: ITelemetryItem[], reason: number) => { },
111
+ [strEventsSendRequest]: (sendReason: number, isAsync: boolean) => { }
112
+ });
113
+ }
114
+
83
115
  export class BaseCore implements IAppInsightsCore {
84
116
  public static defaultConfig: IConfiguration;
85
117
  public config: IConfiguration;
@@ -102,8 +134,11 @@ export class BaseCore implements IAppInsightsCore {
102
134
  let _channelControl: IChannelController;
103
135
  let _channelConfig: IChannelControls[][];
104
136
  let _channelQueue: _IInternalChannels[];
137
+ let _isUnloading: boolean;
105
138
  let _telemetryInitializerPlugin: TelemetryInitializerPlugin;
106
139
  let _internalLogsEventName: string;
140
+ let _evtNamespace: string;
141
+ let _unloadHandlers: IUnloadHandlerContainer;
107
142
  let _debugListener: INotificationListener;
108
143
 
109
144
  /**
@@ -119,6 +154,10 @@ export class BaseCore implements IAppInsightsCore {
119
154
  _self.isInitialized = () => _isInitialized;
120
155
 
121
156
  _self.initialize = (config: IConfiguration, extensions: IPlugin[], logger?: IDiagnosticLogger, notificationManager?: INotificationManager): void => {
157
+ if (_isUnloading) {
158
+ throwError(strSdkUnloadingError);
159
+ }
160
+
122
161
  // Make sure core is only initialized once
123
162
  if (_self.isInitialized()) {
124
163
  throwError("Core should not be initialized more than once");
@@ -140,8 +179,7 @@ export class BaseCore implements IAppInsightsCore {
140
179
  config.extensions = isNullOrUndefined(config.extensions) ? [] : config.extensions;
141
180
 
142
181
  // add notification to the extensions in the config so other plugins can access it
143
- let extConfig = getSetValue(config, strExtensionConfig);
144
- extConfig.NotificationManager = notificationManager;
182
+ _initExtConfig(config);
145
183
 
146
184
  if (logger) {
147
185
  _self.logger = logger;
@@ -181,29 +219,21 @@ export class BaseCore implements IAppInsightsCore {
181
219
  // Common Schema 4.0
182
220
  setValue(telemetryItem, "ver", "4.0", null, isNullOrUndefined);
183
221
 
184
- if (_self.isInitialized()) {
222
+ if (!_isUnloading && _self.isInitialized()) {
185
223
  // Process the telemetry plugin chain
186
- _self.getProcessTelContext().processNext(telemetryItem);
224
+ _createTelCtx().processNext(telemetryItem);
187
225
  } else {
188
226
  // Queue events until all extensions are initialized
189
227
  _eventQueue.push(telemetryItem);
190
228
  }
191
229
  };
192
230
 
193
- _self.getProcessTelContext = (): IProcessTelemetryContext => {
194
- return createProcessTelemetryContext(_getPluginChain(), _self.config, _self);
195
- };
231
+ _self.getProcessTelContext = _createTelCtx;
196
232
 
197
233
  _self.getNotifyMgr = (): INotificationManager => {
198
234
  if (!_notificationManager) {
199
235
  // 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
- });
236
+ _notificationManager = _createDummyNotificationManager();
207
237
 
208
238
  // For backward compatibility only
209
239
  _self[strNotificationManager] = _notificationManager;
@@ -218,9 +248,9 @@ export class BaseCore implements IAppInsightsCore {
218
248
  * called.
219
249
  * @param {INotificationListener} listener - An INotificationListener object.
220
250
  */
221
- _self.addNotificationListener = (listener: INotificationListener): void => {
251
+ _self[strAddNotificationListener] = (listener: INotificationListener): void => {
222
252
  if (_notificationManager) {
223
- _notificationManager.addNotificationListener(listener);
253
+ _notificationManager[strAddNotificationListener](listener);
224
254
  }
225
255
  };
226
256
 
@@ -228,9 +258,9 @@ export class BaseCore implements IAppInsightsCore {
228
258
  * Removes all instances of the listener.
229
259
  * @param {INotificationListener} listener - INotificationListener to remove.
230
260
  */
231
- _self.removeNotificationListener = (listener: INotificationListener): void => {
261
+ _self[strRemoveNotificationListener] = (listener: INotificationListener): void => {
232
262
  if (_notificationManager) {
233
- _notificationManager.removeNotificationListener(listener);
263
+ _notificationManager[strRemoveNotificationListener](listener);
234
264
  }
235
265
  }
236
266
 
@@ -270,7 +300,7 @@ export class BaseCore implements IAppInsightsCore {
270
300
  _eventQueue = [];
271
301
 
272
302
  arrForEach(eventQueue, (event: ITelemetryItem) => {
273
- _self.getProcessTelContext().processNext(event);
303
+ _createTelCtx().processNext(event);
274
304
  });
275
305
  }
276
306
  };
@@ -309,13 +339,108 @@ export class BaseCore implements IAppInsightsCore {
309
339
  // Add addTelemetryInitializer
310
340
  proxyFunctions(_self, () => _telemetryInitializerPlugin, [ "addTelemetryInitializer" ]);
311
341
 
342
+ _self.unload = (isAsync: boolean = true, unloadComplete?: (unloadState: ITelemetryUnloadState) => void, cbTimeout?: number): void => {
343
+ if (!_isInitialized) {
344
+ // The SDK is not initialized
345
+ throwError(strSdkNotInitialized);
346
+ }
347
+
348
+ // Check if the SDK still unloading so throw
349
+ if (_isUnloading) {
350
+ // The SDK is already unloading
351
+ throwError(strSdkUnloadingError);
352
+ }
353
+
354
+ let unloadState: ITelemetryUnloadState = {
355
+ reason: TelemetryUnloadReason.SdkUnload,
356
+ isAsync: isAsync,
357
+ flushComplete: false
358
+ }
359
+
360
+ let processUnloadCtx = createProcessTelemetryUnloadContext(_getPluginChain(), _self.config, _self);
361
+ processUnloadCtx.onComplete(() => {
362
+ _initDefaults();
363
+ unloadComplete && unloadComplete(unloadState);
364
+ }, _self);
365
+
366
+ function _doUnload(flushComplete: boolean) {
367
+ unloadState.flushComplete = flushComplete;
368
+ _isUnloading = true;
369
+
370
+ // Run all of the unload handlers first (before unloading the plugins)
371
+ _unloadHandlers.run(processUnloadCtx, unloadState);
372
+
373
+ // Stop polling the internal logs
374
+ _self.stopPollingInternalLogs();
375
+
376
+ // Start unloading the components, from this point onwards the SDK should be considered to be in an unstable state
377
+ processUnloadCtx.processNext(unloadState);
378
+ }
379
+
380
+ if (_channelControl) {
381
+ _channelControl.flush(isAsync, _doUnload, SendRequestReason.SdkUnload, cbTimeout);
382
+ } else {
383
+ _doUnload(true);
384
+ }
385
+ };
386
+
312
387
  _self.getPlugin = _getPlugin;
313
388
 
389
+ _self.addPlugin = <T extends IPlugin = ITelemetryPlugin>(plugin: T, replaceExisting: boolean, isAsync: boolean = true, addCb?: (added?: boolean) => void): void => {
390
+ if (!plugin) {
391
+ addCb && addCb(false);
392
+ _logOrThrowError(strValidationError);
393
+ return;
394
+ }
395
+
396
+ let existingPlugin = _getPlugin(plugin.identifier);
397
+ if (existingPlugin && !replaceExisting) {
398
+ addCb && addCb(false);
399
+
400
+ _logOrThrowError("Plugin [" + plugin.identifier + "] is already loaded!");
401
+ return;
402
+ }
403
+
404
+ function _addPlugin(removed: boolean) {
405
+ _configExtensions.push(plugin);
406
+
407
+ // Re-Initialize the plugin chain
408
+ _initPluginChain(_self.config);
409
+ addCb && addCb(true);
410
+ }
411
+
412
+ if (existingPlugin) {
413
+ let removedPlugins: IPlugin[] = [existingPlugin.plugin];
414
+ let unloadState: ITelemetryUnloadState = {
415
+ reason: TelemetryUnloadReason.PluginReplace,
416
+ isAsync: isAsync
417
+ };
418
+
419
+ _removePlugins(removedPlugins, unloadState, (removed) => {
420
+ if (!removed) {
421
+ // Previous plugin was successfully removed or was not installed
422
+ addCb && addCb(false);
423
+ } else {
424
+ _addPlugin(true);
425
+ }
426
+ });
427
+ } else {
428
+ _addPlugin(false);
429
+ }
430
+ };
431
+
432
+ _self.evtNamespace = (): string => {
433
+ return _evtNamespace;
434
+ };
435
+
436
+ // Create the addUnloadCb
437
+ proxyFunctionAs(_self, "addUnloadCb", () => _unloadHandlers, "add");
438
+
314
439
  function _initDefaults() {
315
440
  _isInitialized = false;
316
441
 
317
442
  // Use a default logger so initialization errors are not dropped on the floor with full logging
318
- _self.logger = new DiagnosticLogger({ loggingLevelConsole: LoggingSeverity.CRITICAL });
443
+ _self.logger = new DiagnosticLogger({ loggingLevelConsole: eLoggingSeverity.CRITICAL });
319
444
  _self.config = null;
320
445
  _self._extensions = [];
321
446
 
@@ -331,7 +456,14 @@ export class BaseCore implements IAppInsightsCore {
331
456
  _channelControl = null;
332
457
  _channelConfig = null;
333
458
  _channelQueue = null;
459
+ _isUnloading = false;
334
460
  _internalLogsEventName = null;
461
+ _evtNamespace = createUniqueNamespace("AIBaseCore", true);
462
+ _unloadHandlers = createUnloadHandlerContainer();
463
+ }
464
+
465
+ function _createTelCtx(): IProcessTelemetryContext {
466
+ return createProcessTelemetryContext(_getPluginChain(), _self.config, _self);
335
467
  }
336
468
 
337
469
  // Initialize or Re-initialize the plugins
@@ -347,7 +479,25 @@ export class BaseCore implements IAppInsightsCore {
347
479
 
348
480
  // Initialize the Channel Queues and the channel plugins first
349
481
  _channelQueue = objFreeze(createChannelQueues(_channelConfig, allExtensions, config, _self));
350
- _channelControl = createChannelControllerPlugin(_channelQueue, _self);
482
+ if (_channelControl) {
483
+ // During add / remove of a plugin this may get called again, so don't re-add if already present
484
+ // But we also want the controller as the last, so remove if already present
485
+ // And reusing the existing instance, just in case an installed plugin has a reference and
486
+ // is using it.
487
+ let idx = allExtensions.indexOf(_channelControl);
488
+ if (idx !== -1) {
489
+ allExtensions.splice(idx, 1);
490
+ }
491
+
492
+ idx = _coreExtensions.indexOf(_channelControl);
493
+ if (idx !== -1) {
494
+ _coreExtensions.splice(idx, 1);
495
+ }
496
+
497
+ (_channelControl as IInternalChannelController)._setQueue(_channelQueue);
498
+ } else {
499
+ _channelControl = createChannelControllerPlugin(_channelQueue, _self);
500
+ }
351
501
 
352
502
  // Add on "channelController" as the last "plugin"
353
503
  allExtensions.push(_channelControl);
@@ -359,7 +509,7 @@ export class BaseCore implements IAppInsightsCore {
359
509
  // Initialize the controls
360
510
  _channelControl.initialize(config, _self, allExtensions);
361
511
 
362
- initializePlugins(_self.getProcessTelContext(), allExtensions);
512
+ initializePlugins(_createTelCtx(), allExtensions);
363
513
 
364
514
  // Now reset the extensions to just those being managed by Basecore
365
515
  _self._extensions = objFreeze(sortPlugins(_coreExtensions || [])).slice();
@@ -370,15 +520,43 @@ export class BaseCore implements IAppInsightsCore {
370
520
  let thePlugin: IPlugin = null;
371
521
 
372
522
  arrForEach(_self._extensions, (ext: any) => {
373
- if (ext.identifier === pluginIdentifier) {
523
+ if (ext.identifier === pluginIdentifier && ext !== _channelControl && ext !== _telemetryInitializerPlugin) {
374
524
  thePlugin = ext;
375
525
  return -1;
376
526
  }
377
527
  });
378
528
 
529
+ if (!thePlugin && _channelControl) {
530
+ // Check the channel Controller
531
+ thePlugin = _channelControl.getChannel(pluginIdentifier);
532
+ }
533
+
379
534
  if (thePlugin) {
380
535
  theExt = {
381
- plugin: thePlugin as T
536
+ plugin: thePlugin as T,
537
+ setEnabled: (enabled: boolean) => {
538
+ _getPluginState(thePlugin)[strDisabled] = !enabled;
539
+ },
540
+ isEnabled: () => {
541
+ let pluginState = _getPluginState(thePlugin);
542
+ return !pluginState[strTeardown] && !pluginState[strDisabled];
543
+ },
544
+ remove: (isAsync: boolean = true, removeCb?: (removed?: boolean) => void): void => {
545
+ let pluginsToRemove: IPlugin[] = [thePlugin];
546
+ let unloadState: ITelemetryUnloadState = {
547
+ reason: TelemetryUnloadReason.PluginUnload,
548
+ isAsync: isAsync
549
+ };
550
+
551
+ _removePlugins(pluginsToRemove, unloadState, (removed) => {
552
+ if (removed) {
553
+ // Re-Initialize the plugin chain
554
+ _initPluginChain(_self.config);
555
+ }
556
+
557
+ removeCb && removeCb(removed);
558
+ });
559
+ }
382
560
  }
383
561
  }
384
562
 
@@ -389,8 +567,11 @@ export class BaseCore implements IAppInsightsCore {
389
567
  if (!_pluginChain) {
390
568
  // copy the collection of extensions
391
569
  let extensions = (_coreExtensions || []).slice();
392
-
393
- extensions.push(_telemetryInitializerPlugin);
570
+
571
+ // During add / remove this may get called again, so don't readd if already present
572
+ if (extensions.indexOf(_telemetryInitializerPlugin) === -1) {
573
+ extensions.push(_telemetryInitializerPlugin);
574
+ }
394
575
 
395
576
  _pluginChain = createTelemetryProxyChain(sortPlugins(extensions), _self.config, _self);
396
577
  }
@@ -398,6 +579,55 @@ export class BaseCore implements IAppInsightsCore {
398
579
  return _pluginChain;
399
580
  }
400
581
 
582
+ function _removePlugins(thePlugins: IPlugin[], unloadState: ITelemetryUnloadState, removeComplete: (removed: boolean) => void) {
583
+
584
+ if (thePlugins && thePlugins.length > 0) {
585
+ let unloadChain = createTelemetryProxyChain(thePlugins, _self.config, _self);
586
+ let unloadCtx = createProcessTelemetryUnloadContext(unloadChain, _self.config, _self);
587
+
588
+ unloadCtx.onComplete(() => {
589
+ let removed = false;
590
+
591
+ // Remove the listed config extensions
592
+ let newConfigExtensions: IPlugin[] = [];
593
+ arrForEach(_configExtensions, (plugin, idx) => {
594
+ if (!_isPluginPresent(plugin, thePlugins)) {
595
+ newConfigExtensions.push(plugin);
596
+ } else {
597
+ removed = true;
598
+ }
599
+ });
600
+
601
+ _configExtensions = newConfigExtensions;
602
+
603
+ // Re-Create the channel config
604
+ let newChannelConfig: IChannelControls[][] = [];
605
+ if (_channelConfig) {
606
+ arrForEach(_channelConfig, (queue, idx) => {
607
+ let newQueue: IChannelControls[] = [];
608
+ arrForEach(queue, (channel) => {
609
+ if (!_isPluginPresent(channel, thePlugins)) {
610
+ newQueue.push(channel);
611
+ } else {
612
+ removed = true;
613
+ }
614
+ });
615
+
616
+ newChannelConfig.push(newQueue);
617
+ });
618
+
619
+ _channelConfig = newChannelConfig;
620
+ }
621
+
622
+ removeComplete && removeComplete(removed);
623
+ });
624
+
625
+ unloadCtx.processNext(unloadState);
626
+ } else {
627
+ removeComplete(false);
628
+ }
629
+ }
630
+
401
631
  function _flushInternalLogs() {
402
632
  let queue: _InternalLogMessage[] = _self.logger ? _self.logger.queue : [];
403
633
  if (queue) {
@@ -420,13 +650,13 @@ export class BaseCore implements IAppInsightsCore {
420
650
 
421
651
  if (config.disableDbgExt === true && _debugListener) {
422
652
  // Remove any previously loaded debug listener
423
- _notificationManager.removeNotificationListener(_debugListener);
653
+ _notificationManager[strRemoveNotificationListener](_debugListener);
424
654
  _debugListener = null;
425
655
  }
426
656
 
427
657
  if (_notificationManager && !_debugListener && config.disableDbgExt !== true) {
428
658
  _debugListener = getDebugListener(config);
429
- _notificationManager.addNotificationListener(_debugListener);
659
+ _notificationManager[strAddNotificationListener](_debugListener);
430
660
  }
431
661
  }
432
662
 
@@ -441,6 +671,21 @@ export class BaseCore implements IAppInsightsCore {
441
671
  setValue(_self.config, "createPerfMgr", _createPerfManager);
442
672
  }
443
673
  }
674
+
675
+ function _initExtConfig(config: IConfiguration) {
676
+ let extConfig = getSetValue(config, strExtensionConfig);
677
+ extConfig.NotificationManager = _notificationManager;
678
+ }
679
+
680
+ function _logOrThrowError(message: string) {
681
+ let logger = _self.logger;
682
+ if (logger) {
683
+ // there should always be a logger
684
+ logger.throwInternal(eLoggingSeverity.WARNING, _eInternalMessageId.PluginException, message);
685
+ } else {
686
+ throwError(message);
687
+ }
688
+ }
444
689
  });
445
690
  }
446
691
 
@@ -539,10 +784,44 @@ export class BaseCore implements IAppInsightsCore {
539
784
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
540
785
  }
541
786
 
787
+ /**
788
+ * Unload and Tear down the SDK and any initialized plugins, after calling this the SDK will be considered
789
+ * to be un-initialized and non-operational, re-initializing the SDK should only be attempted if the previous
790
+ * unload call return `true` stating that all plugins reported that they also unloaded, the recommended
791
+ * approach is to create a new instance and initialize that instance.
792
+ * This is due to possible unexpected side effects caused by plugins not supporting unload / teardown, unable
793
+ * to successfully remove any global references or they may just be completing the unload process asynchronously.
794
+ */
795
+ public unload(isAsync?: boolean, unloadComplete?: () => void): void {
796
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
797
+ return null;
798
+ }
799
+
542
800
  public getPlugin<T extends IPlugin = IPlugin>(pluginIdentifier: string): ILoadedPlugin<T> {
543
801
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
544
802
  return null;
545
803
  }
804
+
805
+ public addPlugin<T extends IPlugin = ITelemetryPlugin>(plugin: T, replaceExisting: boolean, doAsync: boolean, addCb?: (added?: boolean) => void): void {
806
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
807
+ }
808
+
809
+ /**
810
+ * Returns the unique event namespace that should be used
811
+ */
812
+ public evtNamespace(): string {
813
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
814
+ return null;
815
+ }
816
+
817
+ /**
818
+ * Add an unload handler that will be called when the SDK is being unloaded
819
+ * @param handler - the handler
820
+ */
821
+ public addUnloadCb(handler: UnloadHandler): void {
822
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
823
+ }
824
+
546
825
  protected releaseQueue() {
547
826
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
548
827
  }