@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
@@ -9,12 +9,16 @@ import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
9
9
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
10
10
  import { IPlugin, ITelemetryPlugin } from "../JavaScriptSDK.Interfaces/ITelemetryPlugin";
11
11
  import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
12
- import { IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
12
+ import { IProcessTelemetryContext, IProcessTelemetryUnloadContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
13
13
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
14
- import { createProcessTelemetryContext } from "./ProcessTelemetryContext";
15
- import { isArray, isFunction, isNullOrUndefined, setValue } from "./HelperFuncs";
14
+ import { createProcessTelemetryContext, createProcessTelemetryUnloadContext } from "./ProcessTelemetryContext";
15
+ import { arrForEach, isArray, isFunction, isNullOrUndefined, 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";
19
+ import { ITelemetryUnloadState } from "../JavaScriptSDK.Interfaces/ITelemetryUnloadState";
20
+ import { TelemetryUnloadReason } from "../JavaScriptSDK.Enums/TelemetryUnloadReason";
21
+ import { strDoTeardown, strIsInitialized, strSetNextPlugin } from "./InternalConstants";
18
22
 
19
23
  let strGetPlugin = "getPlugin";
20
24
 
@@ -73,6 +77,16 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
73
77
  */
74
78
  protected setInitialized: (isInitialized: boolean) => void;
75
79
 
80
+ /**
81
+ * Teardown / Unload hook to allow implementations to perform some additional unload operations before the BaseTelemetryPlugin
82
+ * finishes it's removal.
83
+ * @param unloadCtx - This is the context that should be used during unloading.
84
+ * @param unloadState - The details / state of the unload process, it holds details like whether it should be unloaded synchronously or asynchronously and the reason for the unload.
85
+ * @param asyncCallback - An optional callback that the plugin must call if it returns true to inform the caller that it has completed any async unload/teardown operations.
86
+ * @returns boolean - true if the plugin has or will call asyncCallback, this allows the plugin to perform any asynchronous operations.
87
+ */
88
+ protected _doTeardown?: (unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState, asyncCallback?: () => void) => void | boolean;
89
+
76
90
  constructor() {
77
91
  let _self = this; // Setting _self here as it's used outside of the dynamicProto as well
78
92
 
@@ -80,6 +94,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
80
94
  let _isinitialized: boolean;
81
95
  let _rootCtx: IProcessTelemetryContext; // Used as the root context, holding the current config and initialized core
82
96
  let _nextPlugin: ITelemetryPlugin | ITelemetryPluginChain; // Used for backward compatibility where plugins don't call the main pipeline
97
+ let _unloadHandlerContainer: IUnloadHandlerContainer;
83
98
  let _hooks: IInstrumentHook[];
84
99
 
85
100
  _initDefaults();
@@ -90,6 +105,52 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
90
105
  _setDefaults(config, core, pluginChain);
91
106
  _isinitialized = true;
92
107
  }
108
+
109
+ _self.teardown = (unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState) => {
110
+ // If this plugin has already been torn down (not operational) or is not initialized (core is not set)
111
+ // or the core being used for unload was not the same core used for initialization.
112
+ if (!_self.core || (unloadCtx && _self.core !== unloadCtx.core())) {
113
+ // Do Nothing
114
+ return;
115
+ }
116
+
117
+ let result: void | boolean;
118
+ let unloadDone = false;
119
+ let theUnloadCtx = unloadCtx || createProcessTelemetryUnloadContext(null, {}, _self.core, _nextPlugin && _nextPlugin[strGetPlugin] ? _nextPlugin[strGetPlugin]() : _nextPlugin);
120
+ let theUnloadState: ITelemetryUnloadState = unloadState || {
121
+ reason: TelemetryUnloadReason.ManualTeardown,
122
+ isAsync: false
123
+ };
124
+
125
+ function _unloadCallback() {
126
+ if (!unloadDone) {
127
+ unloadDone = true;
128
+
129
+ _unloadHandlerContainer.run(theUnloadCtx, unloadState);
130
+
131
+ // Remove all instrumentation hooks
132
+ arrForEach(_hooks, (fn) => {
133
+ fn.rm();
134
+ });
135
+ _hooks = [];
136
+
137
+ if (result === true) {
138
+ theUnloadCtx.processNext(theUnloadState);
139
+ }
140
+
141
+ _initDefaults();
142
+ }
143
+ }
144
+
145
+ if (!_self[strDoTeardown] || _self[strDoTeardown](theUnloadCtx, theUnloadState, _unloadCallback) !== true) {
146
+ _unloadCallback();
147
+ } else {
148
+ // Tell the caller that we will be calling processNext()
149
+ result = true;
150
+ }
151
+
152
+ return result;
153
+ };
93
154
 
94
155
  _self._addHook = (hooks: IInstrumentHook | IInstrumentHook[]) => {
95
156
  if (hooks) {
@@ -100,6 +161,8 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
100
161
  }
101
162
  }
102
163
  };
164
+
165
+ proxyFunctionAs(_self, "_addUnloadCb", () => _unloadHandlerContainer, "add");
103
166
  });
