Skip to content

Commit

Permalink
[Bug] Fix issues related to dynamic config listeners during unloading (
Browse files Browse the repository at this point in the history
…#2058)

* [Bug] Fix issues related to dynamic config listeners during unloading
- Add Promise support during unloading

* Update channels/tee-channel-js/src/TeeChannel.ts

Co-authored-by: siyuniu-ms <123212536+siyuniu-ms@users.noreply.github.com>

---------

Co-authored-by: siyuniu-ms <123212536+siyuniu-ms@users.noreply.github.com>
  • Loading branch information
MSNev and siyuniu-ms committed Apr 28, 2023
1 parent 95b052d commit e86c346
Show file tree
Hide file tree
Showing 48 changed files with 799 additions and 375 deletions.
5 changes: 3 additions & 2 deletions AISKU/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ See [Breaking Changes](./BETA_BREAKING_CHANGES.md)
| Version | Full Size | Raw Minified | GZip Size
|---------|-----------|--------------|-------------
| [&lt;nightly3&gt;](https://github.com/microsoft/ApplicationInsights-JS/tree/main/AISKU) | [![full size size](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.3-nightly3.js.svg?label=full%20size&color=blue)](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.3-nightly3.js.svg?label=full%20size&color=blue)| ![minified size size](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.3-nightly3.min.js.svg?label=minified%20size&color=darkorchid) | ![gzip size](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.3-nightly3.min.js.svg?compression=gzip&softmax=30000&max=35000)
| &lt;nightly&gt; | [![full size size](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.2-nightly.js.svg?label=full%20size&color=blue)](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.2-nightly.js.svg?label=full%20size&color=blue)| ![minified size size](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.2-nightly.min.js.svg?label=minified%20size&color=darkorchid) | ![gzip size](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.2-nightly.min.js.svg?compression=gzip&softmax=30000&max=35000)
| 2.8.12: | [![full size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.12.js.svg?label=full%20size&color=blue)](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.12.js.svg?label=full%20size&color=blue)| ![minified size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.12.min.js.svg?label=minified%20size&color=darkorchid) | ![gzip size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.12.min.js.svg?compression=gzip&softmax=30000&max=35000)
| 3.0.0: | [![full size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.3.0.0.js.svg?label=full%20size&color=blue)](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.3.0.0.js.svg?label=full%20size&color=blue)| ![minified size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.3.0.0.min.js.svg?label=minified%20size&color=darkorchid) | ![gzip size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.3.0.0.min.js.svg?compression=gzip&softmax=30000&max=35000)
| [&lt;nightly&gt;](https://github.com/microsoft/ApplicationInsights-JS/tree/master/AISKU) | [![full size size](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.2-nightly.js.svg?label=full%20size&color=blue)](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.2-nightly.js.svg?label=full%20size&color=blue)| ![minified size size](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.2-nightly.min.js.svg?label=minified%20size&color=darkorchid) | ![gzip size](https://img.badgesize.io/https://js.monitor.azure.com/nightly/ai.2-nightly.min.js.svg?compression=gzip&softmax=30000&max=35000)
| [2.8.12](https://github.com/microsoft/ApplicationInsights-JS/tree/master/AISKU): | [![full size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.12.js.svg?label=full%20size&color=blue)](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.12.js.svg?label=full%20size&color=blue)| ![minified size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.12.min.js.svg?label=minified%20size&color=darkorchid) | ![gzip size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.12.min.js.svg?compression=gzip&softmax=30000&max=35000)
| 2.8.11: | [![full size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.11.js.svg?label=full%20size&color=blue)](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.11.js.svg?label=full%20size&color=blue)| ![minified size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.11.min.js.svg?label=minified%20size&color=darkorchid) | ![gzip size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.11.min.js.svg?compression=gzip&softmax=30000&max=35000)
| 2.8.10: | [![full size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.10.js.svg?label=full%20size&color=blue)](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.10.js.svg?label=full%20size&color=blue)| ![minified size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.10.min.js.svg?label=minified%20size&color=darkorchid) | ![gzip size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.10.min.js.svg?compression=gzip&softmax=30000&max=35000)
| 2.8.9: | [![full size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.9.js.svg?label=full%20size&color=blue)](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.9.js.svg?label=full%20size&color=blue)| ![minified size size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.9.min.js.svg?label=minified%20size&color=darkorchid) | ![gzip size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.8.9.min.js.svg?compression=gzip&softmax=30000&max=35000)
Expand Down
6 changes: 3 additions & 3 deletions AISKU/Tests/Manual/HelloWorld.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ <h1 class="display-4">Welcome</h1>
<textarea id="log" style="width:45%; min-height: 400px;"></textarea>
<textarea id="cfg" style="width:50%; min-height: 400px;"></textarea>
</div>
</div>

<script>
//Promise = null;
var _message = {
log: "",
cfg: ""
Expand All @@ -69,7 +69,7 @@ <h1 class="display-4">Welcome</h1>
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> -->

<!-- <script src="file://./ai.2.8.0.js"></script> -->
<script src="http://localhost:9001/AISKU/browser/es5/ai.2.js"></script>
<script src="http://localhost:9001/AISKU/browser/es5/ai.3.js"></script>
<!-- <script src="https://js.monitor.azure.com/scripts/b/ai.2.7.4.js" crossorigin="anonymous"></script> -->
<!-- <script src="https://js.monitor.azure.com/scripts/b/ai.2.8.0.js" crossorigin="anonymous"></script> -->
<!-- <script>
Expand All @@ -83,7 +83,7 @@ <h1 class="display-4">Welcome</h1>
// ld: 0, // Defines the load delay (in ms) before attempting to load the sdk. -1 = block page load and add to head. (default) = 0ms load after timeout,
// useXhr: 1, // Use XHR instead of fetch to report failures (if available),
// crossOrigin: "anonymous", // When supplied this will add the provided value as the cross origin attribute on the script tag
// onInit: null, // Once the application insights instance has loaded and initialized this callback function will be called with 1 argument -- the sdk instance (DO NOT ADD anything to the sdk.queue -- As they won't get called)
// onInit: null, // Once the application insights instance has loaded and initialized this callback function will be called with 1 argument - the sdk instance (DO NOT ADD anything to the sdk.queue - As they won't get called)
cfg: { // Application Insights Configuration
connectionString: "InstrumentationKey=" + instrumentationKey + ";IngestionEndpoint=http://localhost:9001",
//extensions: [reactPlugin],
Expand Down
8 changes: 4 additions & 4 deletions AISKU/Tests/Unit/src/AISKUSize.Tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { Snippet } from "../../../src/Snippet";
import { utlRemoveSessionStorage } from "@microsoft/applicationinsights-common";

export class AISKUSizeCheck extends AITestClass {
private readonly MAX_RAW_SIZE = 119;
private readonly MAX_BUNDLE_SIZE = 119;
private readonly MAX_RAW_DEFLATE_SIZE = 47;
private readonly MAX_BUNDLE_DEFLATE_SIZE = 47;
private readonly MAX_RAW_SIZE = 122;
private readonly MAX_BUNDLE_SIZE = 122;
private readonly MAX_RAW_DEFLATE_SIZE = 50;
private readonly MAX_BUNDLE_DEFLATE_SIZE = 50;
private readonly rawFilePath = "../dist/es5/applicationinsights-web.min.js";
// Automatically updated by version scripts
private readonly currentVer = "3.0.0";
Expand Down
3 changes: 2 additions & 1 deletion AISKU/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@
"@microsoft/applicationinsights-core-js": "3.0.0",
"@microsoft/applicationinsights-dependencies-js": "3.0.0",
"@microsoft/applicationinsights-properties-js": "3.0.0",
"@nevware21/ts-utils": ">= 0.9.4 < 2.x"
"@nevware21/ts-utils": ">= 0.9.5 < 2.x",
"@nevware21/ts-async": ">= 0.2.4 < 2.x"
},
"license": "MIT"
}
79 changes: 66 additions & 13 deletions AISKU/src/AISku.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ import {
AppInsightsCore, IAppInsightsCore, IChannelControls, IConfigDefaults, IConfiguration, ICookieMgr, ICustomProperties, IDiagnosticLogger,
IDistributedTraceContext, IDynamicConfigHandler, ILoadedPlugin, INotificationManager, IPlugin, ITelemetryInitializerHandler,
ITelemetryItem, ITelemetryPlugin, ITelemetryUnloadState, IUnloadHook, UnloadHandler, WatcherFunction, _eInternalMessageId,
_throwInternal, addPageHideEventListener, addPageUnloadEventListener, arrForEach, arrIndexOf, cfgDfValidate, createDynamicConfig,
createUniqueNamespace, doPerf, eLoggingSeverity, hasDocument, hasWindow, isArray, isFunction, isNullOrUndefined, isReactNative, isString,
mergeEvtNamespace, objForEachKey, onConfigChange, proxyAssign, proxyFunctions, removePageHideEventListener,
removePageUnloadEventListener
_throwInternal, addPageHideEventListener, addPageUnloadEventListener, cfgDfValidate, createDynamicConfig, createUniqueNamespace, doPerf,
eLoggingSeverity, hasDocument, hasWindow, isArray, isFunction, isNullOrUndefined, isReactNative, isString, mergeEvtNamespace,
onConfigChange, proxyAssign, proxyFunctions, removePageHideEventListener, removePageUnloadEventListener
} from "@microsoft/applicationinsights-core-js";
import {
AjaxPlugin as DependenciesPlugin, DependencyInitializerFunction, DependencyListenerFunction, IDependencyInitializerHandler,
IDependencyListenerHandler
} from "@microsoft/applicationinsights-dependencies-js";
import { PropertiesPlugin } from "@microsoft/applicationinsights-properties-js";
import { objDefine, strIndexOf, throwUnsupported } from "@nevware21/ts-utils";
import { IPromise, createPromise } from "@nevware21/ts-async";
import { arrForEach, arrIndexOf, objDefine, objForEachKey, strIndexOf, throwUnsupported } from "@nevware21/ts-utils";
import { IApplicationInsights } from "./IApplicationInsights";
import {
STR_ADD_TELEMETRY_INITIALIZER, STR_CLEAR_AUTHENTICATED_USER_CONTEXT, STR_EVT_NAMESPACE, STR_GET_COOKIE_MGR, STR_GET_PLUGIN,
Expand Down Expand Up @@ -169,12 +169,36 @@ export class AppInsightsSku implements IApplicationInsights {

_self.snippet = snippet;

_self.flush = (async: boolean = true) => {
_self.flush = (async: boolean = true, callBack?: () => void) => {
let result: void | IPromise<void>;

doPerf(_core, () => "AISKU.flush", () => {
if (async && !callBack) {
result = createPromise((resolve) => {
callBack = resolve;
});
}

let waiting = 1;
const flushDone = () => {
waiting --;
if (waiting === 0) {
callBack();
}
};

arrForEach(_core.getChannels(), channel => {
channel.flush(async);
if (channel) {
waiting++;
channel.flush(async, flushDone);
}
});

// decrement the initial "waiting"
flushDone();
}, null, async);

return result;
};

_self.onunloadFlush = (async: boolean = true) => {
Expand Down Expand Up @@ -352,8 +376,15 @@ export class AppInsightsSku implements IApplicationInsights {
return _sender;
};

_self.unload = (isAsync?: boolean, unloadComplete?: (unloadState: ITelemetryUnloadState) => void, cbTimeout?: number): void => {
_self.unload = (isAsync?: boolean, unloadComplete?: (unloadState: ITelemetryUnloadState) => void, cbTimeout?: number): void | IPromise<ITelemetryUnloadState> => {
let unloadDone = false;
let result: IPromise<ITelemetryUnloadState>;
if (isAsync && !unloadComplete) {
result = createPromise<ITelemetryUnloadState>((resolve) => {
// Set the callback to the promise resolve callback
unloadComplete = resolve;
});
}

function _unloadCallback(unloadState: ITelemetryUnloadState) {
if (!unloadDone) {
Expand All @@ -369,6 +400,8 @@ export class AppInsightsSku implements IApplicationInsights {
_removePageEventHandlers();

_core.unload && _core.unload(isAsync, _unloadCallback, cbTimeout);

return result;
};

proxyFunctions(_self, _analyticsPlugin, [
Expand Down Expand Up @@ -602,11 +635,20 @@ export class AppInsightsSku implements IApplicationInsights {
// Misc

/**
* Manually trigger an immediate send of all telemetry still in the buffer.
* @param [async=true]
* @memberof Initialization
* Attempt to flush data immediately; If executing asynchronously (the default) and
* you DO NOT pass a callback function then a [IPromise](https://nevware21.github.io/ts-async/typedoc/interfaces/IPromise.html)
* will be returned which will resolve once the flush is complete. The actual implementation of the `IPromise`
* will be a native Promise (if supported) or the default as supplied by [ts-async library](https://github.com/nevware21/ts-async)
* @param async - send data asynchronously when true
* @param callBack - if specified, notify caller when send is complete, the channel should return true to indicate to the caller that it will be called.
* If the caller doesn't return true the caller should assume that it may never be called.
* @returns - If a callback is provided `true` to indicate that callback will be called after the flush is complete otherwise the caller
* should assume that any provided callback will never be called, Nothing or if occurring asynchronously a
* [IPromise](https://nevware21.github.io/ts-async/typedoc/interfaces/IPromise.html) which will be resolved once the unload is complete,
* the [IPromise](https://nevware21.github.io/ts-async/typedoc/interfaces/IPromise.html) will only be returned when no callback is provided
* and async is true.
*/
public flush(async: boolean = true) {
public flush(async?: boolean, callBack?: () => void): void | IPromise<void> {
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
}

Expand Down Expand Up @@ -673,8 +715,19 @@ export class AppInsightsSku implements IApplicationInsights {
* approach is to create a new instance and initialize that instance.
* This is due to possible unexpected side effects caused by plugins not supporting unload / teardown, unable
* to successfully remove any global references or they may just be completing the unload process asynchronously.
* If you pass isAsync as true and do not provide
* If you pass isAsync as `true` (also the default) and DO NOT pass a callback function then an [IPromise](https://nevware21.github.io/ts-async/typedoc/interfaces/IPromise.html)
* will be returned which will resolve once the unload is complete. The actual implementation of the `IPromise`
* will be a native Promise (if supported) or the default as supplied by [ts-async library](https://github.com/nevware21/ts-async)
* @param isAsync - Can the unload be performed asynchronously (default)
* @param unloadComplete - An optional callback that will be called once the unload has completed
* @param cbTimeout - An optional timeout to wait for any flush operations to complete before proceeding with the
* unload. Defaults to 5 seconds.
* @return Nothing or if occurring asynchronously a [IPromise](https://nevware21.github.io/ts-async/typedoc/interfaces/IPromise.html)
* which will be resolved once the unload is complete, the [IPromise](https://nevware21.github.io/ts-async/typedoc/interfaces/IPromise.html)
* will only be returned when no callback is provided and isAsync is true
*/
public unload(isAsync?: boolean, unloadComplete?: () => void): void {
public unload(isAsync?: boolean, unloadComplete?: (unloadState: ITelemetryUnloadState) => void, cbTimeout?: number): void | IPromise<ITelemetryUnloadState> {
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
return null;
}
Expand Down
Loading

0 comments on commit e86c346

Please sign in to comment.