@microsoft/applicationinsights-core-js 2.8.0-beta.2203-01 → 2.8.0-beta.2203-04

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
@@ -0,0 +1,26 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved.
2
+ // Licensed under the MIT License.
3
+
4
+ // Note: DON'T Export these const from the package as we are still targeting ES3 this will export a mutable variables that someone could change!!!
5
+
6
+ export const strEmpty = "";
7
+ export const strProcessTelemetry = "processTelemetry";
8
+ export const strPriority = "priority";
9
+ export const strSetNextPlugin = "setNextPlugin";
10
+ export const strIsInitialized = "isInitialized";
11
+ export const strTeardown = "teardown";
12
+ export const strCore = "core";
13
+ export const strUpdate = "update";
14
+ export const strDisabled = "disabled";
15
+ export const strDoTeardown = "_doTeardown";
16
+ export const strProcessNext = "processNext";
17
+ export const strResume = "resume";
18
+ export const strPause = "pause";
19
+ export const strNotificationListener = "NotificationListener";
20
+ export const strAddNotificationListener = "add" + strNotificationListener;
21
+ export const strRemoveNotificationListener = "remove" + strNotificationListener;
22
+
23
+ export const strEventsSent = "eventsSent";
24
+ export const strEventsDiscarded = "eventsDiscarded";
25
+ export const strEventsSendRequest = "eventsSendRequest";
26
+ export const strPerfEvent = "perfEvent";
@@ -7,11 +7,7 @@ import { INotificationManager } from "../JavaScriptSDK.Interfaces/INotificationM
7
7
  import { IPerfEvent } from "../JavaScriptSDK.Interfaces/IPerfEvent";
8
8
  import dynamicProto from "@microsoft/dynamicproto-js";
9
9
  import { arrForEach, arrIndexOf } from "./HelperFuncs";
10
-
11
- const strEventsSent = "eventsSent";
12
- const strEventsDiscarded = "eventsDiscarded";
13
- const strEventsSendRequest = "eventsSendRequest";
14
- const strPerfEvent = "perfEvent";
10
+ import { strAddNotificationListener, strEventsDiscarded, strEventsSendRequest, strEventsSent, strPerfEvent, strRemoveNotificationListener } from "./InternalConstants";
15
11
 