104
167
 
105
168
  // These are added after the dynamicProto so that are not moved to the prototype
@@ -108,7 +171,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
108
171
  return _getTelCtx(itemCtx).diagLog();
109
172
  }
110
173
 
111
- _self.isInitialized = () => {
174
+ _self[strIsInitialized] = () => {
112
175
  return _isinitialized;
113
176
  }
114
177
 
@@ -121,7 +184,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
121
184
  // should use processNext() function. If you require access to the plugin use the
122
185
  // IProcessTelemetryContext.getNext().getPlugin() while in the pipeline, Note getNext() may return null.
123
186
 
124
- _self.setNextPlugin = (next: ITelemetryPlugin | ITelemetryPluginChain) => {
187
+ _self[strSetNextPlugin] = (next: ITelemetryPlugin | ITelemetryPluginChain) => {
125
188
  _nextPlugin = next;
126
189
  };
127
190
 
@@ -182,6 +245,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
182
245
  _rootCtx = null;
183
246
  _nextPlugin = null;
184
247
  _hooks = [];
248
+ _unloadHandlerContainer = createUnloadHandlerContainer();
185
249
  }
186
250
  }
187
251
 
@@ -189,8 +253,29 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
189
253
  // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
190
254
  }
191
255
 
256
+ /**
257
+ * Tear down the plugin and remove any hooked value, the plugin should be removed so that it is no longer initialized and
258
+ * therefore could be re-initialized after being torn down. The plugin should ensure that once this has been called any further
259
+ * processTelemetry calls are ignored and it just calls the processNext() with the provided context.
260
+ * @param unloadCtx - This is the context that should be used during unloading.
261
+ * @param unloadState - The details / state of the unload process, it holds details like whether it should be unloaded synchronously or asynchronously and the reason for the unload.
262
+ * @returns boolean - true if the plugin has or will call processNext(), this for backward compatibility as previously teardown was synchronous and returned nothing.
263
+ */
264
+ public teardown(unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState): void | boolean {
265
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
266
+ return false;
267
+ }
268
+
192
269
  public abstract processTelemetry(env: ITelemetryItem, itemCtx?: IProcessTelemetryContext): void;
193
270
 
