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

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 (122) hide show
  1. package/browser/applicationinsights-core-js.integrity.json +9 -9
  2. package/browser/applicationinsights-core-js.js +945 -479
  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 +3904 -877
  7. package/dist/applicationinsights-core-js.api.md +264 -30
  8. package/dist/applicationinsights-core-js.d.ts +410 -89
  9. package/dist/applicationinsights-core-js.js +945 -479
  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 +410 -89
  14. package/dist-esm/JavaScriptSDK/AppInsightsCore.js +1 -1
  15. package/dist-esm/JavaScriptSDK/BaseCore.js +66 -23
  16. package/dist-esm/JavaScriptSDK/BaseCore.js.map +1 -1
  17. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js +44 -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 +184 -110
  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.Enums/EventsDiscardedReason.js +1 -1
  52. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js +90 -96
  53. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js.map +1 -1
  54. package/dist-esm/JavaScriptSDK.Enums/SendRequestReason.js +1 -1
  55. package/dist-esm/JavaScriptSDK.Enums/TelemetryUnloadReason.js +8 -0
  56. package/dist-esm/JavaScriptSDK.Enums/TelemetryUnloadReason.js.map +1 -0
  57. package/dist-esm/JavaScriptSDK.Interfaces/IAppInsightsCore.js +1 -1
  58. package/dist-esm/JavaScriptSDK.Interfaces/IChannelControls.js +1 -1
  59. package/dist-esm/JavaScriptSDK.Interfaces/IConfiguration.js +1 -1
  60. package/dist-esm/JavaScriptSDK.Interfaces/ICookieMgr.js +1 -1
  61. package/dist-esm/JavaScriptSDK.Interfaces/IDbgExtension.js +1 -1
  62. package/dist-esm/JavaScriptSDK.Interfaces/IDiagnosticLogger.js +1 -1
  63. package/dist-esm/JavaScriptSDK.Interfaces/IInstrumentHooks.js +1 -1
  64. package/dist-esm/JavaScriptSDK.Interfaces/INotificationListener.js +1 -1
  65. package/dist-esm/JavaScriptSDK.Interfaces/INotificationManager.js +1 -1
  66. package/dist-esm/JavaScriptSDK.Interfaces/IPerfEvent.js +1 -1
  67. package/dist-esm/JavaScriptSDK.Interfaces/IPerfManager.js +1 -1
  68. package/dist-esm/JavaScriptSDK.Interfaces/IProcessTelemetryContext.js +1 -1
  69. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryInitializers.js +1 -1
  70. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryItem.js +1 -1
  71. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPlugin.js +1 -1
  72. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js +1 -2
  73. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js.map +1 -1
  74. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUnloadState.js +8 -0
  75. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUnloadState.js.map +1 -0
  76. package/dist-esm/applicationinsights-core-js.js +8 -4
  77. package/dist-esm/applicationinsights-core-js.js.map +1 -1
  78. package/package.json +1 -1
  79. package/src/JavaScriptSDK/BaseCore.ts +80 -24
  80. package/src/JavaScriptSDK/BaseTelemetryPlugin.ts +76 -5
  81. package/src/JavaScriptSDK/ChannelController.ts +107 -61
  82. package/src/JavaScriptSDK/CookieMgr.ts +4 -4
  83. package/src/JavaScriptSDK/CoreUtils.ts +6 -143
  84. package/src/JavaScriptSDK/DataCacheHelper.ts +106 -0
  85. package/src/JavaScriptSDK/DiagnosticLogger.ts +12 -11
  86. package/src/JavaScriptSDK/EnvUtils.ts +7 -6
  87. package/src/JavaScriptSDK/EventHelpers.ts +542 -0
  88. package/src/JavaScriptSDK/HelperFuncs.ts +35 -54
  89. package/src/JavaScriptSDK/InternalConstants.ts +26 -0
  90. package/src/JavaScriptSDK/NotificationManager.ts +7 -11
  91. package/src/JavaScriptSDK/ProcessTelemetryContext.ts +237 -124
  92. package/src/JavaScriptSDK/RandomHelper.ts +2 -1
  93. package/src/JavaScriptSDK/TelemetryHelpers.ts +47 -15
  94. package/src/JavaScriptSDK/TelemetryInitializerPlugin.ts +5 -15
  95. package/src/JavaScriptSDK.Enums/LoggingEnums.ts +184 -87
  96. package/src/JavaScriptSDK.Enums/TelemetryUnloadReason.ts +27 -0
  97. package/src/JavaScriptSDK.Interfaces/IAppInsightsCore.ts +20 -0
  98. package/src/JavaScriptSDK.Interfaces/IChannelControls.ts +9 -2
  99. package/src/JavaScriptSDK.Interfaces/IProcessTelemetryContext.ts +55 -16
  100. package/src/JavaScriptSDK.Interfaces/ITelemetryPlugin.ts +16 -9
  101. package/src/JavaScriptSDK.Interfaces/ITelemetryPluginChain.ts +9 -11
  102. package/src/JavaScriptSDK.Interfaces/ITelemetryUnloadState.ts +10 -0
  103. package/types/JavaScriptSDK/BaseCore.d.ts +4 -0
  104. package/types/JavaScriptSDK/BaseTelemetryPlugin.d.ts +20 -1
  105. package/types/JavaScriptSDK/ChannelController.d.ts +4 -0
  106. package/types/JavaScriptSDK/CoreUtils.d.ts +1 -42
  107. package/types/JavaScriptSDK/DataCacheHelper.d.ts +13 -0
  108. package/types/JavaScriptSDK/EventHelpers.d.ts +152 -0
  109. package/types/JavaScriptSDK/HelperFuncs.d.ts +8 -17
  110. package/types/JavaScriptSDK/InternalConstants.d.ts +20 -0
  111. package/types/JavaScriptSDK/ProcessTelemetryContext.d.ts +10 -3
  112. package/types/JavaScriptSDK/TelemetryHelpers.d.ts +8 -0
  113. package/types/JavaScriptSDK/TelemetryInitializerPlugin.d.ts +0 -7
  114. package/types/JavaScriptSDK.Enums/LoggingEnums.d.ts +91 -2
  115. package/types/JavaScriptSDK.Enums/TelemetryUnloadReason.d.ts +9 -0
  116. package/types/JavaScriptSDK.Interfaces/IAppInsightsCore.d.ts +17 -0
  117. package/types/JavaScriptSDK.Interfaces/IChannelControls.d.ts +9 -2
  118. package/types/JavaScriptSDK.Interfaces/IProcessTelemetryContext.d.ts +49 -14
  119. package/types/JavaScriptSDK.Interfaces/ITelemetryPlugin.d.ts +15 -8
  120. package/types/JavaScriptSDK.Interfaces/ITelemetryPluginChain.d.ts +9 -10
  121. package/types/JavaScriptSDK.Interfaces/ITelemetryUnloadState.d.ts +6 -0
  122. package/types/applicationinsights-core-js.d.ts +6 -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) {
@@ -39,65 +55,74 @@ function _getNextProxyStart(proxy: ITelemetryPluginChain, config: IConfiguration
39
55
  return createTelemetryProxyChain([startAt], config, core);
40
56
  }
41
57
 
42
- /**
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
47
- */
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;
60
- }
58
+ function _createInternalContext<T extends IBaseProcessingContext>(telemetryChain: ITelemetryPluginChain, config: IConfiguration, core:IAppInsightsCore, startAt?: IPlugin): IInternalContext<T> {
59
+ // We have a special case where we want to start execution from this specific plugin
60
+ // or we simply reuse the existing telemetry plugin chain (normal execution case)
61
+ let _nextProxy: ITelemetryPluginChain = startAt ? _getNextProxyStart(telemetryChain, config, core, startAt) : telemetryChain;
62
+ let _onComplete: OnCompleteCallback[] = [];
63
+
64
+ let context: IInternalContext<T> = {
65
+ _next: _moveNext,
66
+ ctx: {
67
+ core: () => { return core },
68
+ diagLog: () => {
69
+ return safeGetLogger(core, config);
70
+ },
71
+ getCfg: () => {
72
+ return config;
73
+ },
74
+ getExtCfg: _getExtCfg,
75
+ getConfig: _getConfig,
76
+ hasNext: () => {
77
+ return !!_nextProxy;
78
+ },
79
+ getNext: () => {
80
+ return _nextProxy;
81
+ },
82
+ setNext: (nextPlugin:ITelemetryPluginChain) => {
83
+ _nextProxy = nextPlugin;
84
+ },
85
+ iterate: _iterateChain,
86
+ onComplete: _addOnComplete
87
+ } as T
88
+ };
61
89
 
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);
90
+ function _addOnComplete(onComplete: Function, that?: any, ...args: any[]) {
91
+ if (onComplete) {
92
+ _onComplete.push({
93
+ func: onComplete,
94
+ self: !isUndefined(that) ? that : context.ctx,
95
+ args: args
87
96
  });
88
- },
89
- iterate: _iterateChain,
90
- createNew: (plugins: IPlugin[] | ITelemetryPluginChain = null, startAt?: IPlugin) => {
91
- if (isArray(plugins)) {
92
- plugins = createTelemetryProxyChain(plugins, config, core, startAt);
93
- }
97
+ }
98
+ }
94
99
 
