Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
56644e9
Update Sender.ts
siyuniu-ms Dec 4, 2024
d3e5127
Update npm-shrinkwrap.json
siyuniu-ms Dec 4, 2024
d8e0a21
add 1ds change
siyuniu-ms Dec 19, 2024
00774e5
add config
siyuniu-ms Jan 14, 2025
f596055
add test
siyuniu-ms Jan 15, 2025
9dc8cf9
change sender back
siyuniu-ms Jan 15, 2025
1644e16
Update PostChannelTest.ts
siyuniu-ms Jan 15, 2025
298f39e
compress the code
siyuniu-ms Apr 1, 2025
15d773e
Update HttpManager.ts
siyuniu-ms Apr 1, 2025
7068cf2
Update README.md
siyuniu-ms Apr 1, 2025
4ad4884
change the way read the stream
siyuniu-ms Apr 8, 2025
619e654
Update PostChannelTest.ts
siyuniu-ms Apr 8, 2025
1618d15
Merge branch 'main' into siyu/compress
siyuniu-ms Apr 8, 2025
a55fe98
print out result for debug
siyuniu-ms Apr 8, 2025
14c0e86
Update PostChannelTest.ts
siyuniu-ms Apr 8, 2025
95c1ab5
Update HttpManager.ts
siyuniu-ms Apr 8, 2025
66ae546
Update HttpManager.ts
siyuniu-ms Apr 9, 2025
3d0672c
Update HttpManager.ts
siyuniu-ms Apr 9, 2025
eab5a63
Update PostChannelTest.ts
siyuniu-ms Apr 9, 2025
c189de2
Update DataCacheHelper.ts
siyuniu-ms Apr 10, 2025
8a648b4
Update DataCacheHelper.ts
siyuniu-ms Apr 10, 2025
34dae2c
add test and move to core
siyuniu-ms Apr 11, 2025
39202b9
Merge branch 'main' into siyu/compress
siyuniu-ms Apr 11, 2025
9ecb58c
Update HttpManager.ts
siyuniu-ms Apr 11, 2025
650b26b
Update AppInsightsCoreSize.Tests.ts
siyuniu-ms Apr 11, 2025
46ade96
Update SenderPostManager.ts
siyuniu-ms Apr 15, 2025
78523a6
Update AppInsightsCoreSize.Tests.ts
siyuniu-ms Apr 15, 2025
a3b2207
minify purpose
siyuniu-ms Apr 15, 2025
68124b5
Update AISKULightSize.Tests.ts
siyuniu-ms Apr 16, 2025
6f435b3
Update FileSizeCheckTest.ts
siyuniu-ms Apr 16, 2025
96f3cd6
Update AnalyticsExtensionSize.tests.ts
siyuniu-ms Apr 16, 2025
eaab4dc
Update AISKUSize.Tests.ts
siyuniu-ms Apr 16, 2025
cff99a3
Update AISKUSize.Tests.ts
siyuniu-ms Apr 16, 2025
40082a7
Merge branch 'main' into siyu/compress
siyuniu-ms Apr 22, 2025
78284ec
use cfg to control disablezip
siyuniu-ms Apr 22, 2025
7e9ed28
Update AISKUSize.Tests.ts
siyuniu-ms Apr 22, 2025
90be470
change the name
siyuniu-ms Apr 22, 2025
c6c8943
use isfeatureenabled
siyuniu-ms Apr 22, 2025
6851671
rebuilt
siyuniu-ms Apr 23, 2025
4c5c824
add more comments
siyuniu-ms Apr 23, 2025
67199f6
post channel test pass
siyuniu-ms Apr 25, 2025
f97327f
ai-channel test pass
siyuniu-ms Apr 25, 2025
2ae15d5
set aiskulight
siyuniu-ms Apr 25, 2025
cc3a87e
Update HelperFunc.Tests.ts
siyuniu-ms Apr 25, 2025
ffe370e
MERGE
siyuniu-ms Apr 25, 2025
7d60abd
udpate import
siyuniu-ms Apr 29, 2025
81ca9ab
Merge branch 'main' into siyu/compress
siyuniu-ms Apr 29, 2025
2bccd85
size
siyuniu-ms Apr 29, 2025
eaf8762
Update AISKUSize.Tests.ts
siyuniu-ms Apr 29, 2025
e8a12ad
add test for aiskuLight also
siyuniu-ms Apr 29, 2025
508edd6
remove zipPayload config
siyuniu-ms Apr 30, 2025
05584da
test update
siyuniu-ms Apr 30, 2025
c548408
readme update
siyuniu-ms Apr 30, 2025
4d2499a
remove zipPayload config
siyuniu-ms Apr 30, 2025
c0e2912
doc update
siyuniu-ms Apr 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -54,10 +54,10 @@ function _checkSize(checkType: string, maxSize: number, size: number, isNightly:
}

