@microsoft/applicationinsights-core-js 2.7.4-nightly.2202-07 → 2.8.0-beta.2202-06

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 (108) hide show
  1. package/browser/applicationinsights-core-js.integrity.json +9 -9
  2. package/browser/applicationinsights-core-js.js +860 -457
  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 +1193 -267
  7. package/dist/applicationinsights-core-js.api.md +54 -14
  8. package/dist/applicationinsights-core-js.d.ts +133 -45
  9. package/dist/applicationinsights-core-js.js +860 -457
  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 +133 -45
  14. package/dist-esm/JavaScriptSDK/AppInsightsCore.js +3 -69
  15. package/dist-esm/JavaScriptSDK/AppInsightsCore.js.map +1 -1
  16. package/dist-esm/JavaScriptSDK/BaseCore.js +237 -82
  17. package/dist-esm/JavaScriptSDK/BaseCore.js.map +1 -1
  18. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js +45 -19
  19. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js.map +1 -1
  20. package/dist-esm/JavaScriptSDK/ChannelController.js +155 -87
  21. package/dist-esm/JavaScriptSDK/ChannelController.js.map +1 -1
  22. package/dist-esm/JavaScriptSDK/Constants.js +1 -1
  23. package/dist-esm/JavaScriptSDK/CookieMgr.js +1 -1
  24. package/dist-esm/JavaScriptSDK/CoreUtils.js +2 -27
  25. package/dist-esm/JavaScriptSDK/CoreUtils.js.map +1 -1
  26. package/dist-esm/JavaScriptSDK/DbgExtensionUtils.js +1 -1
  27. package/dist-esm/JavaScriptSDK/DiagnosticLogger.js +1 -1
  28. package/dist-esm/JavaScriptSDK/EnvUtils.js +6 -6
  29. package/dist-esm/JavaScriptSDK/EnvUtils.js.map +1 -1
  30. package/dist-esm/JavaScriptSDK/HelperFuncs.js +51 -11
  31. package/dist-esm/JavaScriptSDK/HelperFuncs.js.map +1 -1
  32. package/dist-esm/JavaScriptSDK/InstrumentHooks.js +3 -1
  33. package/dist-esm/JavaScriptSDK/InstrumentHooks.js.map +1 -1
  34. package/dist-esm/JavaScriptSDK/NotificationManager.js +34 -36
  35. package/dist-esm/JavaScriptSDK/NotificationManager.js.map +1 -1
  36. package/dist-esm/JavaScriptSDK/PerfManager.js +1 -1
  37. package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js +289 -119
  38. package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js.map +1 -1
  39. package/dist-esm/JavaScriptSDK/RandomHelper.js +29 -4
  40. package/dist-esm/JavaScriptSDK/RandomHelper.js.map +1 -1
  41. package/dist-esm/JavaScriptSDK/TelemetryHelpers.js +2 -2
  42. package/dist-esm/JavaScriptSDK/TelemetryHelpers.js.map +1 -1
  43. package/dist-esm/JavaScriptSDK/TelemetryInitializerPlugin.js +82 -0
  44. package/dist-esm/JavaScriptSDK/TelemetryInitializerPlugin.js.map +1 -0
  45. package/dist-esm/JavaScriptSDK.Enums/EventsDiscardedReason.js +1 -1
  46. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js +1 -1
  47. package/dist-esm/JavaScriptSDK.Enums/SendRequestReason.js +1 -1
  48. package/dist-esm/JavaScriptSDK.Interfaces/IAppInsightsCore.js +1 -2
  49. package/dist-esm/JavaScriptSDK.Interfaces/IAppInsightsCore.js.map +1 -1
  50. package/dist-esm/JavaScriptSDK.Interfaces/IChannelControls.js +1 -1
  51. package/dist-esm/JavaScriptSDK.Interfaces/IConfiguration.js +1 -1
  52. package/dist-esm/JavaScriptSDK.Interfaces/ICookieMgr.js +1 -1
  53. package/dist-esm/JavaScriptSDK.Interfaces/IDbgExtension.js +1 -1
  54. package/dist-esm/JavaScriptSDK.Interfaces/IDiagnosticLogger.js +1 -1
  55. package/dist-esm/JavaScriptSDK.Interfaces/IInstrumentHooks.js +1 -1
  56. package/dist-esm/JavaScriptSDK.Interfaces/INotificationListener.js +1 -1
  57. package/dist-esm/JavaScriptSDK.Interfaces/INotificationManager.js +1 -1
  58. package/dist-esm/JavaScriptSDK.Interfaces/IPerfEvent.js +1 -1
  59. package/dist-esm/JavaScriptSDK.Interfaces/IPerfManager.js +1 -1
  60. package/dist-esm/JavaScriptSDK.Interfaces/IProcessTelemetryContext.js +1 -1
  61. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryInitializers.js +6 -0
  62. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryInitializers.js.map +1 -0
  63. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryItem.js +1 -1
  64. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPlugin.js +1 -1
  65. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js +1 -1
  66. package/dist-esm/applicationinsights-core-js.js +4 -4
  67. package/dist-esm/applicationinsights-core-js.js.map +1 -1
  68. package/package.json +2 -2
  69. package/src/JavaScriptSDK/AppInsightsCore.ts +2 -101
  70. package/src/JavaScriptSDK/BaseCore.ts +330 -100
  71. package/src/JavaScriptSDK/BaseTelemetryPlugin.ts +69 -32
  72. package/src/JavaScriptSDK/ChannelController.ts +175 -103
  73. package/src/JavaScriptSDK/CoreUtils.ts +1 -28
  74. package/src/JavaScriptSDK/EnvUtils.ts +5 -5
  75. package/src/JavaScriptSDK/HelperFuncs.ts +57 -14
  76. package/src/JavaScriptSDK/InstrumentHooks.ts +3 -1
  77. package/src/JavaScriptSDK/NotificationManager.ts +32 -31
  78. package/src/JavaScriptSDK/PerfManager.ts +1 -1
  79. package/src/JavaScriptSDK/ProcessTelemetryContext.ts +350 -133
  80. package/src/JavaScriptSDK/RandomHelper.ts +34 -3
  81. package/src/JavaScriptSDK/TelemetryHelpers.ts +4 -6
  82. package/src/JavaScriptSDK/TelemetryInitializerPlugin.ts +119 -0
  83. package/src/JavaScriptSDK.Interfaces/IAppInsightsCore.ts +17 -1
  84. package/src/JavaScriptSDK.Interfaces/IChannelControls.ts +7 -3
  85. package/src/JavaScriptSDK.Interfaces/IInstrumentHooks.ts +5 -0
  86. package/src/JavaScriptSDK.Interfaces/IProcessTelemetryContext.ts +23 -5
  87. package/src/JavaScriptSDK.Interfaces/ITelemetryInitializers.ts +16 -0
  88. package/src/JavaScriptSDK.Interfaces/ITelemetryPlugin.ts +1 -1
  89. package/types/JavaScriptSDK/AppInsightsCore.d.ts +0 -21
  90. package/types/JavaScriptSDK/BaseCore.d.ts +30 -1
  91. package/types/JavaScriptSDK/BaseTelemetryPlugin.d.ts +13 -11
  92. package/types/JavaScriptSDK/ChannelController.d.ts +12 -17
  93. package/types/JavaScriptSDK/CoreUtils.d.ts +0 -6
  94. package/types/JavaScriptSDK/HelperFuncs.d.ts +14 -5
  95. package/types/JavaScriptSDK/ProcessTelemetryContext.d.ts +49 -3
  96. package/types/JavaScriptSDK/RandomHelper.d.ts +6 -0
  97. package/types/JavaScriptSDK/TelemetryHelpers.d.ts +3 -3
  98. package/types/JavaScriptSDK/TelemetryInitializerPlugin.d.ts +23 -0
  99. package/types/JavaScriptSDK.Interfaces/IAppInsightsCore.d.ts +15 -0
  100. package/types/JavaScriptSDK.Interfaces/IChannelControls.d.ts +7 -3
  101. package/types/JavaScriptSDK.Interfaces/IInstrumentHooks.d.ts +4 -0
  102. package/types/JavaScriptSDK.Interfaces/IProcessTelemetryContext.d.ts +18 -3
  103. package/types/JavaScriptSDK.Interfaces/ITelemetryInitializers.d.ts +13 -0
  104. package/types/applicationinsights-core-js.d.ts +5 -4
  105. package/dist-esm/JavaScriptSDK/TelemetryPluginChain.js +0 -76
  106. package/dist-esm/JavaScriptSDK/TelemetryPluginChain.js.map +0 -1
  107. package/src/JavaScriptSDK/TelemetryPluginChain.ts +0 -120
  108. package/types/JavaScriptSDK/TelemetryPluginChain.d.ts +0 -32