95
- return createProcessTelemetryContext(plugins || _nextProxy, config, core, startAt);
96
- },
97
- onComplete: (onComplete: () => void) => {
98
- _onComplete = onComplete;
100
+ function _moveNext() {
101
+ let nextProxy = _nextProxy;
102
+
103
+ // Automatically move to the next plugin
104
+ _nextProxy = nextProxy ? nextProxy.getNext() : null;
105
+
106
+ if (!nextProxy) {
107
+ let onComplete = _onComplete;
108
+ if (onComplete && onComplete.length > 0) {
109
+ arrForEach(onComplete, (completeDetails) => {
110
+ try {
111
+ completeDetails.func.call(completeDetails.self, completeDetails.args);
112
+ } catch (e) {
113
+ core.logger.throwInternal(
114
+ eLoggingSeverity.WARNING,
115
+ _eInternalMessageId.PluginException,
116
+ "Unexpected Exception during onComplete - " + dumpObj(e));
117
+ }
118
+ });
119
+
120
+ _onComplete = [];
121
+ }
99
122
  }
100
- };
123
+
124
+ return nextProxy;
125
+ }
101
126
 
102
127
  function _getExtCfg<T>(identifier: string, defaultValue: T|any = {}, mergeDefault: GetExtCfgMergeType = GetExtCfgMergeType.None) {
103
128
  let theConfig: T;
@@ -147,36 +172,86 @@ export function createProcessTelemetryContext(telemetryChain: ITelemetryPluginCh
147
172
  return !isNullOrUndefined(theValue) ? theValue : defaultValue;
148
173
  }
149
174
 
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;
175
+ function _iterateChain<T extends ITelemetryPlugin = ITelemetryPlugin>(cb: (plugin: T) => void) {
176
+ // Keep processing until we reach the end of the chain
177
+ let nextPlugin: ITelemetryPluginChain;
178
+ while(!!(nextPlugin = context._next())) {
179
+ let plugin = nextPlugin.getPlugin();
180
+ if (plugin) {
181
+ // callback with the current on
182
+ cb(plugin as T);
161
183
  }
162
184
  }
163
185
  }
164
186
 
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
- });
187
+ return context;
188
+ }
189
+
190
+ /**
191
+ * Creates a new Telemetry Item context with the current config, core and plugin execution chain
192
+ * @param plugins - The plugin instances that will be executed
193
+ * @param config - The current config
194
+ * @param core - The current core instance
195
+ */
196
+ export function createProcessTelemetryContext(telemetryChain: ITelemetryPluginChain, config: IConfiguration, core:IAppInsightsCore, startAt?: IPlugin): IProcessTelemetryContext {
197
+
198
+ let internalContext: IInternalContext<IProcessTelemetryContext> = _createInternalContext<IProcessTelemetryContext>(telemetryChain, config, core, startAt);
199
+ let context = internalContext.ctx;
200
+
201
+ function _processNext(env: ITelemetryItem) {
202
+ let nextPlugin: ITelemetryPluginChain = internalContext._next();
203
+ // Run the next plugin which will call "processNext()"
204
+ nextPlugin && nextPlugin.processTelemetry(env, context);
205
+
206
+ return !nextPlugin;
207
+ }
208
+
209
+ function _createNew(plugins: IPlugin[] | ITelemetryPluginChain = null, startAt?: IPlugin) {
210
+ if (isArray(plugins)) {
211
+ plugins = createTelemetryProxyChain(plugins, config, core, startAt);
212
+ }
213
+
214
+ return createProcessTelemetryContext(plugins || context.getNext(), config, core, startAt);
215
+ }
216
+
217
+ context.processNext = _processNext;
218
+ context.createNew = _createNew;
219
+
220
+ return context;
221
+ }
222
+
223
+ /**
224
+ * Creates a new Telemetry Item context with the current config, core and plugin execution chain for handling the unloading of the chain
225
+ * @param plugins - The plugin instances that will be executed
226
+ * @param config - The current config
227
+ * @param core - The current core instance
228
+ */
229
+ export function createProcessTelemetryUnloadContext(telemetryChain: ITelemetryPluginChain, config: IConfiguration, core:IAppInsightsCore, startAt?: IPlugin): IProcessTelemetryUnloadContext {
230
+ let internalContext: IInternalContext<IProcessTelemetryUnloadContext> = _createInternalContext<IProcessTelemetryUnloadContext>(telemetryChain, config, core, startAt);
231
+ let context = internalContext.ctx;
232
+
233
+ function _processNext(unloadState: ITelemetryUnloadState) {
234
+ let nextPlugin: ITelemetryPluginChain = internalContext._next();
235
+ nextPlugin && nextPlugin.unload(context, unloadState);
236
+
237
+ return !nextPlugin;
238
+ }
239
+
240
+ function _createNew(plugins: IPlugin[] | ITelemetryPluginChain = null, startAt?: IPlugin): IProcessTelemetryUnloadContext {
241
+ if (isArray(plugins)) {
242
+ plugins = createTelemetryProxyChain(plugins, config, core, startAt);
174
243
  }
244
+
245
+ return createProcessTelemetryUnloadContext(plugins || context.getNext(), config, core, startAt);
175
246
  }
176
247
 
248
+ context.processNext = _processNext;
249
+ context.createNew = _createNew
250
+
177
251
  return context;
178
252
  }