export class AISKUSizeCheck extends AITestClass {
private readonly MAX_RAW_SIZE = 146;
private readonly MAX_BUNDLE_SIZE = 146;
private readonly MAX_RAW_DEFLATE_SIZE = 58;
private readonly MAX_BUNDLE_DEFLATE_SIZE = 58;
private readonly MAX_RAW_SIZE = 147;
private readonly MAX_BUNDLE_SIZE = 147;
private readonly MAX_RAW_DEFLATE_SIZE = 59;
private readonly MAX_BUNDLE_DEFLATE_SIZE = 59;
private readonly rawFilePath = "../dist/es5/applicationinsights-web.min.js";
// Automatically updated by version scripts
private readonly currentVer = "3.3.6";
Expand Down
45 changes: 42 additions & 3 deletions AISKU/Tests/Unit/src/CdnThrottle.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,14 @@ export class CdnThrottle extends AITestClass {
offCfg: {
"throttleMgrCfg.106.disabled":true,
"throttleMgrCfg.109.disabled":true,
}
}},
}},
["zipPayload"]: {
mode: CdnFeatureMode.enable},
},
config: {
maxMessageLimit: 10,
throttleMgrCfg: throttleCfgDisable
throttleMgrCfg: throttleCfgDisable,

}
} as ICfgSyncConfig;
doc["res"] = new (doc as any).Response(JSON.stringify(cdnCfg), {
Expand Down Expand Up @@ -245,6 +248,42 @@ export class CdnThrottle extends AITestClass {
}, "response received", 60, 1000) as any)
});

this.testCaseAsync({
name: "CfgSyncPlugin: customer didn't set feature opt in, successfully get aisku default and fetch from config url, get disable zip config to be true",
stepDelay: 10,
useFakeTimers: true,
steps: [ () => {
let doc = getGlobal();
hookFetch((resolve) => { // global instance cannot access test private instance
AITestClass.orgSetTimeout(function() {
resolve( doc["res2"]);
}, 0);
});

let noSetconfig = {
instrumentationKey: TestInstrumentationKey,
extensionConfig : {["AppInsightsCfgSyncPlugin"] : {
syncMode: ICfgSyncMode.Receive,
cfgUrl: "testurl"
}}
};

this.fetchStub = this.sandbox.spy((doc as any), "fetch");
this.init = new ApplicationInsights({
config: noSetconfig,
});
this.init.loadAppInsights();
this._ai = this.init;
}].concat(PollingAssert.createPollingAssert(() => {
if (this.fetchStub.called){
let newCfg = this._ai.config;
Assert.equal(newCfg.featureOptIn["zipPayload"]["mode"], FeatureOptInMode.enable); // aisku default is none, overwrite to true by cdn config
return true;
}
return false;
}, "response received", 60, 1000) as any)
});