16
12
  function _runListeners(listeners: INotificationListener[], name: string, isAsync: boolean, callback: (listener: INotificationListener) => void) {
17
13
  arrForEach(listeners, (listener) => {
@@ -39,7 +35,7 @@ export class NotificationManager implements INotificationManager {
39
35
  let perfEvtsSendAll = !!(config ||{}).perfEvtsSendAll;
40
36
 
41
37
  dynamicProto(NotificationManager, this, (_self) => {
42
- _self.addNotificationListener = (listener: INotificationListener): void => {
38
+ _self[strAddNotificationListener] = (listener: INotificationListener): void => {
43
39
  _self.listeners.push(listener);
44
40
  };
45
41
 
@@ -47,7 +43,7 @@ export class NotificationManager implements INotificationManager {
47
43
  * Removes all instances of the listener.
48
44
  * @param {INotificationListener} listener - AWTNotificationListener to remove.
49
45
  */
50
- _self.removeNotificationListener = (listener: INotificationListener): void => {
46
+ _self[strRemoveNotificationListener] = (listener: INotificationListener): void => {
51
47
  let index: number = arrIndexOf(_self.listeners, listener);
52
48
  while (index > -1) {
53
49
  _self.listeners.splice(index, 1);
@@ -59,7 +55,7 @@ export class NotificationManager implements INotificationManager {
59
55
  * Notification for events sent.
60
56
  * @param {ITelemetryItem[]} events - The array of events that have been sent.
61
57
  */
62
- _self.eventsSent = (events: ITelemetryItem[]): void => {
58
+ _self[strEventsSent] = (events: ITelemetryItem[]): void => {
63
59
  _runListeners(_self.listeners, strEventsSent, true, (listener) => {
64
60
  listener[strEventsSent](events);
65
61
  });
@@ -71,7 +67,7 @@ export class NotificationManager implements INotificationManager {
71
67
  * @param {number} reason - The reason for which the SDK discarded the events. The EventsDiscardedReason
72
68
  * constant should be used to check the different values.
73
69
  */
74
- _self.eventsDiscarded = (events: ITelemetryItem[], reason: number): void => {
70
+ _self[strEventsDiscarded] = (events: ITelemetryItem[], reason: number): void => {
75
71
  _runListeners(_self.listeners, strEventsDiscarded, true, (listener) => {
76
72
  listener[strEventsDiscarded](events, reason);
77
73
  });
@@ -82,13 +78,13 @@ export class NotificationManager implements INotificationManager {
82
78
  * @param {number} sendReason - The reason why the event batch is being sent.
83
79
  * @param {boolean} isAsync - A flag which identifies whether the requests are being sent in an async or sync manner.
84
80
  */
85
- _self.eventsSendRequest = (sendReason: number, isAsync: boolean): void => {
81
+ _self[strEventsSendRequest] = (sendReason: number, isAsync: boolean): void => {
86
82
  _runListeners(_self.listeners, strEventsSendRequest, isAsync, (listener) => {
87
83
  listener[strEventsSendRequest](sendReason, isAsync);
88
84
  });
89
85
  };
90
86
 
91
- _self.perfEvent = (perfEvent?: IPerfEvent): void => {
87
+ _self[strPerfEvent] = (perfEvent?: IPerfEvent): void => {
92
88
  if (perfEvent) {
93
89
 
94
90
  // Send all events or only parent events
@@ -6,14 +6,17 @@ import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore";
6
6
  import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
7
7
  import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
8
8
  import { IPlugin, ITelemetryPlugin } from "../JavaScriptSDK.Interfaces/ITelemetryPlugin";
9
- import { GetExtCfgMergeType, IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
9
+ import { GetExtCfgMergeType, IBaseProcessingContext, IProcessTelemetryContext, IProcessTelemetryUnloadContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
10
10
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
11
11
  import { safeGetLogger } from "./DiagnosticLogger";
12
- import { arrForEach, isArray, isFunction, isNullOrUndefined, isObject, objExtend, objForEachKey, objFreeze, objKeys, proxyFunctions } from "./HelperFuncs";
12
+ import { arrForEach, isArray, isFunction, isNullOrUndefined, isObject, isUndefined, objExtend, objForEachKey, objFreeze, objKeys, proxyFunctions } from "./HelperFuncs";
13
13
  import { doPerf } from "./PerfManager";
14
- import { LoggingSeverity, _InternalMessageId } from "../JavaScriptSDK.Enums/LoggingEnums";
14
+ import { eLoggingSeverity, _eInternalMessageId } from "../JavaScriptSDK.Enums/LoggingEnums";
15
15
  import { dumpObj } from "./EnvUtils";
16
+ import { strCore, strDisabled, strEmpty, strIsInitialized, strTeardown } from "./InternalConstants";
16
17
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
18
+ import { ITelemetryUnloadState } from "../JavaScriptSDK.Interfaces/ITelemetryUnloadState";
19
+ import { _getPluginState } from "./TelemetryHelpers";
17
20
 
18
21
  const strTelemetryPluginChain = "TelemetryPluginChain";
19
22
  const strHasRunFlags = "_hasRun";
@@ -21,11 +24,24 @@ const strGetTelCtx = "_getTelCtx";
21
24
 
22
25
  let _chainId = 0;
23
26
 
27
+ interface OnCompleteCallback {
28
+ func: Function;
29
+ self: any; // This for the function
30
+ args: any[]; // Additional arguments for the function
31
+ }
32
+
24
33
  interface IInternalTelemetryPluginChain extends ITelemetryPluginChain {
25
34
  _id: string;
26
35
  _setNext: (nextPlugin: IInternalTelemetryPluginChain) => void;
27
36
  }
28
37
 
38
+ interface IInternalContext<T extends IBaseProcessingContext> {
39
+ _next: () => ITelemetryPluginChain,
40
+
41
+ // The public context that will be exposed
42
+ ctx: T
43
+ }
44
+
29
45
  function _getNextProxyStart(proxy: ITelemetryPluginChain, config: IConfiguration, core:IAppInsightsCore, startAt: IPlugin): ITelemetryPluginChain {
30
46
  while (proxy) {
31
47
  if (proxy.getPlugin() === startAt) {
@@ -40,64 +56,86 @@ function _getNextProxyStart(proxy: ITelemetryPluginChain, config: IConfiguration
40
56
  }
41
57
 
42
58
  /**
43
- * Creates a new Telemetry Item context with the current config, core and plugin execution chain
44
- * @param plugins - The plugin instances that will be executed
45
- * @param config - The current config
46
- * @param core - The current core instance
59
+ * @ignore
60
+ * @param telemetryChain
61
+ * @param config
62
+ * @param core
63
+ * @param startAt - Identifies the next plugin to execute, if null there is no "next" plugin and if undefined it should assume the start of the chain
64
+ * @returns
47
65
  */
48
- export function createProcessTelemetryContext(telemetryChain: ITelemetryPluginChain, config: IConfiguration, core:IAppInsightsCore, startAt?: IPlugin): IProcessTelemetryContext {
49
- let _nextProxy: ITelemetryPluginChain = null; // Null == No next plugin
50
- let _onComplete: () => void = null;
51
-
52
- // There is no next element (null === last element) vs not defined (undefined)
53
- // We have a proxy chain object
54
- if (startAt) {
55
- // We have a special case where we want to start execution from this specific plugin
56
- _nextProxy = _getNextProxyStart(telemetryChain, config, core, startAt);
57
- } else {
58
- // Reuse the existing telemetry plugin chain (normal execution case)
59
- _nextProxy = telemetryChain;
66
+ function _createInternalContext<T extends IBaseProcessingContext>(telemetryChain: ITelemetryPluginChain, config: IConfiguration, core:IAppInsightsCore, startAt?: IPlugin): IInternalContext<T> {
67
+ // We have a special case where we want to start execution from this specific plugin
68
+ // or we simply reuse the existing telemetry plugin chain (normal execution case)
69
+ let _nextProxy: ITelemetryPluginChain = null; // By Default set as no next plugin
70
+ let _onComplete: OnCompleteCallback[] = [];
71
+
72
+ if (startAt !== null) {
73
+ // There is no next element (null) vs not defined (undefined) so use the full chain
74
+ _nextProxy = startAt ? _getNextProxyStart(telemetryChain, config, core, startAt) : telemetryChain;
60
75
  }
61
76
 
62
- let context: IProcessTelemetryContext = {
63
- core: () => {
64
- return core;
65
- },
66
- diagLog: () => {
67
- return safeGetLogger(core, config);
68
- },
69
- getCfg: () => {
70
- return config;
71
- },
72
- getExtCfg: _getExtCfg,
73
- getConfig: _getConfig,
74
- hasNext: () => {
75
- return _nextProxy != null;
76
- },
77
- getNext: () => {
78
- return _nextProxy;
79
- },
80
- setNext: (nextPlugin:ITelemetryPluginChain) => {
81
- _nextProxy = nextPlugin;
82
- },
83
- processNext: (env: ITelemetryItem) => {
84
- _processChain((nextPlugin) => {
85
- // Run the next plugin which will call "processNext()"
86
- nextPlugin.processTelemetry(env, context);
77
+ let context: IInternalContext<T> = {
78
+ _next: _moveNext,
79
+ ctx: {
80
+ core: () => { return core },
81
+ diagLog: () => {
82
+ return safeGetLogger(core, config);
83
+ },
84
+ getCfg: () => {
85
+ return config;
86
+ },
87
+ getExtCfg: _getExtCfg,
88
+ getConfig: _getConfig,
89
+ hasNext: () => {
90
+ return !!_nextProxy;
91
+ },
92
+ getNext: () => {
93
+ return _nextProxy;
94
+ },
95
+ setNext: (nextPlugin:ITelemetryPluginChain) => {
96
+ _nextProxy = nextPlugin;
97
+ },
98
+ iterate: _iterateChain,
99
+ onComplete: _addOnComplete
100
+ } as T
101
+ };
102
+
103
+ function _addOnComplete(onComplete: Function, that?: any, ...args: any[]) {
104
+ if (onComplete) {
105
+ _onComplete.push({
106
+ func: onComplete,
107
+ self: !isUndefined(that) ? that : context.ctx,
108
+ args: args
87
109
  });
88
- },
89
- iterate: _iterateChain,
90
- createNew: (plugins: IPlugin[] | ITelemetryPluginChain = null, startAt?: IPlugin) => {
91
- if (isArray(plugins)) {
92
- plugins = createTelemetryProxyChain(plugins, config, core, startAt);
93
- }
110
+ }
111
+ }
94
112
 
95
- return createProcessTelemetryContext(plugins || _nextProxy, config, core, startAt);
96
- },
97
- onComplete: (onComplete: () => void) => {
98
- _onComplete = onComplete;
113
+ function _moveNext() {
114
+ let nextProxy = _nextProxy;
115
+
116
+ // Automatically move to the next plugin
117
+ _nextProxy = nextProxy ? nextProxy.getNext() : null;
118
+
119
+ if (!nextProxy) {
120
+ let onComplete = _onComplete;
121
+ if (onComplete && onComplete.length > 0) {
122
+ arrForEach(onComplete, (completeDetails) => {
123
+ try {
124
+ completeDetails.func.call(completeDetails.self, completeDetails.args);
125
+ } catch (e) {
126
+ core.logger.throwInternal(
127
+ eLoggingSeverity.WARNING,
128
+ _eInternalMessageId.PluginException,
129
+ "Unexpected Exception during onComplete - " + dumpObj(e));
130
+ }
131
+ });
132
+
133
+ _onComplete = [];
134
+ }
99
135
  }
100
- };
136
+
137
+ return nextProxy;
138
+ }
101
139
 
102
140
  function _getExtCfg<T>(identifier: string, defaultValue: T|any = {}, mergeDefault: GetExtCfgMergeType = GetExtCfgMergeType.None) {
103
141
  let theConfig: T;
@@ -147,36 +185,87 @@ export function createProcessTelemetryContext(telemetryChain: ITelemetryPluginCh
147
185
  return !isNullOrUndefined(theValue) ? theValue : defaultValue;
148
186
  }
149
187
 
150
- function _processChain(cb: (nextPlugin: ITelemetryPluginChain) => void) {
151
- let nextPlugin = _nextProxy;
152
-
153
- if (nextPlugin) {
154
- // Automatically move to the next plugin
155
- _nextProxy = nextPlugin.getNext();
156
- cb(nextPlugin);
157
- } else {
158
- if (_onComplete) {
159
- _onComplete();
160
- _onComplete = null;
188
+ function _iterateChain<T extends ITelemetryPlugin = ITelemetryPlugin>(cb: (plugin: T) => void) {
189
+ // Keep processing until we reach the end of the chain
190
+ let nextPlugin: ITelemetryPluginChain;
191
+ while(!!(nextPlugin = context._next())) {
192
+ let plugin = nextPlugin.getPlugin();
193
+ if (plugin) {
194
+ // callback with the current on
195
+ cb(plugin as T);
161
196
  }
162
197
  }
163
198
  }
164
199
 
165
- function _iterateChain<T extends ITelemetryPlugin = ITelemetryPlugin>(cb: (plugin: T) => void) {
166
- while(_nextProxy) {
167
- _processChain((nextPlugin: ITelemetryPluginChain) => {
168
- let plugin = nextPlugin.getPlugin();
169
- if (plugin) {
170
- // callback with the current on
171
- cb(plugin as T);
172
- }
173
- });
200
+ return context;
201
+ }
202
+
203
+ /**
204
+ * Creates a new Telemetry Item context with the current config, core and plugin execution chain
205
+ * @param plugins - The plugin instances that will be executed
206
+ * @param config - The current config
207
+ * @param core - The current core instance
208
+ * @param startAt - Identifies the next plugin to execute, if null there is no "next" plugin and if undefined it should assume the start of the chain
209
+ */
210
+ export function createProcessTelemetryContext(telemetryChain: ITelemetryPluginChain, config: IConfiguration, core:IAppInsightsCore, startAt?: IPlugin): IProcessTelemetryContext {
211
+ let internalContext: IInternalContext<IProcessTelemetryContext> = _createInternalContext<IProcessTelemetryContext>(telemetryChain, config, core, startAt);
212
+ let context = internalContext.ctx;
213
+
214
+ function _processNext(env: ITelemetryItem) {
215
+ let nextPlugin: ITelemetryPluginChain = internalContext._next();
216
+ // Run the next plugin which will call "processNext()"
217
+ nextPlugin && nextPlugin.processTelemetry(env, context);
218
+
219
+ return !nextPlugin;
220
+ }
221
+
222
+ function _createNew(plugins: IPlugin[] | ITelemetryPluginChain = null, startAt?: IPlugin) {
223
+ if (isArray(plugins)) {
224
+ plugins = createTelemetryProxyChain(plugins, config, core, startAt);
225
+ }
226
+
227
+ return createProcessTelemetryContext(plugins || context.getNext(), config, core, startAt);
228
+ }
229
+
230
+ context.processNext = _processNext;
231
+ context.createNew = _createNew;
232
+
233
+ return context;
234
+ }
235
+
236
+ /**
237
+ * Creates a new Telemetry Item context with the current config, core and plugin execution chain for handling the unloading of the chain
238
+ * @param plugins - The plugin instances that will be executed
239
+ * @param config - The current config
240
+ * @param core - The current core instance
241
+ * @param startAt - Identifies the next plugin to execute, if null there is no "next" plugin and if undefined it should assume the start of the chain
242
+ */
243
+ export function createProcessTelemetryUnloadContext(telemetryChain: ITelemetryPluginChain, config: IConfiguration, core:IAppInsightsCore, startAt?: IPlugin): IProcessTelemetryUnloadContext {
244
+ let internalContext: IInternalContext<IProcessTelemetryUnloadContext> = _createInternalContext<IProcessTelemetryUnloadContext>(telemetryChain, config, core, startAt);
245
+ let context = internalContext.ctx;
246
+
247
+ function _processNext(unloadState: ITelemetryUnloadState) {
248
+ let nextPlugin: ITelemetryPluginChain = internalContext._next();
249
+ nextPlugin && nextPlugin.unload(context, unloadState);
250
+
251
+ return !nextPlugin;
252
+ }
253
+
254
+ function _createNew(plugins: IPlugin[] | ITelemetryPluginChain = null, startAt?: IPlugin): IProcessTelemetryUnloadContext {
255
+ if (isArray(plugins)) {
256
+ plugins = createTelemetryProxyChain(plugins, config, core, startAt);
174
257
  }
258
+
259
+ return createProcessTelemetryUnloadContext(plugins || context.getNext(), config, core, startAt);
175
260
  }
176
261
 
262
+ context.processNext = _processNext;
263
+ context.createNew = _createNew
264
+
177
265
  return context;
178
266
  }
179
267
 
268
+
180
269
  /**
181
270
  * Creates an execution chain from the array of plugins
182
271
  * @param plugins - The array of plugins that will be executed in this order
@@ -250,34 +339,38 @@ export function createTelemetryPluginProxy(plugin: ITelemetryPlugin, config: ICo
250
339
  return nextProxy;
251
340
  },
252
341
  processTelemetry: _processTelemetry,
342
+ unload: _unloadPlugin,
253
343
  _id: chainId,
254
344
  _setNext: (nextPlugin: IInternalTelemetryPluginChain) => {
255
345
  nextProxy = nextPlugin;
256
346
  }
257
347
  };
258
348
 
259
- function _processChain(
260
- itemCtx: IProcessTelemetryContext,
261
- processPluginFn: (itemCtx: IProcessTelemetryContext) => boolean,
262
- processProxyFn: (itemCtx: IProcessTelemetryContext) => void,
263
- name: string,
264
- details: () => any,
265
- isAsync: boolean) {
349
+ function _getTelCtx() {
350
+ let itemCtx: IProcessTelemetryContext;
266
351
 
267
- // Make sure we have a context
268
- if (!itemCtx) {
269
- // Looks like a plugin didn't pass the (optional) context, so create a new one
270
- if (plugin && isFunction(plugin[strGetTelCtx])) {
271
- // This plugin extends from the BaseTelemetryPlugin so lets use it
272
- itemCtx = plugin[strGetTelCtx]();
273
- }
352
+ // Looks like a plugin didn't pass the (optional) context, so create a new one
353
+ if (plugin && isFunction(plugin[strGetTelCtx])) {
354
+ // This plugin extends from the BaseTelemetryPlugin so lets use it
355
+ itemCtx = plugin[strGetTelCtx]();
356
+ }
274
357
 
275
- if (!itemCtx) {
276
- // Create a temporary one
277
- itemCtx = createProcessTelemetryContext(proxyChain, config, core);
278
- }
358
+ if (!itemCtx) {
359
+ // Create a temporary one
360
+ itemCtx = createProcessTelemetryContext(proxyChain, config, core);
279
361
  }
280
362
 
363
+ return itemCtx;
364
+ }
365
+
366
+ function _processChain<T extends IBaseProcessingContext>(
367
+ itemCtx: T,
368
+ processPluginFn: (itemCtx: T) => boolean,
369
+ name: string,
370
+ details: () => any,
371
+ isAsync: boolean) {
372
+
373
+ let hasRun = false;
281
374
  let identifier = plugin ? plugin.identifier : strTelemetryPluginChain;
282
375
  let hasRunContext = itemCtx[strHasRunFlags];
283
376
  if (!hasRunContext) {
@@ -285,18 +378,17 @@ export function createTelemetryPluginProxy(plugin: ITelemetryPlugin, config: ICo
285
378
  hasRunContext = itemCtx[strHasRunFlags] = {};
286
379
  }
287
380
 
288
- doPerf(itemCtx.core(), () => identifier + ":" + name, () => {
289
- // Mark this component as having run
290
- hasRunContext[chainId] = true;
291
- let hasRun = false;
381
+ // Ensure that we keep the context in sync
382
+ itemCtx.setNext(nextProxy);
292
383
 
293
- // Ensure that we keep the context in sync
294
- itemCtx.setNext(nextProxy);
384
+ if (plugin) {
385
+ doPerf(itemCtx[strCore](), () => identifier + ":" + name, () => {
386
+ // Mark this component as having run
387
+ hasRunContext[chainId] = true;
295
388
 
296
- if (plugin) {
297
389
  try {
298
390
  // Set a flag on the next plugin so we know if it was attempted to be executed
299
- let nextId = nextProxy ? nextProxy._id : "";
391
+ let nextId = nextProxy ? nextProxy._id : strEmpty;
300
392
  if (nextId) {
301
393
  hasRunContext[nextId] = false;
302
394
  }
@@ -314,24 +406,27 @@ export function createTelemetryPluginProxy(plugin: ITelemetryPlugin, config: ICo
314
406
  // Either we have no next plugin or the current one did not attempt to call the next plugin
315
407
  // Which means the current one is the root of the failure so log/report this failure
316
408
  itemCtx.diagLog().throwInternal(
317
- LoggingSeverity.CRITICAL,
318
- _InternalMessageId.PluginException,
409
+ eLoggingSeverity.CRITICAL,
410
+ _eInternalMessageId.PluginException,
319
411
  "Plugin [" + plugin.identifier + "] failed during " + name + " - " + dumpObj(error) + ", run flags: " + dumpObj(hasRunContext));
320
412
  }
321
413
  }
322
- }
323
-
324
- if (nextProxy && !hasRun) {
325
- // The underlying plugin is not defined, but we still want the next plugin to be executed.
326
- // So rather than leave the pipeline dead in the water we call the next plugin
327
- processProxyFn(itemCtx);
328
- }
329
- }, details, isAsync);
414
+ }, details, isAsync);
415
+ }
416
+
417
+ return hasRun;
330
418
  }
331
419
 
332
420
  function _processTelemetry(env: ITelemetryItem, itemCtx: IProcessTelemetryContext) {
333
- _processChain(itemCtx, (itemCtx: IProcessTelemetryContext) => {
334
- if (!hasProcessTelemetry) {
421
+ itemCtx = itemCtx || _getTelCtx();
422
+
423
+ function _callProcessTelemetry(itemCtx: IProcessTelemetryContext) {
424
+ if (!plugin || !hasProcessTelemetry) {
425
+ return false;
426
+ }
427
+
428
+ let pluginState = _getPluginState(plugin);
429
+ if (pluginState[strTeardown] || pluginState[strDisabled]) {
335
430
  return false;
336
431
  }
337
432
 
@@ -345,14 +440,46 @@ export function createTelemetryPluginProxy(plugin: ITelemetryPlugin, config: ICo
345
440
 
346
441
  plugin.processTelemetry(env, itemCtx);
347
442
 
443
+ // Process Telemetry is expected to call itemCtx.processNext() or nextPlugin.processTelemetry()
348
444
  return true;
349
- },
350
- (itemCtx: IProcessTelemetryContext) => {
351
- // The underlying plugin is either not defined or does not have a processTelemetry implementation
445
+ }
446
+
447
+ if (!_processChain(itemCtx, _callProcessTelemetry, "processTelemetry", () => ({ item: env }), !((env as any).sync))) {
448
+ // The underlying plugin is either not defined, not enabled or does not have a processTelemetry implementation
352
449
  // so we still want the next plugin to be executed.
353
- nextProxy.processTelemetry(env, itemCtx);
354
- },
355
- "processTelemetry", () => ({ item: env }), !((env as any).sync));
450
+ itemCtx.processNext(env);
451
+ }
452
+ }
453
+
454
+ function _unloadPlugin(unloadCtx: IProcessTelemetryUnloadContext, unloadState: ITelemetryUnloadState) {
455
+
456
+ function _callTeardown() {
457
+ // Setting default of hasRun as false so the proxyProcessFn() is called as teardown() doesn't have to exist or call unloadNext().
458
+ let hasRun = false;
459
+ if (plugin) {
460
+ let pluginState = _getPluginState(plugin);
461
+ let pluginCore = plugin[strCore] || pluginState.core;
462
+ // Only teardown the plugin if it was initialized by the current core (i.e. It's not a shared plugin)
463
+ if (plugin && (!pluginCore || pluginCore === unloadCtx[strCore]()) && !pluginState[strTeardown]) {
464
+ // Handle plugins that don't extend from the BaseTelemetryPlugin
465
+ pluginState[strCore] = null;
466
+ pluginState[strTeardown] = true;
467
+ pluginState[strIsInitialized] = false;
468
+
469
+ if (plugin[strTeardown] && plugin[strTeardown](unloadCtx, unloadState) === true) {
470
+ // plugin told us that it was going to (or has) call unloadCtx.processNext()
471
+ hasRun = true;
472
+ }
473
+ }
474
+ }
475
+
476
+ return hasRun;
477
+ }
478
+
479
+ if (!_processChain(unloadCtx, _callTeardown, "unload", () => {}, unloadState.isAsync)) {
480
+ // Only called if we hasRun was not true
481
+ unloadCtx.processNext(unloadState);
482
+ }
356
483
  }
357
484
 
358
485
  return objFreeze(proxyChain);
@@ -404,8 +531,9 @@ export class ProcessTelemetryContext implements IProcessTelemetryContext {
404
531
  * @param itemCtx - This is the context for the current request, ITelemetryPlugin instances
405
532
  * can optionally use this to access the current core instance or define / pass additional information
406
533
  * to later plugins (vs appending items to the telemetry item)
534
+ * @returns boolean (true) if there is no more plugins to process otherwise false or undefined (void)
407
535
  */
408
- public processNext: (env: ITelemetryItem) => void;
536
+ public processNext: (env: ITelemetryItem) => boolean | void;
409
537
 
410
538
  /**
411
539
  * Synchronously iterate over the context chain running the callback for each plugin, once
@@ -414,7 +542,6 @@ export class ProcessTelemetryContext implements IProcessTelemetryContext {
414
542
  */
415
543
  public iterate: <T extends ITelemetryPlugin = ITelemetryPlugin>(callback: (plugin: T) => void) => void;
416
544
 
417
- /**
418
545
  /**
419
546
  * Create a new context using the core and config from the current instance
420
547
  * @param plugins - The execution order to process the plugins, if null or not supplied
@@ -2,6 +2,7 @@
2
2
  // Licensed under the MIT License.
3
3
  import { getCrypto, getMsCrypto, isIE } from "./EnvUtils";
4
4
  import { dateNow } from "./HelperFuncs";
5
+ import { strEmpty } from "./InternalConstants";
5
6
 
6
7
  const UInt32Mask = 0x100000000;
7
8
  const MaxUInt32 = 0xffffffff;
@@ -127,7 +128,7 @@ export function mwcRandom32(signed?: boolean) {
127
128
  // Start with an initial random number, consuming the value in reverse byte order
128
129
  let number = random32() >>> 0; // Make sure it's a +ve number
129
130
  let chars = 0;
130
- let result = "";
131
+ let result = strEmpty;
131
132
  while (result.length < maxLength) {
132
133
  chars ++;
133
134
  result += base64chars.charAt(number & 0x3F);