179
253
 
254
+
180
255
  /**
181
256
  * Creates an execution chain from the array of plugins
182
257
  * @param plugins - The array of plugins that will be executed in this order
@@ -250,34 +325,38 @@ export function createTelemetryPluginProxy(plugin: ITelemetryPlugin, config: ICo
250
325
  return nextProxy;
251
326
  },
252
327
  processTelemetry: _processTelemetry,
328
+ unload: _unloadPlugin,
253
329
  _id: chainId,
254
330
  _setNext: (nextPlugin: IInternalTelemetryPluginChain) => {
255
331
  nextProxy = nextPlugin;
256
332
  }
257
333
  };
258
334
 
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) {
335
+ function _getTelCtx() {
336
+ let itemCtx: IProcessTelemetryContext;
266
337
 
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
- }
338
+ // Looks like a plugin didn't pass the (optional) context, so create a new one
339
+ if (plugin && isFunction(plugin[strGetTelCtx])) {
340
+ // This plugin extends from the BaseTelemetryPlugin so lets use it
341
+ itemCtx = plugin[strGetTelCtx]();
342
+ }
274
343
 
275
- if (!itemCtx) {
276
- // Create a temporary one
277
- itemCtx = createProcessTelemetryContext(proxyChain, config, core);
278
- }
344
+ if (!itemCtx) {
345
+ // Create a temporary one
346
+ itemCtx = createProcessTelemetryContext(proxyChain, config, core);
279
347
  }
280
348
 
349
+ return itemCtx;
350
+ }
351
+
352
+ function _processChain<T extends IBaseProcessingContext>(
353
+ itemCtx: T,
354
+ processPluginFn: (itemCtx: T) => boolean,
355
+ name: string,
356
+ details: () => any,
357
+ isAsync: boolean) {
358
+
359
+ let hasRun = false;
281
360
  let identifier = plugin ? plugin.identifier : strTelemetryPluginChain;
282
361
  let hasRunContext = itemCtx[strHasRunFlags];
283
362
  if (!hasRunContext) {
@@ -285,18 +364,17 @@ export function createTelemetryPluginProxy(plugin: ITelemetryPlugin, config: ICo
285
364
  hasRunContext = itemCtx[strHasRunFlags] = {};
286
365
  }
287
366
 
288
- doPerf(itemCtx.core(), () => identifier + ":" + name, () => {
289
- // Mark this component as having run
290
- hasRunContext[chainId] = true;
291
- let hasRun = false;
367
+ // Ensure that we keep the context in sync
368
+ itemCtx.setNext(nextProxy);
292
369
 
293
- // Ensure that we keep the context in sync
294
- itemCtx.setNext(nextProxy);
370
+ if (plugin) {
371
+ doPerf(itemCtx[strCore](), () => identifier + ":" + name, () => {
372
+ // Mark this component as having run
373
+ hasRunContext[chainId] = true;
295
374
 
296
- if (plugin) {
297
375
  try {
298
376
  // Set a flag on the next plugin so we know if it was attempted to be executed
299
- let nextId = nextProxy ? nextProxy._id : "";
377
+ let nextId = nextProxy ? nextProxy._id : strEmpty;
300
378
  if (nextId) {
301
379
  hasRunContext[nextId] = false;
302
380
  }
@@ -314,24 +392,27 @@ export function createTelemetryPluginProxy(plugin: ITelemetryPlugin, config: ICo
314
392
  // Either we have no next plugin or the current one did not attempt to call the next plugin
315
393
  // Which means the current one is the root of the failure so log/report this failure
316
394
  itemCtx.diagLog().throwInternal(
317
- LoggingSeverity.CRITICAL,
318
- _InternalMessageId.PluginException,
395
+ eLoggingSeverity.CRITICAL,
396
+ _eInternalMessageId.PluginException,
319
397
  "Plugin [" + plugin.identifier + "] failed during " + name + " - " + dumpObj(error) + ", run flags: " + dumpObj(hasRunContext));
320
398
  }
321
399
  }
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);
400
+ }, details, isAsync);
401
+ }
402
+
403
+ return hasRun;
330
404
  }
331
405
 
332
406
  function _processTelemetry(env: ITelemetryItem, itemCtx: IProcessTelemetryContext) {
333
- _processChain(itemCtx, (itemCtx: IProcessTelemetryContext) => {
334
- if (!hasProcessTelemetry) {
407
+ itemCtx = itemCtx || _getTelCtx();
408
+
409
+ function _callProcessTelemetry(itemCtx: IProcessTelemetryContext) {
410
+ if (!plugin || !hasProcessTelemetry) {
411
+ return false;
412
+ }
413
+
414
+ let pluginState = _getPluginState(plugin);
415
+ if (pluginState[strTeardown] || pluginState[strDisabled]) {
335
416
  return false;
336
417
  }
337
418
 
@@ -345,14 +426,46 @@ export function createTelemetryPluginProxy(plugin: ITelemetryPlugin, config: ICo
345
426
 
346
427
  plugin.processTelemetry(env, itemCtx);
347
428
 
429
+ // Process Telemetry is expected to call itemCtx.processNext() or nextPlugin.processTelemetry()
348
430
  return true;
349
- },
350
- (itemCtx: IProcessTelemetryContext) => {
351
- // The underlying plugin is either not defined or does not have a processTelemetry implementation
431
+ }
432
+
433
+ if (!_processChain(itemCtx, _callProcessTelemetry, "processTelemetry", () => ({ item: env }), !((env as any).sync))) {
434
+ // The underlying plugin is either not defined, not enabled or does not have a processTelemetry implementation
352
435
  // so we still want the next plugin to be executed.
353
- nextProxy.processTelemetry(env, itemCtx);
354
- },
355
- "processTelemetry", () => ({ item: env }), !((env as any).sync));
436
+ itemCtx.processNext(env);
437
+ }
438
+ }
439
+
440
+ function _unloadPlugin(unloadCtx: IProcessTelemetryUnloadContext, unloadState: ITelemetryUnloadState) {
441
+
442
+ function _callTeardown() {
443
+ // Setting default of hasRun as false so the proxyProcessFn() is called as teardown() doesn't have to exist or call unloadNext().
444
+ let hasRun = false;
445
+ if (plugin) {
446
+ let pluginState = _getPluginState(plugin);
447
+ let pluginCore = plugin[strCore] || pluginState.core;
448
+ // Only teardown the plugin if it was initialized by the current core (i.e. It's not a shared plugin)
449
+ if (plugin && (!pluginCore || pluginCore === unloadCtx[strCore]()) && !pluginState[strTeardown]) {
450
+ // Handle plugins that don't extend from the BaseTelemetryPlugin
451
+ pluginState[strCore] = null;
452
+ pluginState[strTeardown] = true;
453
+ pluginState[strIsInitialized] = false;
454
+
455
+ if (plugin[strTeardown] && plugin[strTeardown](unloadCtx, unloadState) === true) {
456
+ // plugin told us that it was going to (or has) call unloadCtx.processNext()
457
+ hasRun = true;
458
+ }
459
+ }
460
+ }
461
+
462
+ return hasRun;
463
+ }
464
+
465
+ if (!_processChain(unloadCtx, _callTeardown, "unload", () => {}, unloadState.isAsync)) {
466
+ // Only called if we hasRun was not true
467
+ unloadCtx.processNext(unloadState);
468
+ }
356
469
  }
357
470
 
358
471
  return objFreeze(proxyChain);
@@ -404,8 +517,9 @@ export class ProcessTelemetryContext implements IProcessTelemetryContext {
404
517
  * @param itemCtx - This is the context for the current request, ITelemetryPlugin instances
405
518
  * can optionally use this to access the current core instance or define / pass additional information
406
519
  * to later plugins (vs appending items to the telemetry item)
520
+ * @returns boolean (true) if there is no more plugins to process otherwise false or undefined (void)
407
521
  */
408
- public processNext: (env: ITelemetryItem) => void;
522
+ public processNext: (env: ITelemetryItem) => boolean | void;
409
523
 
410
524
  /**
411
525
  * Synchronously iterate over the context chain running the callback for each plugin, once
@@ -414,7 +528,6 @@ export class ProcessTelemetryContext implements IProcessTelemetryContext {
414
528
  */
415
529
  public iterate: <T extends ITelemetryPlugin = ITelemetryPlugin>(callback: (plugin: T) => void) => void;
416
530
 
417
- /**
418
531
  /**
419
532
  * Create a new context using the core and config from the current instance
420
533
  * @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);