@@ -3,6 +3,7 @@
3
3
 
4
4
  "use strict";
5
5
 
6
+ import dynamicProto from "@microsoft/dynamicproto-js";
6
7
  import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore"
7
8
  import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
8
9
  import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger";
@@ -10,9 +11,10 @@ import { IPlugin, ITelemetryPlugin } from "../JavaScriptSDK.Interfaces/ITelemetr
10
11
  import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
11
12
  import { IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
12
13
  import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
13
- import { ProcessTelemetryContext } from "./ProcessTelemetryContext";
14
- import { isFunction, isNullOrUndefined, setValue } from "./HelperFuncs";
14
+ import { createProcessTelemetryContext } from "./ProcessTelemetryContext";
15
+ import { isArray, isFunction, isNullOrUndefined, setValue } from "./HelperFuncs";
15
16
  import { strExtensionConfig } from "./Constants";
17
+ import { IInstrumentHook } from "../JavaScriptSDK.Interfaces/IInstrumentHooks";
16
18
 
17
19
  let strGetPlugin = "getPlugin";
18
20
 
@@ -22,6 +24,16 @@ let strGetPlugin = "getPlugin";
22
24
  * implementation so that new default implementations can be added without breaking all plugins.
23
25
  */
24
26
  export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
27
+
28
+ public identifier: string;
29
+ public version?: string;
30
+
31
+ /**
32
+ * Holds the core instance that was used during initialization
33
+ */
34
+ public core: IAppInsightsCore;
35
+
36
+ priority: number;
25
37
 
26
38
  /**
27
39
  * Call back for telemetry processing before it it is sent
@@ -35,7 +47,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
35
47
  /**
36
48
  * Set next extension for telemetry processing
37
49
  */
38
- public setNextPlugin: (next: ITelemetryPlugin|ITelemetryPluginChain) => void;
50
+ public setNextPlugin: (next: ITelemetryPlugin | ITelemetryPluginChain) => void;
39
51
 
40
52
  /**
41
53
  * Returns the current diagnostic logger that can be used to log issues, if no logger is currently
@@ -48,16 +60,6 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
48
60
  */
49
61
  public isInitialized: () => boolean;
50
62
 
51
- public identifier: string;
52
- public version?: string;
53
-
54
- /**
55
- * Holds the core instance that was used during initialization
56
- */
57
- public core: IAppInsightsCore;
58
-
59
- priority: number;
60
-
61
63
  /**
62
64
  * Helper to return the current IProcessTelemetryContext, if the passed argument exists this just
63
65
  * returns that value (helps with minification for callers), otherwise it will return the configured
@@ -71,21 +73,39 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
71
73
  */
72
74
  protected setInitialized: (isInitialized: boolean) => void;
73
75
 
74
- /**
75
- * Internal helper to initialize the instance
76
- */
77
- private _baseTelInit: (config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?:ITelemetryPluginChain) => void;
78
-
79
76
  constructor() {
80
- let _self = this;
81
- let _isinitialized = false;
82
- let _rootCtx: IProcessTelemetryContext = null; // Used as the root context, holding the current config and initialized core
83
- let _nextPlugin:ITelemetryPlugin|ITelemetryPluginChain = null; // Used for backward compatibility where plugins don't call the main pipeline
77
+ let _self = this; // Setting _self here as it's used outside of the dynamicProto as well
84
78
 
85
- _self.core = null;
79
+ // NOTE!: DON'T set default values here, instead set them in the _initDefaults() function as it is also called during teardown()
80
+ let _isinitialized: boolean;
81
+ let _rootCtx: IProcessTelemetryContext; // Used as the root context, holding the current config and initialized core
82
+ let _nextPlugin: ITelemetryPlugin | ITelemetryPluginChain; // Used for backward compatibility where plugins don't call the main pipeline
83
+ let _hooks: IInstrumentHook[];
84
+
85
+ _initDefaults();
86
+
87
+ dynamicProto(BaseTelemetryPlugin, _self, (_self) => {
88
+
89
+ _self.initialize = (config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?:ITelemetryPluginChain): void => {
90
+ _setDefaults(config, core, pluginChain);
91
+ _isinitialized = true;
92
+ }
93
+
94
+ _self._addHook = (hooks: IInstrumentHook | IInstrumentHook[]) => {
95
+ if (hooks) {
96
+ if (isArray(hooks)) {
97
+ _hooks = _hooks.concat(hooks);
98
+ } else {
99
+ _hooks.push(hooks);
100
+ }
101
+ }
102
+ };
103
+ });
104
+
105
+ // These are added after the dynamicProto so that are not moved to the prototype
86
106
 
87
107
  _self.diagLog = (itemCtx:IProcessTelemetryContext): IDiagnosticLogger => {
88
- return _self._getTelCtx(itemCtx).diagLog();
108
+ return _getTelCtx(itemCtx).diagLog();
89
109
  }
90
110
 
91
111
  _self.isInitialized = () => {
@@ -101,7 +121,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
101
121
  // should use processNext() function. If you require access to the plugin use the
102
122
  // IProcessTelemetryContext.getNext().getPlugin() while in the pipeline, Note getNext() may return null.
103
123
 
104
- _self.setNextPlugin = (next: ITelemetryPlugin|ITelemetryPluginChain) => {
124
+ _self.setNextPlugin = (next: ITelemetryPlugin | ITelemetryPluginChain) => {
105
125
  _nextPlugin = next;
106
126
  };
107
127
 
@@ -116,10 +136,12 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
116
136
  }
117
137
  };
118
138
 
119
- _self._getTelCtx = (currentCtx:IProcessTelemetryContext = null) => {
139
+ _self._getTelCtx = _getTelCtx;
140
+
141
+ function _getTelCtx(currentCtx:IProcessTelemetryContext = null) {
120
142
  let itemCtx:IProcessTelemetryContext = currentCtx;
121
143
  if (!itemCtx) {
122
- let rootCtx = _rootCtx || new ProcessTelemetryContext(null, {}, _self.core);
144
+ let rootCtx = _rootCtx || createProcessTelemetryContext(null, {}, _self.core);
123
145
  // tslint:disable-next-line: prefer-conditional-expression
124
146
  if (_nextPlugin && _nextPlugin[strGetPlugin]) {
125
147
  // Looks like a chain object
@@ -132,7 +154,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
132
154
  return itemCtx;
133
155
  }
134
156
 
135
- _self._baseTelInit = (config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?:ITelemetryPluginChain) => {
157
+ function _setDefaults(config: IConfiguration, core: IAppInsightsCore, pluginChain: ITelemetryPluginChain) {
136
158
  if (config) {
137
159
  // Make sure the extensionConfig exists
138
160
  setValue(config, strExtensionConfig, [], null, isNullOrUndefined);
@@ -143,7 +165,7 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
143
165
  pluginChain = core.getProcessTelContext().getNext();
144
166
  }
145
167
 
146
- let nextPlugin:IPlugin = _nextPlugin as IPlugin;
168
+ let nextPlugin: IPlugin = _nextPlugin as IPlugin;
147
169
  if (_nextPlugin && _nextPlugin[strGetPlugin]) {
148
170
  // If it looks like a proxy/chain then get the plugin
149
171
  nextPlugin = _nextPlugin[strGetPlugin]();
@@ -151,14 +173,29 @@ export abstract class BaseTelemetryPlugin implements ITelemetryPlugin {
151
173
 
152
174
  // Support legacy plugins where core was defined as a property
153
175
  _self.core = core;
154
- _rootCtx = new ProcessTelemetryContext(pluginChain, config, core, nextPlugin);
155
- _isinitialized = true;
176
+ _rootCtx = createProcessTelemetryContext(pluginChain, config, core, nextPlugin);
177
+ }
178
+
179
+ function _initDefaults() {
180
+ _isinitialized = false;
181
+ _self.core = null;
182
+ _rootCtx = null;
183
+ _nextPlugin = null;
184
+ _hooks = [];
156
185
  }
157
186
  }
158
187
 
159
188
  public initialize(config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?:ITelemetryPluginChain): void {
160
- this._baseTelInit(config, core, extensions, pluginChain);
189
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
161
190
  }
162
191
 
163
192
  public abstract processTelemetry(env: ITelemetryItem, itemCtx?: IProcessTelemetryContext): void;
193
+
194
+ /**
195
+ * Add this hook so that it is automatically removed during unloading
196
+ * @param hooks - The single hook or an array of IInstrumentHook objects
197
+ */
198
+ protected _addHook(hooks: IInstrumentHook | IInstrumentHook[]): void {
199
+ // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
200
+ }
164
201
  }
@@ -1,135 +1,207 @@
1
1
  // Copyright (c) Microsoft Corporation. All rights reserved.
2
- // Licensed under the MIT License.
3
- "use strict";
2
+ // // Licensed under the MIT License.
4
3
 
5
- import dynamicProto from "@microsoft/dynamicproto-js";
6
- import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore"
7
- import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
4
+ import { SendRequestReason } from "../JavaScriptSDK.Enums/SendRequestReason";
5
+ import { IAppInsightsCore } from "../JavaScriptSDK.Interfaces/IAppInsightsCore";
8
6
  import { IChannelControls } from "../JavaScriptSDK.Interfaces/IChannelControls";
9
- import { IPlugin, ITelemetryPlugin } from "../JavaScriptSDK.Interfaces/ITelemetryPlugin";
10
- import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
11
- import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
7
+ import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration";
12
8
  import { IProcessTelemetryContext } from "../JavaScriptSDK.Interfaces/IProcessTelemetryContext";
13
- import { _InternalLogMessage } from "./DiagnosticLogger";
14
- import { BaseTelemetryPlugin } from "./BaseTelemetryPlugin";
15
- import { ProcessTelemetryContext } from "./ProcessTelemetryContext";
9
+ import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem";
10
+ import { IPlugin } from "../JavaScriptSDK.Interfaces/ITelemetryPlugin";
11
+ import { ITelemetryPluginChain } from "../JavaScriptSDK.Interfaces/ITelemetryPluginChain";
12
+ import { arrForEach, isArray, objFreeze, throwError } from "./HelperFuncs";
13
+ import { createProcessTelemetryContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
16
14
  import { initializePlugins } from "./TelemetryHelpers";
17
- import { arrForEach, objDefineAccessors, throwError } from "./HelperFuncs";
18
15
 
19
- const ChannelControllerPriority = 500;
20
- const ChannelValidationMessage = "Channel has invalid priority";
16
+ export const ChannelControllerPriority = 500;
17
+ const ChannelValidationMessage = "Channel has invalid priority - ";
21
18
 
22
- export class ChannelController extends BaseTelemetryPlugin {
19
+ export interface IChannelController extends IChannelControls {
20
+ flush(isAsync: boolean, callBack: (flushComplete?: boolean) => void, sendReason: SendRequestReason, cbTimeout?: number): void
21
+ }
22
+
23
+ export interface _IInternalChannels {
24
+ queue: IChannelControls[];
25
+ chain: ITelemetryPluginChain;
26
+ }
27
+
28
+ function _addChannelQueue(channelQueue: _IInternalChannels[], queue: IChannelControls[], config: IConfiguration, core: IAppInsightsCore) {
29
+ if (queue && isArray(queue) && queue.length > 0) {
30
+ queue = queue.sort((a, b) => { // sort based on priority within each queue
31
+ return a.priority - b.priority;
32
+ });
33
+
34
+ arrForEach(queue, queueItem => {
35
+ if (queueItem.priority < ChannelControllerPriority) {
36
+ throwError(ChannelValidationMessage + queueItem.identifier);
37
+ }
38
+ });
23
39
 
24
- identifier: string = "ChannelControllerPlugin";
25
- priority: number = ChannelControllerPriority; // in reserved range 100 to 200
40
+ channelQueue.push({
41
+ queue: objFreeze(queue),
42
+ chain: createTelemetryProxyChain(queue, config, core)
43
+ });
44
+ }
45
+ }
26
46
 
27
- public setNextPlugin: (next: ITelemetryPlugin | ITelemetryPluginChain) => void;
47
+ export function createChannelControllerPlugin(channelQueue: _IInternalChannels[], core: IAppInsightsCore): IChannelController {
28
48
 
29
- constructor() {
30
- super();
31
- let _channelQueue: IChannelControls[][];
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
+ }
32
54
 
33
- dynamicProto(ChannelController, this, (_self, _base) => {
34
- _self.setNextPlugin = (next: ITelemetryPlugin | ITelemetryPluginChain) => {
35
- // The Channel controller is last in pipeline
36
- };
55
+ return itemCtx;
56
+ }
37
57
 
38
- _self.processTelemetry = (item: ITelemetryItem, itemCtx: IProcessTelemetryContext) => {
39
- if (_channelQueue) {
40
- arrForEach(_channelQueue, queues => {
41
- // pass on to first item in queue
42
- if (queues.length > 0) {
43
- // Copying the item context as we could have mutiple chains that are executing asynchronously
44
- // and calling _getDefTelCtx as it's possible that the caller doesn't pass any context
45
- let chainCtx = this._getTelCtx(itemCtx).createNew(queues);
46
- chainCtx.processNext(item);
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
+ // pass on to first item in queue
63
+ if (channels && channels.queue.length > 0) {
64
+ 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;
47
72
  }
48
73
  });
49
- }
50
- };
51
-
52
- _self.getChannelControls = (): IChannelControls[][] => {
53
- return _channelQueue;
54
- };
55
-
56
- _self.initialize = (config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[]) => {
57
- if (_self.isInitialized()) {
58
- // already initialized
59
- return;
60
- }
61
74
 
62
- _base.initialize(config, core, extensions);
75
+ // Cause this chain to start processing
76
+ processFn(chainCtx);
77
+ } else {
78
+ waiting --;
79
+ }
80
+ });
63
81
 
64
- _createChannelQueues((config||{}).channels, extensions);
65
-
66
- // Initialize the Queues
67
- arrForEach(_channelQueue, queue => initializePlugins(new ProcessTelemetryContext(queue, config, core), extensions));
82
+ if (waiting === 0) {
83
+ onComplete && onComplete();
68
84
  }
69
- });
85
+ } else {
86
+ onComplete && onComplete();
87
+ }
88
+ }
70
89
 
71
- function _checkQueuePriority(queue:IChannelControls[]) {
72
- arrForEach(queue, queueItem => {
73
- if (queueItem.priority < ChannelControllerPriority) {
74
- throwError(ChannelValidationMessage + queueItem.identifier);
90
+ let isInitialized = false;
91
+ let channelController: IChannelController = {
92
+ identifier: "ChannelControllerPlugin",
93
+ priority: ChannelControllerPriority,
94
+ initialize: (config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?: ITelemetryPluginChain) => {
95
+ isInitialized = true;
96
+ arrForEach(channelQueue, (channels) => {
97
+ if (channels && channels.queue.length > 0) {
98
+ initializePlugins(createProcessTelemetryContext(channels.chain, config, core), extensions);
75
99
  }
76
100
  });
77
- }
78
-
79
- function _addChannelQueue(queue:IChannelControls[]) {
80
- if (queue && queue.length > 0) {
81
- queue = queue.sort((a, b) => { // sort based on priority within each queue
82
- return a.priority - b.priority;
101
+ },
102
+ isInitialized: () => { return isInitialized },
103
+ processTelemetry: (item: ITelemetryItem, itemCtx: IProcessTelemetryContext) => {
104
+ _processChannelQueue(itemCtx, (chainCtx: IProcessTelemetryContext) => {
105
+ chainCtx.processNext(item);
106
+ }, () => {
107
+ itemCtx.processNext(item);
108
+ });
109
+ },
110
+ pause: () => {
111
+ _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
112
+ chainCtx.iterate<IChannelControls>((plugin) => {
113
+ plugin.pause && plugin.pause();
83
114
  });
84
-
85
- _checkQueuePriority(queue);
86
- _channelQueue.push(queue);
87
- }
88
- }
89
-
90
- function _createChannelQueues(channels:IChannelControls[][], extensions: IPlugin[]) {
91
- _channelQueue = [];
92
-
93
- if (channels) {
94
- // Add and sort the configuration channel queues
95
- arrForEach(channels, queue => _addChannelQueue(queue));
115
+ });
116
+ },
117
+ resume: () => {
118
+ _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
119
+ chainCtx.iterate<IChannelControls>((plugin) => {
120
+ plugin.resume && plugin.resume();
121
+ });
122
+ });
123
+ },
124
+ teardown: () => {
125
+ _processChannelQueue(null, (chainCtx: IProcessTelemetryContext) => {
126
+ chainCtx.iterate<IChannelControls>((plugin) => {
127
+ plugin.teardown && plugin.teardown();
128
+ });
129
+ });
130
+ },
131
+ flush: (isAsync: boolean, callBack: (flushComplete?: boolean) => void, sendReason: SendRequestReason, cbTimeout?: number) => {
132
+ let doneIterating = false;
133
+ let waiting = 0;
134
+ let cbTimer: any = null;
135
+
136
+ cbTimeout = cbTimeout || 5000;
137
+
138
+ function doCallback() {
139
+ if (doneIterating && waiting === 0) {
140
+ if (cbTimer) {
141
+ clearTimeout(cbTimer);
142
+ cbTimer = null;
143
+ }
144
+
145
+ callBack && callBack(doneIterating);
146
+ callBack = null;
147
+ }
96
148
  }
97
-
98
- if (extensions) {
99
- // Create a new channel queue for any extensions with a priority > the ChannelControllerPriority
100
- let extensionQueue:IChannelControls[] = [];
101
- arrForEach(extensions as IChannelControls[], plugin => {
102
- if (plugin.priority > ChannelControllerPriority) {
103
- extensionQueue.push(plugin);
149
+
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) => {
153
+ chainCtx.iterate<IChannelControls>((plugin) => {
154
+ if (plugin.flush) {
155
+ waiting ++;
156
+
157
+ // Not all channels will call this callback for every scenario
158
+ if (!plugin.flush(isAsync, () => {
159
+ waiting--;
160
+ doCallback();
161
+ }, 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);
171
+ }
172
+ }
104
173
  }
105
174
  });
106
-
107
- _addChannelQueue(extensionQueue);
108
- }
175
+ }, () => {
176
+ waiting--;
177
+ doneIterating = true;
178
+ doCallback();
179
+ });
109
180
  }
110
- }
181
+ };
111
182
 
112
- public processTelemetry(item: ITelemetryItem, itemCtx: IProcessTelemetryContext) {
113
- // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
114
- }
183
+ return channelController;
184
+ }
185
+
186
+ export function createChannelQueues(channels: IChannelControls[][], extensions: IPlugin[], config: IConfiguration, core: IAppInsightsCore) {
187
+ let channelQueue: _IInternalChannels[] = [];
115
188
 
116
- public getChannelControls(): IChannelControls[][] {
117
- // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
118
- return null;
189
+ if (channels) {
190
+ // Add and sort the configuration channel queues
191
+ arrForEach(channels, queue => _addChannelQueue(channelQueue, queue, config, core));
119
192
  }
120
193
 
121
- public initialize(config: IConfiguration, core: IAppInsightsCore, extensions: IPlugin[]) {
122
- // @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
194
+ if (extensions) {
195
+ // Create a new channel queue for any extensions with a priority > the ChannelControllerPriority
196
+ let extensionQueue: IChannelControls[] = [];
197
+ arrForEach(extensions as IChannelControls[], plugin => {
198
+ if (plugin.priority > ChannelControllerPriority) {
199
+ extensionQueue.push(plugin);
200
+ }
201
+ });
202
+
203
+ _addChannelQueue(channelQueue, extensionQueue, config, core);
123
204
  }
124
205
 
125
- /**
126
- * Static constructor, attempt to create accessors
127
- */
128
- // tslint:disable-next-line
129
- private static _staticInit = (() => {
130
- let proto = ChannelController.prototype;
131
- // Dynamically create get/set property accessors
132
- objDefineAccessors(proto, "ChannelControls", proto.getChannelControls);
133
- objDefineAccessors(proto, "channelQueue", proto.getChannelControls);
134
- })();
206
+ return channelQueue;
135
207
  }
@@ -12,7 +12,7 @@ import {
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 { randomValue, random32, mwcRandomSeed, mwcRandom32 } from "./RandomHelper";
15
+ import { randomValue, random32, mwcRandomSeed, mwcRandom32, newId } from "./RandomHelper";
16
16
 
17
17
  const strVisibilityChangeEvt: string = "visibilitychange";
18
18
  const strPageHide: string = "pagehide";
@@ -182,33 +182,6 @@ export function perfNow(): number {
182
182
  return dateNow();
183
183
  }
184
184
 
185
- /**
186
- * Generate random base64 id string.
187
- * The default length is 22 which is 132-bits so almost the same as a GUID but as base64 (the previous default was 5)
188
- * @param maxLength - Optional value to specify the length of the id to be generated, defaults to 22
189
- */
190
- export function newId(maxLength = 22): string {
191
- const base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
192
-
193
- // Start with an initial random number, consuming the value in reverse byte order
194
- let number = random32() >>> 0; // Make sure it's a +ve number
195
- let chars = 0;
196
- let result = "";
197
- while (result.length < maxLength) {
198
- chars ++;
199
- result += base64chars.charAt(number & 0x3F);
200
- number >>>= 6; // Zero fill with right shift
201
- if (chars === 5) {
202
- // 5 base64 characters === 30 bits so we don't have enough bits for another base64 char
203
- // So add on another 30 bits and make sure it's +ve
204
- number = (((random32() << 2) & 0xFFFFFFFF) | (number & 0x03)) >>> 0;
205
- chars = 0; // We need to reset the number every 5 chars (30 bits)
206
- }
207
- }
208
-
209
- return result;
210
- }
211
-
212
185
  /**
213
186
  * The strEndsWith() method determines whether a string ends with the characters of a specified string, returning true or false as appropriate.
214
187
  * @param value - The value to check whether it ends with the search value.
@@ -31,6 +31,7 @@ const strMsCrypto = "msCrypto";
31
31
  const strReactNative = "ReactNative";
32
32
  const strMsie = "msie";
33
33
  const strTrident = "trident/";
34
+ const strXMLHttpRequest = "XMLHttpRequest";
34
35
 
35
36
  let _isTrident: boolean = null;
36
37
  let _navUserAgentCheck: string = null;
@@ -371,8 +372,7 @@ export function isSafari(userAgentStr ?: string) {
371
372
  export function isFetchSupported(withKeepAlive?: boolean): boolean {
372
373
  let isSupported = false;
373
374
  try {
374
- const fetchApi = getGlobalInst("fetch");
375
- isSupported = !!fetchApi;
375
+ isSupported = !!getGlobalInst("fetch");
376
376
  const request = getGlobalInst("Request");
377
377
  if (isSupported && withKeepAlive && request) {
378
378
  isSupported = _hasProperty(request, "keepalive");
@@ -386,9 +386,9 @@ export function isFetchSupported(withKeepAlive?: boolean): boolean {
386
386
 
387
387
  export function useXDomainRequest(): boolean | undefined {
388
388
  if (_useXDomainRequest === null) {
389
- _useXDomainRequest = (typeof XDomainRequest !== "undefined");
389
+ _useXDomainRequest = (typeof XDomainRequest !== strShimUndefined);
390
390
  if (_useXDomainRequest && isXhrSupported()) {
391
- _useXDomainRequest = _useXDomainRequest && !_hasProperty(getGlobalInst("XMLHttpRequest"), "withCredentials");
391
+ _useXDomainRequest = _useXDomainRequest && !_hasProperty(getGlobalInst(strXMLHttpRequest), "withCredentials");
392
392
  }
393
393
  }
394
394
 
@@ -402,7 +402,7 @@ export function useXDomainRequest(): boolean | undefined {
402
402
  export function isXhrSupported(): boolean {
403
403
  let isSupported = false;
404
404
  try {
405
- const xmlHttpRequest = getGlobalInst("XMLHttpRequest");
405
+ const xmlHttpRequest = getGlobalInst(strXMLHttpRequest);
406
406
  isSupported = !!xmlHttpRequest;
407
407
  } catch (e) {
408
408
  // Just Swallow any failure during availability checks