271
+ /**
272
+ * Add an unload handler that will be called when the SDK is being unloaded
273
+ * @param handler - the handler
274
+ */
275
+ protected _addUnloadCb(handler: UnloadHandler): void {
276
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
277
+ }
278
+
194
279
  /**
195
280
  * Add this hook so that it is automatically removed during unloading
196
281
  * @param hooks - The single hook or an array of IInstrumentHook objects
@@ -2,14 +2,17 @@
2
2
  // // Licensed under the MIT License.
3
3
 
4
4
  import { SendRequestReason } from "../JavaScriptSDK.Enums/SendRequestReason";
5
+ import { TelemetryUnloadReason } from "../JavaScriptSDK.Enums/TelemetryUnloadReason";
5
6
  import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore";
6
7
  import { IChannelControls } from "../JavaScriptSDK.Interfaces/IChannelControls";
7
8
  import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
8
- import { IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
9
+ import { IBaseProcessingContext, IProcessTelemetryContext, IProcessTelemetryUnloadContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
9
10
  import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
10
11
  import { IPlugin } from "../JavaScriptSDK.Interfaces/ITelemetryPlugin";
11
12
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
13
+ import { ITelemetryUnloadState } from "../JavaScriptSDK.Interfaces/ITelemetryUnloadState";
12
14
  import { arrForEach, isArray, objFreeze, throwError } from "./HelperFuncs";
15
+ import { strPause, strProcessNext, strResume, strTeardown } from "./InternalConstants";
13
16
  import { createProcessTelemetryContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
14
17
  import { initializePlugins } from "./TelemetryHelpers";
15
18
 
@@ -17,7 +20,13 @@ export const ChannelControllerPriority = 500;
17
20
  const ChannelValidationMessage = "Channel has invalid priority - ";
18
21
 
19
22
  export interface IChannelController extends IChannelControls {
20
- flush(isAsync: boolean, callBack: (flushComplete?: boolean) => void, sendReason: SendRequestReason, cbTimeout?: number): void
23
+ flush(isAsync: boolean, callBack: (flushComplete?: boolean) => void, sendReason: SendRequestReason, cbTimeout?: number): void;
24
+
25
+ getChannel<T extends IPlugin = IPlugin>(pluginIdentifier: string): T;
26
+ }
27
+
28
+ export interface IInternalChannelController extends IChannelController {
29
+ _setQueue: (channels: _IInternalChannels[]) => void;
21
30
  }
22
31
 
23
32
  export interface _IInternalChannels {
@@ -46,31 +55,29 @@ function _addChannelQueue(channelQueue: _IInternalChannels[], queue: IChannelCon
46
55
 
47
56
  export function createChannelControllerPlugin(channelQueue: _IInternalChannels[], core: IAppInsightsCore): IChannelController {
48
57
 
49
- function _getTelCtx(itemCtx: IProcessTelemetryContext) {
50
- if (!itemCtx) {
51
- // For some reason the previous plugin didn't pass down the itemCtx (perhaps an old plugin)
52
- itemCtx = createProcessTelemetryContext(null, core.config, core, null)
53
- }
54
-
55
- return itemCtx;
58
+ function _getTelCtx() {
59
+ return createProcessTelemetryContext(null, core.config, core, null)
56
60
  }
57
61
 
58
- function _processChannelQueue(itemCtx: IProcessTelemetryContext, processFn: (chainCtx: IProcessTelemetryContext) => void, onComplete?: () => void) {
59
- if (channelQueue && channelQueue.length > 0) {
60
- let waiting = channelQueue.length;
61
- arrForEach(channelQueue, (channels) => {
62
+ function _processChannelQueue<T extends IBaseProcessingContext>(theChannels: _IInternalChannels[], itemCtx: T, processFn: (chainCtx: T) => void, onComplete: () => void) {
63
+ let waiting = theChannels ? (theChannels.length + 1) : 1;
64
+
65
+ function _runChainOnComplete() {
66
+ waiting --;
67
+
68
+ if (waiting === 0) {
69
+ onComplete && onComplete();
70
+ onComplete = null;
71
+ }
72
+ }
73
+
74
+ if (waiting > 0) {
75
+ arrForEach(theChannels, (channels) => {
62
76
  // pass on to first item in queue
63
77
  if (channels && channels.queue.length > 0) {
64
78
  let channelChain = channels.chain;
65
- let chainCtx = _getTelCtx(itemCtx).createNew(channelChain);
66
- chainCtx.onComplete(() => {
67
- waiting --;
68
-
69
- if (waiting === 0) {
70
- onComplete && onComplete();
71
- onComplete = null;
72
- }
73
- });
79
+ let chainCtx = itemCtx.createNew(channelChain) as T;
80
+ chainCtx.onComplete(_runChainOnComplete);
74
81
 
75
82
  // Cause this chain to start processing
76
83
  processFn(chainCtx);
@@ -78,17 +85,55 @@ export function createChannelControllerPlugin(channelQueue: _IInternalChannels[]
78
85
  waiting --;
79
86
  }
80
87
  });
88
+ }
81
89
 
82
- if (waiting === 0) {
83
- onComplete && onComplete();
84
- }
85
- } else {
86
- onComplete && onComplete();
90
+ _runChainOnComplete();
91
+ }
92
+
93
+ function _doTeardown(unloadCtx: IProcessTelemetryUnloadContext, unloadState: ITelemetryUnloadState) {
94
+ let theUnloadState: ITelemetryUnloadState = unloadState || {
95
+ reason: TelemetryUnloadReason.ManualTeardown,
96
+ isAsync: false
97
+ };
98
+
99
+ _processChannelQueue(channelQueue, unloadCtx, (chainCtx: IProcessTelemetryUnloadContext) => {
100
+ chainCtx[strProcessNext](theUnloadState);
101
+ }, () => {
102
+ unloadCtx[strProcessNext](theUnloadState);
103
+ isInitialized = false;
104
+ });
105
+
106
+ return true;
107
+ }
108
+
109
+ function _getChannel<T extends IPlugin = IPlugin>(pluginIdentifier: string): T {
110
+ let thePlugin: T = null;
111
+
112
+ if (channelQueue && channelQueue.length > 0) {
113
+ arrForEach(channelQueue, (channels) => {
114
+ // pass on to first item in queue
115
+ if (channels && channels.queue.length > 0) {
116
+ arrForEach(channels.queue, (ext: any) => {
117
+ if (ext.identifier === pluginIdentifier) {
118
+ thePlugin = ext;
119
+ // Cause arrForEach to stop iterating
120
+ return -1;
121
+ }
122
+ });
123
+
124
+ if (thePlugin) {
125
+ // Cause arrForEach to stop iterating
126
+ return -1;
127
+ }
128
+ }
129
+ });
87
130
  }
131
+
132
+ return thePlugin;
88
133
  }
89
134
 
90
135
  let isInitialized = false;
91
- let channelController: IChannelController = {
136
+ let channelController: IInternalChannelController = {
92
137
  identifier: "ChannelControllerPlugin",
93
138
  priority: ChannelControllerPriority,
94
139
  initialize: (config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?: ITelemetryPluginChain) => {
@@ -101,41 +146,38 @@ export function createChannelControllerPlugin(channelQueue: _IInternalChannels[]
101
146
  },
102
147
  isInitialized: () => { return isInitialized },
103
148
  processTelemetry: (item: ITelemetryItem, itemCtx: IProcessTelemetryContext) => {
104
- _processChannelQueue(itemCtx, (chainCtx: IProcessTelemetryContext) => {
105
- chainCtx.processNext(item);
149
+ _processChannelQueue(channelQueue, itemCtx || _getTelCtx(), (chainCtx: IProcessTelemetryContext) => {
150
+ chainCtx[strProcessNext](item);
106
151
  }, () => {
107
- itemCtx.processNext(item);
108
- });
109
- },
110
- pause: () => {
111
- _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
112
- chainCtx.iterate<IChannelControls>((plugin) => {
113
- plugin.pause && plugin.pause();
114
- });
152
+ itemCtx[strProcessNext](item);
115
153
  });
116
154
  },
117
- resume: () => {
118
- _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
155
+ [strPause]: () => {
156
+ _processChannelQueue(channelQueue, _getTelCtx(), (chainCtx: IProcessTelemetryContext) => {
119
157
  chainCtx.iterate<IChannelControls>((plugin) => {
120
- plugin.resume && plugin.resume();
158
+ plugin[strPause] && plugin[strPause]();
121
159
  });
122
- });
160
+ }, null);
123
161
  },
124
- teardown: () => {
125
- _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
162
+ [strResume]: () => {
163
+ _processChannelQueue(channelQueue, _getTelCtx(), (chainCtx: IProcessTelemetryContext) => {
126
164
  chainCtx.iterate<IChannelControls>((plugin) => {
127
- plugin.teardown && plugin.teardown();
165
+ plugin[strResume] && plugin[strResume]();
128
166
  });
129
- });
167
+ }, null);
130
168
  },
169
+ [strTeardown]: _doTeardown,
170
+ getChannel: _getChannel,
131
171
  flush: (isAsync: boolean, callBack: (flushComplete?: boolean) => void, sendReason: SendRequestReason, cbTimeout?: number) => {
172
+ // Setting waiting to one so that we don't call the callBack until we finish iterating
173
+ let waiting = 1;
132
174
  let doneIterating = false;
133
- let waiting = 0;
134
175
  let cbTimer: any = null;
135
176
 
136
177
  cbTimeout = cbTimeout || 5000;
137
178
 
138
179
  function doCallback() {
180
+ waiting--;
139
181
  if (doneIterating && waiting === 0) {
140
182
  if (cbTimer) {
141
183
  clearTimeout(cbTimer);
@@ -147,36 +189,40 @@ export function createChannelControllerPlugin(channelQueue: _IInternalChannels[]
147
189
  }
148
190
  }
149
191
 
150
- // Setting waiting to one so that we don't call the callBack until we finish iterating
151
- waiting = 1;
152
- _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
192
+ _processChannelQueue(channelQueue, _getTelCtx(), (chainCtx: IProcessTelemetryContext) => {
153
193
  chainCtx.iterate<IChannelControls>((plugin) => {
154
194
  if (plugin.flush) {
155
195
  waiting ++;
156
196
 
197
+ let handled = false;
157
198
  // Not all channels will call this callback for every scenario
158
199
  if (!plugin.flush(isAsync, () => {
159
- waiting--;
200
+ handled = true;
160
201
  doCallback();
161
202
  }, sendReason)) {
162
- // If any channel doesn't return true we should assume that the callback will never be called, so use a timeout
163
- // to allow the channel some time to "finish" before triggering any followup function (such as unloading)
164
- if (cbTimer == null) {
165
- cbTimer = setTimeout(() => {
166
- cbTimer = null;
167
- callBack && callBack(false);
168
- // Make sure we don't call the callback more than once
169
- callBack = null;
170
- }, cbTimeout);
203
+ if (!handled) {
204
+ // If any channel doesn't return true and it didn't call the callback, then we should assume that the callback
205
+ // will never be called, so use a timeout to allow the channel(s) some time to "finish" before triggering any
206
+ // followup function (such as unloading)
207
+ if (isAsync && cbTimer == null) {
208
+ cbTimer = setTimeout(() => {
209
+ cbTimer = null;
210
+ doCallback();
211
+ }, cbTimeout);
212
+ } else {
213
+ doCallback();
214
+ }
171
215
  }
172
216
  }
173
217
  }
174
218
  });
175
219
  }, () => {
176
- waiting--;
177
220
  doneIterating = true;
178
221
  doCallback();
179
222
  });
223
+ },
224
+ _setQueue: (queue: _IInternalChannels[]) => {
225
+ channelQueue = queue;
180
226
  }
181
227
  };
182
228
 
@@ -2,7 +2,7 @@
2
2
  // Licensed under the MIT License.
3
3
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
4
4
  import { ICookieMgr, ICookieMgrConfig } from "../JavaScriptSDK.Interfaces/ICookieMgr";
5
- import { _InternalMessageId, LoggingSeverity } from "../JavaScriptSDK.Enums/LoggingEnums";
5
+ import { _eInternalMessageId, eLoggingSeverity } from "../JavaScriptSDK.Enums/LoggingEnums";
6
6
  import { dumpObj, getDocument, getLocation, getNavigator, isIE } from "./EnvUtils";
7
7
  import {
8
8
  arrForEach, dateNow, getExceptionName, isFunction, isNotNullOrUndefined, isNullOrUndefined, isString, isTruthy, isUndefined,
@@ -10,6 +10,7 @@ import {
10
10
  } from "./HelperFuncs";
11
11
  import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
12
12
  import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore";
13
+ import { strEmpty } from "./InternalConstants";
13
14
 
14
15
  const strToGMTString = "toGMTString";
15
16
  const strToUTCString = "toUTCString";
@@ -19,7 +20,6 @@ const strEnabled = "enabled";
19
20
  const strIsCookieUseDisabled = "isCookieUseDisabled";
20
21
  const strDisableCookiesUsage = "disableCookiesUsage";
21
22
  const strConfigCookieMgr = "_ckMgr";
22
- const strEmpty = "";
23
23
 
24
24
  let _supportsCookies: boolean = null;
25
25
  let _allowUaSameSite: boolean = null;
@@ -253,8 +253,8 @@ export function areCookiesSupported(logger?: IDiagnosticLogger): any {
253
253
  _supportsCookies = doc[strCookie] !== undefined;
254
254
  } catch (e) {
255
255
  logger && logger.throwInternal(
256
- LoggingSeverity.WARNING,
257
- _InternalMessageId.CannotAccessCookie,
256
+ eLoggingSeverity.WARNING,
257
+ _eInternalMessageId.CannotAccessCookie,
258
258
  "Cannot access document.cookie - " + getExceptionName(e),
259
259
  { exception: dumpObj(e) });
260
260
  }
@@ -6,158 +6,21 @@ import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
6
6
  import { ICookieMgr } from "../JavaScriptSDK.Interfaces/ICookieMgr";
7
7
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
8
8
  import { _gblCookieMgr } from "./CookieMgr";
9
- import { getWindow, getDocument, getPerformance, isIE } from "./EnvUtils";
9
+ import { getPerformance, isIE } from "./EnvUtils";
10
10
  import {
11
- arrForEach, arrIndexOf, arrMap, arrReduce, attachEvent, dateNow, detachEvent, hasOwnProperty,
11
+ arrForEach, arrIndexOf, arrMap, arrReduce, dateNow, hasOwnProperty,
12
12
  isArray, isBoolean, isDate, isError, isFunction, isNullOrUndefined, isNumber, isObject, isString, isTypeof,
13
13
  isUndefined, objDefineAccessors, objKeys, strTrim, toISOString
14
14
  } from "./HelperFuncs";
15
+ import { addEventHandler, attachEvent, detachEvent } from "./EventHelpers";
15
16
  import { randomValue, random32, mwcRandomSeed, mwcRandom32, newId } from "./RandomHelper";
16
-
17
- const strVisibilityChangeEvt: string = "visibilitychange";
18
- const strPageHide: string = "pagehide";
19
- const strPageShow: string = "pageshow";
17
+ import { strEmpty } from "./InternalConstants";
20
18
 
21
19
  let _cookieMgrs: ICookieMgr[] = null;
22
20
  let _canUseCookies: boolean; // legacy supported config
23
21
 
24
22
  // Added to help with minfication
25
23
  export const Undefined = strShimUndefined;
26
-
27
- /**
28
- * Trys to add an event handler for the specified event to the window, body and document
29
- * @param eventName {string} - The name of the event
30
- * @param callback {any} - The callback function that needs to be executed for the given event
31
- * @return {boolean} - true if the handler was successfully added
32
- */
33
- export function addEventHandler(eventName: string, callback: any): boolean {
34
- let result = false;
35
- let w = getWindow();
36
- if (w) {
37
- result = attachEvent(w, eventName, callback);
38
- result = attachEvent(w["body"], eventName, callback) || result;
39
- }
40
-
41
- let doc = getDocument();
42
- if (doc) {
43
- result = attachEvent(doc, eventName, callback) || result;
44
- }
45
-
46
- return result;
47
- }
48
-
49
- /**
50
- * Bind the listener to the array of events
51
- * @param events An string array of event names to bind the listener to
52
- * @param listener The event callback to call when the event is triggered
53
- * @param excludeEvents - [Optional] An array of events that should not be hooked (if possible), unless no other events can be.
54
- * @returns true - when at least one of the events was registered otherwise false
55
- */
56
- export function addEventListeners(events: string[], listener: any, excludeEvents?: string[]): boolean {
57
- let added = false;
58
-
59
- if (listener && events && isArray(events)) {
60
- let excluded: string[] = [];
61
- arrForEach(events, (name) => {
62
- if (isString(name)) {
63
- if (!excludeEvents || arrIndexOf(excludeEvents, name) === -1) {
64
- added = addEventHandler(name, listener) || added;
65
- } else {
66
- excluded.push(name);
67
- }
68
- }
69
- });
70
-
71
- if (!added && excluded.length > 0) {
72
- // Failed to add any listeners and we excluded some, so just attempt to add the excluded events
73
- added = addEventListeners(excluded, listener);
74
- }
75
- }
76
-
77
- return added;
78
- }
79
-
80
- /**
81
- * Listen to the 'beforeunload', 'unload' and 'pagehide' events which indicates a page unload is occurring,
82
- * this does NOT listen to the 'visibilitychange' event as while it does indicate that the page is being hidden
83
- * it does not *necessarily* mean that the page is being completely unloaded, it can mean that the user is
84
- * just navigating to a different Tab and may come back (without unloading the page). As such you may also
85
- * need to listen to the 'addPageHideEventListener' and 'addPageShowEventListener' events.
86
- * @param listener - The event callback to call when a page unload event is triggered
87
- * @param excludeEvents - [Optional] An array of events that should not be hooked, unless no other events can be.
88
- * @returns true - when at least one of the events was registered otherwise false
89
- */
90
- export function addPageUnloadEventListener(listener: any, excludeEvents?: string[]): boolean {
91
- // Hook the unload event for the document, window and body to ensure that the client events are flushed to the server
92
- // As just hooking the window does not always fire (on chrome) for page navigation's.
93
- return addEventListeners(["beforeunload", "unload", "pagehide"], listener, excludeEvents);
94
- }
95
-
96
- /**
97
- * Listen to the pagehide and visibility changing to 'hidden' events
98
- * @param listener - The event callback to call when a page hide event is triggered
99
- * @param excludeEvents - [Optional] An array of events that should not be hooked (if possible), unless no other events can be.
100
- * Suggestion: pass as true if you are also calling addPageUnloadEventListener as that also hooks pagehide
101
- * @returns true - when at least one of the events was registered otherwise false
102
- */
103
- export function addPageHideEventListener(listener: any, excludeEvents?: string[]): boolean {
104
-
105
- function _handlePageVisibility(evt: any) {
106
- let doc = getDocument();
107
- if (listener && doc && doc.visibilityState === "hidden") {
108
- listener(evt);
109
- }
110
- }
111
-
112
- let pageUnloadAdded = false;
113
- if (!excludeEvents || arrIndexOf(excludeEvents, strPageHide) === -1) {
114
- pageUnloadAdded = addEventHandler(strPageHide, listener);
115
- }
116
-
117
- if (!excludeEvents || arrIndexOf(excludeEvents, strVisibilityChangeEvt) === -1) {
118
- pageUnloadAdded = addEventHandler(strVisibilityChangeEvt, _handlePageVisibility) || pageUnloadAdded;
119
- }
120
-
121
- if (!pageUnloadAdded && excludeEvents) {
122
- // Failed to add any listeners and we where requested to exclude some, so just call again without excluding anything
123
- pageUnloadAdded = addPageHideEventListener(listener);
124
- }
125
-
126
- return pageUnloadAdded;
127
- }
128
-
129
- /**
130
- * Listen to the pageshow and visibility changing to 'visible' events
131
- * @param listener - The event callback to call when a page is show event is triggered
132
- * @param excludeEvents - [Optional] An array of events that should not be hooked (if possible), unless no other events can be.
133
- * @returns true - when at least one of the events was registered otherwise false
134
- */
135
- export function addPageShowEventListener(listener: any, excludeEvents?: string[]): boolean {
136
-
137
- function _handlePageVisibility(evt: any) {
138
- let doc = getDocument();
139
- if (listener && doc && doc.visibilityState === "visible") {
140
- listener(evt);
141
- }
142
- }
143
-
144
- let pageShowAdded = false;
145
- if (!excludeEvents || arrIndexOf(excludeEvents, strPageShow) === -1) {
146
- pageShowAdded = addEventHandler(strPageShow, listener);
147
- }
148
-
149
- if (!excludeEvents || arrIndexOf(excludeEvents, strVisibilityChangeEvt) === -1) {
150
- pageShowAdded = addEventHandler(strVisibilityChangeEvt, _handlePageVisibility) || pageShowAdded;
151
- }
152
-
153
- if (!pageShowAdded && excludeEvents) {
154
- // Failed to add any listeners and we where requested to exclude some, so just call again without excluding anything
155
- pageShowAdded = addPageShowEventListener(listener);
156
- }
157
-
158
- return pageShowAdded;
159
- }
160
-
161
24
  export function newGuid(): string {
162
25
  function randomHexDigit() {
163
26
  return randomValue(15); // Get a random value from 0..15
@@ -205,7 +68,7 @@ export function generateW3CId(): string {
205
68
  const hexValues = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
206
69
 
207
70
  // rfc4122 version 4 UUID without dashes and with lowercase letters
208
- let oct = "", tmp;
71
+ let oct = strEmpty, tmp;
209
72
  for (let a = 0; a < 4; a++) {
210
73
  tmp = random32();
211
74
  oct +=
@@ -380,7 +243,7 @@ export interface ICoreUtils {
380
243
  * @param callback {any} - The callback function that needs to be executed for the given event
381
244
  * @return {boolean} - true if the handler was successfully added
382
245
  */
383
- addEventHandler: (eventName: string, callback: any) => boolean;
246
+ addEventHandler: (eventName: string, callback: any, evtNamespace?: string | string[]) => boolean;
384
247
 
385
248
  /**
386
249
  * Return the current time via the Date now() function (if available) and falls back to (new Date()).getTime() if now() is unavailable (IE8 or less)