this.testCaseAsync({
name: "CfgSyncPlugin: customer set throttle config, new config fetch from config url could overwrite original one",
stepDelay: 10,
Expand Down
4 changes: 3 additions & 1 deletion AISKU/src/AISku.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const _ignoreUpdateSnippetProperties = [
const IKEY_USAGE = "iKeyUsage";
const CDN_USAGE = "CdnUsage";
const SDK_LOADER_VER = "SdkLoaderVer";
const ZIP_PAYLOAD = "zipPayload";

const UNDEFINED_VALUE: undefined = undefined;

Expand Down Expand Up @@ -80,7 +81,8 @@ const defaultConfigValues: IConfigDefaults<IConfiguration & IConfig> = {
featureOptIn:{
[IKEY_USAGE]: {mode: FeatureOptInMode.enable}, //for versions after 3.1.2 (>= 3.2.0)
[CDN_USAGE]: {mode: FeatureOptInMode.disable},
[SDK_LOADER_VER]: {mode: FeatureOptInMode.disable}
[SDK_LOADER_VER]: {mode: FeatureOptInMode.disable},
[ZIP_PAYLOAD]: {mode: FeatureOptInMode.none}
},
throttleMgrCfg: cfgDfMerge<{[key:number]: IThrottleMgrConfig}>(
{
Expand Down
4 changes: 2 additions & 2 deletions AISKULight/Tests/Unit/src/AISKULightSize.Tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ function _checkSize(checkType: string, maxSize: number, size: number, isNightly:
}

export class AISKULightSizeCheck extends AITestClass {
private readonly MAX_RAW_SIZE = 92;
private readonly MAX_BUNDLE_SIZE = 92;
private readonly MAX_RAW_SIZE = 93;
private readonly MAX_BUNDLE_SIZE = 93;
private readonly MAX_RAW_DEFLATE_SIZE = 38;
private readonly MAX_BUNDLE_DEFLATE_SIZE = 38;
private readonly rawFilePath = "../dist/es5/applicationinsights-web-basic.min.js";
Expand Down
90 changes: 87 additions & 3 deletions AISKULight/Tests/Unit/src/dynamicconfig.tests.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { AITestClass, Assert, PollingAssert } from "@microsoft/ai-test-framework";
import { IConfig } from "@microsoft/applicationinsights-common";
import { IConfiguration, isString, newId } from "@microsoft/applicationinsights-core-js";
import { IConfiguration, IPayloadData, isString, ITelemetryItem, IXHROverride, newId } from "@microsoft/applicationinsights-core-js";
import { ApplicationInsights, ISenderConfig } from "../../../src/index";
import { createAsyncResolvedPromise } from "@nevware21/ts-async";

import { SinonSpy } from 'sinon';
export class ApplicationInsightsDynamicConfigTests extends AITestClass {
private static readonly _instrumentationKey = "b7170927-2d1c-44f1-acec-59f4e1751c11";
private static readonly _connectionString = `InstrumentationKey=${ApplicationInsightsDynamicConfigTests._instrumentationKey}`;
private _ai: ApplicationInsights;
private _sessionPrefix: string = newId();
private _config: IConfiguration & IConfig;
static registerTests: any;
private genericSpy: SinonSpy;
private _ctx: any;

private xhrOverride: IXHROverride;
constructor(testName?: string) {
super(testName || "AISKU Dynamic Config");
}
Expand All @@ -30,6 +31,7 @@ export class ApplicationInsightsDynamicConfigTests extends AITestClass {

this._ai = new ApplicationInsights(this._config);
this._ctx = {};
this.xhrOverride = new AutoCompleteXhrOverride();
} catch (e) {
console.error("Failed to initialize", e);
}
Expand Down Expand Up @@ -137,6 +139,80 @@ export class ApplicationInsightsDynamicConfigTests extends AITestClass {
return false;
}, "Wait for promise response" + new Date().toISOString(), 60, 1000) as any)
});

this.testCaseAsync({
name: "zip test: gzip encode is working and content-encode header is set (feature opt-in)",
stepDelay: 10,
useFakeTimers: true,
useFakeServer: true,
steps: [
() => {
this.genericSpy = this.sandbox.spy(this.xhrOverride, 'sendPOST');
this._ai.config.featureOptIn["zipPayload"] = { mode: 3 };
this._ai.config.extensionConfig["AppInsightsChannelPlugin"] = {
httpXHROverride: this.xhrOverride,
alwaysUseXhrOverride: true
}
this.clock.tick(10);
const telemetryItem: ITelemetryItem = {
name: 'fake item with some really long name to take up space quickly',
iKey: 'iKey',
baseType: 'some type',
baseData: {}
};

this._ai.track(telemetryItem);
this._ai.flush();
this.clock.tick(10);
}].concat(PollingAssert.createPollingAssert(() => {
if (this.genericSpy.called){
let request = this.genericSpy.getCall(0).args[0];
let gzipData = request.data;
QUnit.assert.ok(gzipData, "data should be set");
QUnit.assert.equal(true, gzipData[0] === 0x1F && gzipData[1] === 0x8B, "telemetry should be gzip encoded");
QUnit.assert.equal(request.headers["Content-Encoding"], "gzip", "telemetry should be gzip encoded");
return true;
}
return false;
}, "Wait for promise response" + new Date().toISOString(), 60, 1000) as any)
});

this.testCaseAsync({
name: "zip test: gzip encode will not working (feature opt-in is not set)",
stepDelay: 10,
useFakeTimers: true,
useFakeServer: true,
steps: [
() => {
this.genericSpy = this.sandbox.spy(this.xhrOverride, 'sendPOST');
this._ai.config.extensionConfig["AppInsightsChannelPlugin"] = {
httpXHROverride: this.xhrOverride,
alwaysUseXhrOverride: true
}
this.clock.tick(10);
const telemetryItem: ITelemetryItem = {
name: 'fake item with some really long name to take up space quickly',
iKey: 'iKey',
baseType: 'some type',
baseData: {}
};

this._ai.track(telemetryItem);
this._ai.flush();
this.clock.tick(10);
}].concat(PollingAssert.createPollingAssert(() => {
if (this.genericSpy.called){
let request = this.genericSpy.getCall(0).args[0];
let gzipData = request.data;
QUnit.assert.ok(gzipData, "data should be set");
QUnit.assert.equal(false, gzipData[0] === 0x1F && gzipData[1] === 0x8B, "telemetry should not be gzip encoded");
QUnit.assert.equal(request.headers["Content-Encoding"], undefined, "telemetry should not be gzip encoded");
return true;
}
return false;
}, "Wait for promise response" + new Date().toISOString(), 60, 1000) as any)
});

}

public addApiTests(): void {
Expand All @@ -153,4 +229,12 @@ export class ApplicationInsightsDynamicConfigTests extends AITestClass {
});
}

}

class AutoCompleteXhrOverride {

public sendPOST(payload: IPayloadData, oncomplete: (status: number, headers: { [headerName: string]: string }) => void, sync?: boolean) {
console.log("AutoCompleteXhrOverride.sendPOST called with payload: ", payload);
oncomplete(200, null);
}
}
3 changes: 2 additions & 1 deletion AISKULight/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
"rollup-plugin-sourcemaps": "^0.6.3",
"typescript": "^4.9.3",
"typedoc": "^0.26.6",
"tslib": "^2.0.0"
"tslib": "^2.0.0",
"sinon": "^7.3.1"
},
"peerDependencies": {
"tslib": ">= 1.0.0"
Expand Down
9 changes: 6 additions & 3 deletions AISKULight/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import dynamicProto from "@microsoft/dynamicproto-js";
import { Sender } from "@microsoft/applicationinsights-channel-js";
import { DEFAULT_BREEZE_PATH, IConfig, parseConnectionString } from "@microsoft/applicationinsights-common";
import {
AppInsightsCore, IConfigDefaults, IConfiguration, IDistributedTraceContext, IDynamicConfigHandler, ILoadedPlugin, IPlugin,
ITelemetryInitializerHandler, ITelemetryItem, ITelemetryPlugin, ITelemetryUnloadState, IUnloadHook, UnloadHandler, WatcherFunction,
cfgDfValidate, createDynamicConfig, onConfigChange, proxyFunctions
AppInsightsCore, FeatureOptInMode, IConfigDefaults, IConfiguration, IDistributedTraceContext, IDynamicConfigHandler, ILoadedPlugin,
IPlugin, ITelemetryInitializerHandler, ITelemetryItem, ITelemetryPlugin, ITelemetryUnloadState, IUnloadHook, UnloadHandler,
WatcherFunction, cfgDfValidate, createDynamicConfig, onConfigChange, proxyFunctions
} from "@microsoft/applicationinsights-core-js";
import { IPromise, createSyncPromise, doAwaitResponse } from "@nevware21/ts-async";
import { isNullOrUndefined, isPromiseLike, isString, objDefine, throwError } from "@nevware21/ts-utils";
Expand All @@ -18,6 +18,9 @@ const defaultConfigValues: IConfigDefaults<IConfiguration> = {
connectionString: UNDEFINED_VALUE,
endpointUrl: UNDEFINED_VALUE,
instrumentationKey: UNDEFINED_VALUE,
featureOptIn:{
["zipPayload"]: {mode: FeatureOptInMode.none}
},
extensionConfig: {}
};

Expand Down
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,11 +447,43 @@ Most configuration fields are named such that they can be defaulted to falsey. A
| disableIkeyDeprecationMessage | boolean | true | [Optional] Disable instrumentation Key deprecation error message. If true, error message will NOT be sent. **Note: instrumentation key support will end soon**, see aka.ms/IkeyMigrate for more details.
| bufferOverride <br/><sub>since 2.8.12</sub> | IStorageBuffer | undefined | [Optional] Identifies a simple interface to allow you to override the storage mechanism used for tracking unsent and unacknowledged events, when not provided defaults to using SessionStorage interface. You MUST supply both the `getItem` and `setItem` functions when defined.
| storagePrefix | string[] | undefined | [Optional] An optional value that will be added as name prefix for storage name. |
| featureOptIn <br/><sub>since 3.0.3</sub> | IFeatureOptIn | undefined | [Optional] Set Feature opt in details. |
| featureOptIn (#feature)<br/><sub>since 3.0.3</sub> | IFeatureOptIn | undefined | [Optional] Set Feature opt in details. |
| throttleMgrCfg <br/><sub>since 3.0.3</sub> | `{[key: number]: IThrottleMgrConfig}` | undefined | [Optional] Set throttle mgr configuration by key. |
| retryCodes | number[] | undefined | Identifies the status codes that will cause event batches to be resent, when `null` or `undefined` the SDK will use it's defaults `[401, 408, 429, 500, 502, 503, 504]`. `403` was removed in version 3.1.1. |
| expCfg <br/><sub>since 3.3.1</sub>| [`IExceptionConfig`](https://github.com/microsoft/ApplicationInsights-JS/blob/main/shared/AppInsightsCommon/src/Interfaces/IExceptionTelemetry.ts) | undefined | Set additional configuration for exceptions, such as more scripts to include in the exception telemetry. |

### Feature

You can use the `featureOptIn` configuration to enable or customize specific SDK features.

#### Available Feature Flags

| Name | Default | Description | Note |
|-------------|---------|----------------------------------------------|------------|
| `zipPayload` | `none`*(version 3.3.7) | Enables compression using the Compression API to zip telemetry payloads. |If this feature is turned on and the CompressionStream API is available, the payload will be compressed using the CompressionStream API. Compression will only occur if the event is asynchronous. For events like unloads, compression will not be applied. Note: if user set payloadPreprocessor, this zip compression will not be applied.|

* A default value of none means the SDK may automatically enable this feature in the future. To explicitly prevent this, set the feature to disable using FeatureOptInMode.disable.

#### How to Enable a Feature

To enable a feature such as `zipPayload`, set the `featureOptIn` property in the SDK configuration as shown below:

```javascript
const appInsights = new ApplicationInsights({
config: {
connectionString: "YOUR_CONNECTION_STRING",
// Other configuration options...
featureOptIn: {
zipPayload: {
mode: FeatureOptInMode.enable, // Set the opt-in status for the feature
blockCdnCfg: false, // Define whether to block changes from CDN config
} as IFeatureOptInDetails
}
}
});
```
See [feature opt-in status](https://microsoft.github.io/ApplicationInsights-JS/WebConfig) for more details.


### ExtensionConfig

Expand Down
1 change: 1 addition & 0 deletions channels/1ds-post-js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ appInsightsCore.initialize(coreConfig, []);
| maxEventRetryAttempts<br /><sub><i>(Since 3.1.11+)</i></sub> | [Optional] Identifies the number of times any single event will be retried if it receives a failed (retirable) response, this causes the event to be internally "requeued" and resent in the next batch. As each normal batched send request is retried at least once before starting to increase the internal backoff send interval, normally batched events will generally be attempted the next nearest even number of times. This means that the total number of actual send attempts will almost always be even (setting to 5 will cause 6 requests), unless using manual synchronous flushing (calling flush(false)) which is not subject to request level retry attempts. | number<br/>Default: 6
| maxUnloadEventRetryAttempts<br /><sub><i>(Since 3.1.11+)</i></sub> | [Optional] Identifies the number of times any single event will be retried if it receives a failed (retriable) response as part of processing / flushing events once a page unload state has been detected, this causes the event to be internally "requeued" and resent in the next batch, which during page unload. Unlike the normal batching process, send requests are never retried, so the value listed here is always the maximum number of attempts for any single event.<br/>Notes: The SDK by default will use the sendBeacon() API if it exists which is treated as a fire and forget successful response, so for environments that support or supply this API the events won't be retried (because they will be deeded to be successfully sent). When an environment (IE) doesn't support sendBeacon(), this will cause multiple synchronous (by default) XMLHttpRequests to be sent, which will block the UI until a response is received. You can disable ALL synchronous XHR requests by setting the 'disableXhrSync' configuration setting and/or changing this value to 0 or 1. | number<br/>Default: 2
| addNoResponse <br /><sub><i>(Since 3.2.8+)</i></sub> | [Optional] flag to indicate whether the sendBeacon and fetch (with keep-alive flag) should add the "NoResponseBody" query string value to indicate that the server should return a 204 for successful requests. | boolean<br/>Default: true
| disableZip <br /><sub><i>(Since 4.3.7+)</i></sub> | [Optional] flag to use CompressionStream API to compress the payload. Compression will only occur if the event is asynchronous. For events like unloads, compression will not be applied. * Note: if user set payloadPreprocessor, this zip compression will not be applied. | boolean<br/>Default: true

### [IXHROverride](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IXHROverride.html)

Expand Down
Loading
Loading