Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[main][stats beat] implement stats beat in application insights #2489

Open
wants to merge 48 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
acc2e43
basic structure
siyuniu-ms Mar 5, 2025
65be711
Merge branch 'main' into siyu/statsbeats
siyuniu-ms Mar 5, 2025
bfe5965
imp[ort
siyuniu-ms Mar 5, 2025
5182765
test locally works good
siyuniu-ms Mar 6, 2025
3f5ae6c
Update StatsBeat.ts
siyuniu-ms Mar 6, 2025
0711bf7
only check statsbeat before send it
siyuniu-ms Mar 6, 2025
94a090e
refactor
siyuniu-ms Mar 11, 2025
5cbac35
remove statsbeatdata from function call
siyuniu-ms Mar 17, 2025
9913e66
remove
siyuniu-ms Mar 17, 2025
31811e7
refactor statsbeat
siyuniu-ms Mar 17, 2025
a6ba0fb
count in a different way
siyuniu-ms Mar 18, 2025
0006c9b
call oncomplete manually
siyuniu-ms Mar 18, 2025
11b7e26
Update Sender.ts
siyuniu-ms Mar 18, 2025
ff8e0b6
format change
siyuniu-ms Mar 18, 2025
2190c12
rename var and remove set initilize
siyuniu-ms Mar 19, 2025
28f2696
change class to interface
siyuniu-ms Mar 19, 2025
c81ea69
set up timer
siyuniu-ms Mar 20, 2025
eb2392b
avoid duplicate init
siyuniu-ms Mar 20, 2025
6dd7528
rename exception
siyuniu-ms Mar 20, 2025
96d5089
Update testVersionConflict.html
siyuniu-ms Mar 20, 2025
6131e9f
add some comment
siyuniu-ms Mar 20, 2025
b24c9fd
add count check
siyuniu-ms Mar 24, 2025
ea2b96a
throttle count
siyuniu-ms Mar 24, 2025
41cb9d7
fix the ugilify not compile problem
siyuniu-ms Mar 25, 2025
d475568
status code change
siyuniu-ms Mar 25, 2025
fae3295
add basic test
siyuniu-ms Mar 25, 2025
c94a752
add counter test
siyuniu-ms Mar 25, 2025
ee5faa9
Update Sender.ts
siyuniu-ms Mar 27, 2025
13ec43c
Merge branch 'main' into siyu/statsbeats
siyuniu-ms Mar 27, 2025
4b5ea40
signature changes
siyuniu-ms Apr 1, 2025
8f0cb34
remove duplicate
siyuniu-ms Apr 1, 2025
4bf7c05
refactor config
siyuniu-ms Apr 2, 2025
bfd5178
Update Sender.ts
siyuniu-ms Apr 2, 2025
1d7fe05
Update Sender.ts
siyuniu-ms Apr 2, 2025
19e3fc7
Merge branch 'siyu/statsbeats' of https://github.com/microsoft/Applic…
siyuniu-ms Apr 2, 2025
9fd36fd
Merge branch 'main' into siyu/statsbeats
siyuniu-ms Apr 2, 2025
e79f02c
size change and a trick
siyuniu-ms Apr 2, 2025
bc0ff2c
Update AISKUSize.Tests.ts
siyuniu-ms Apr 2, 2025
7fa1123
size change
siyuniu-ms Apr 3, 2025
2dd95a5
Update AISKULightSize.Tests.ts
siyuniu-ms Apr 3, 2025
50939a7
Update Sender.ts
siyuniu-ms Apr 7, 2025
162a5d3
rename and change the way to call statsbeat
siyuniu-ms Apr 7, 2025
4edd527
Merge branch 'main' into siyu/statsbeats
siyuniu-ms Apr 7, 2025
6a65e00
Update cfgsynchelper.tests.ts
siyuniu-ms Apr 7, 2025
3a6eea0
Update AppInsightsCore.ts
siyuniu-ms Apr 8, 2025
a60cfdb
Update StatsBeat.tests.ts
siyuniu-ms Apr 8, 2025
23d4771
comment out statsbeat test, set statsbeat to null by default
siyuniu-ms Apr 8, 2025
3598def
Update AppInsightsCore.ts
siyuniu-ms Apr 8, 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
10 changes: 6 additions & 4 deletions AISKU/Tests/Manual/testVersionConflict.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<!-- <script src="https://requirejs.org/docs/release/2.3.6/minified/require.js" type="text/javascript"></script> -->
<script type="text/javascript">
!(function (cfg){function e(){cfg.onInit&&cfg.onInit(n)}var x,w,D,t,E,n,C=window,O=document,b=C.location,q="script",I="ingestionendpoint",L="disableExceptionTracking",j="ai.device.";"instrumentationKey"[x="toLowerCase"](),w="crossOrigin",D="POST",t="appInsightsSDK",E=cfg.name||"appInsights",(cfg.name||C[t])&&(C[t]=E),n=C[E]||function(g){var f=!1,m=!1,h={initialize:!0,queue:[],sv:"8",version:2,config:g};function v(e,t){var n={},i="Browser";function a(e){e=""+e;return 1===e.length?"0"+e:e}return n[j+"id"]=i[x](),n[j+"type"]=i,n["ai.operation.name"]=b&&b.pathname||"_unknown_",n["ai.internal.sdkVersion"]="javascript:snippet_"+(h.sv||h.version),{time:(i=new Date).getUTCFullYear()+"-"+a(1+i.getUTCMonth())+"-"+a(i.getUTCDate())+"T"+a(i.getUTCHours())+":"+a(i.getUTCMinutes())+":"+a(i.getUTCSeconds())+"."+(i.getUTCMilliseconds()/1e3).toFixed(3).slice(2,5)+"Z",iKey:e,name:"Microsoft.ApplicationInsights."+e.replace(/-/g,"")+"."+t,sampleRate:100,tags:n,data:{baseData:{ver:2}},ver:undefined,seq:"1",aiDataContract:undefined}}var n,i,t,a,y=-1,T=0,S=["js.monitor.azure.com","js.cdn.applicationinsights.io","js.cdn.monitor.azure.com","js0.cdn.applicationinsights.io","js0.cdn.monitor.azure.com","js2.cdn.applicationinsights.io","js2.cdn.monitor.azure.com","az416426.vo.msecnd.net"],o=g.url||cfg.src,r=function(){return s(o,null)};function s(d,t){if((n=navigator)&&(~(n=(n.userAgent||"").toLowerCase()).indexOf("msie")||~n.indexOf("trident/"))&&~d.indexOf("ai.3")&&(d=d.replace(/(\/)(ai\.3\.)([^\d]*)$/,function(e,t,n){return t+"ai.2"+n})),!1!==cfg.cr)for(var e=0;e<S.length;e++)if(0<d.indexOf(S[e])){y=e;break}var n,i=function(e){var a,t,n,i,o,r,s,c,u,l;h.queue=[],m||(0<=y&&T+1<S.length?(a=(y+T+1)%S.length,p(d.replace(/^(.*\/\/)([\w\.]*)(\/.*)$/,function(e,t,n,i){return t+S[a]+i})),T+=1):(f=m=!0,s=d,!0!==cfg.dle&&(c=(t=function(){var e,t={},n=g.connectionString;if(n)for(var i=n.split(";"),a=0;a<i.length;a++){var o=i[a].split("=");2===o.length&&(t[o[0][x]()]=o[1])}return t[I]||(e=(n=t.endpointsuffix)?t.location:null,t[I]="https://"+(e?e+".":"")+"dc."+(n||"services.visualstudio.com")),t}()).instrumentationkey||g.instrumentationKey||"",t=(t=(t=t[I])&&"/"===t.slice(-1)?t.slice(0,-1):t)?t+"/v2/track":g.endpointUrl,t=g.userOverrideEndpointUrl||t,(n=[]).push((i="SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details)",o=s,u=t,(l=(r=v(c,"Exception")).data).baseType="ExceptionData",l.baseData.exceptions=[{typeName:"SDKLoadFailed",message:i.replace(/\./g,"-"),hasFullStack:!1,stack:i+"\nSnippet failed to load ["+o+"] -- Telemetry is disabled\nHelp Link: https://go.microsoft.com/fwlink/?linkid=2128109\nHost: "+(b&&b.pathname||"_unknown_")+"\nEndpoint: "+u,parsedStack:[]}],r)),n.push((l=s,i=t,(u=(o=v(c,"Message")).data).baseType="MessageData",(r=u.baseData).message='AI (Internal): 99 message:"'+("SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details) ("+l+")").replace(/\"/g,"")+'"',r.properties={endpoint:i},o)),s=n,c=t,JSON&&((u=C.fetch)&&!cfg.useXhr?u(c,{method:D,body:JSON.stringify(s),mode:"cors"}):XMLHttpRequest&&((l=new XMLHttpRequest).open(D,c),l.setRequestHeader("Content-type","application/json"),l.send(JSON.stringify(s)))))))},a=function(e,t){m||setTimeout(function(){!t&&h.core||i()},500),f=!1},p=function(e){var n=O.createElement(q),e=(n.src=e,t&&(n.integrity=t),n.setAttribute("data-ai-name",E),cfg[w]);return!e&&""!==e||"undefined"==n[w]||(n[w]=e),n.onload=a,n.onerror=i,n.onreadystatechange=function(e,t){"loaded"!==n.readyState&&"complete"!==n.readyState||a(0,t)},cfg.ld&&cfg.ld<0?O.getElementsByTagName("head")[0].appendChild(n):setTimeout(function(){O.getElementsByTagName(q)[0].parentNode.appendChild(n)},cfg.ld||0),n};p(d)}cfg.sri&&(n=o.match(/^((http[s]?:\/\/.*\/)\w+(\.\d+){1,5})\.(([\w]+\.){0,2}js)$/))&&6===n.length?(d="".concat(n[1],".integrity.json"),i="@".concat(n[4]),l=window.fetch,t=function(e){if(!e.ext||!e.ext[i]||!e.ext[i].file)throw Error("Error Loading JSON response");var t=e.ext[i].integrity||null;s(o=n[2]+e.ext[i].file,t)},l&&!cfg.useXhr?l(d,{method:"GET",mode:"cors"}).then(function(e){return e.json()["catch"](function(){return{}})}).then(t)["catch"](r):XMLHttpRequest&&((a=new XMLHttpRequest).open("GET",d),a.onreadystatechange=function(){if(a.readyState===XMLHttpRequest.DONE)if(200===a.status)try{t(JSON.parse(a.responseText))}catch(e){r()}else r()},a.send())):o&&r();try{h.cookie=O.cookie}catch(k){}function e(e){for(;e.length;)!function(t){h[t]=function(){var e=arguments;f||h.queue.push(function(){h[t].apply(h,e)})}}(e.pop())}var c,u,l="track",d="TrackPage",p="TrackEvent",l=(e([l+"Event",l+"PageView",l+"Exception",l+"Trace",l+"DependencyData",l+"Metric",l+"PageViewPerformance","start"+d,"stop"+d,"start"+p,"stop"+p,"addTelemetryInitializer","setAuthenticatedUserContext","clearAuthenticatedUserContext","flush"]),h.SeverityLevel={Verbose:0,Information:1,Warning:2,Error:3,Critical:4},(g.extensionConfig||{}).ApplicationInsightsAnalytics||{});return!0!==g[L]&&!0!==l[L]&&(e(["_"+(c="onerror")]),u=C[c],C[c]=function(e,t,n,i,a){var o=u&&u(e,t,n,i,a);return!0!==o&&h["_"+c]({message:e,url:t,lineNumber:n,columnNumber:i,error:a,evt:C.event}),o},g.autoExceptionInstrumented=!0),h}(cfg.cfg),(C[E]=n).queue&&0===n.queue.length?(n.queue.push(e),n.trackPageView({})):e();})({
src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
// src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
src: "../../browser/es5/ai.3.3.6.js",
// name: "appInsights", // Global SDK Instance name defaults to "appInsights" when not supplied
// 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),
Expand All @@ -19,18 +20,19 @@
// 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)
sri: true, // Custom optional value to specify whether fetching the snippet from integrity file and do integrity check
cfg: { // Application Insights Configuration
connectionString: "Your-connection-string-here"
disableStatsBeat: false,
connectionString: "YOUR_INSTRUMENTATION_KEY",
}
});
</script>
</head>
<body>
<h1>Microsoft Application Insights JavaScript SDK - AISKU</h1>
<script>
<!-- <script>
let appInsights = new ApplicationInsights.ApplicationInsights({ config: {connectionString: "InstrumentationKey=88888888", disableInstrumentationKeyValidation: true}});
appInsights.loadAppInsights();
window.appInsights = appInsights;
</script>
</script> -->
<!-- <script src="aisku-example-index.gbl.js"></script> -->
</body>
</html>
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 = 145;
private readonly MAX_BUNDLE_SIZE = 145;
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
2 changes: 1 addition & 1 deletion AISKU/Tests/Unit/src/applicationinsights.e2e.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export class ApplicationInsightsTests extends AITestClass {
}

public registerTests() {
this.addDynamicConfigTests()
this.addDynamicConfigTests();
this.addGenericE2ETests();
this.addAnalyticsApiTests();
this.addAsyncTests();
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 = 91;
private readonly MAX_BUNDLE_SIZE = 91;
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
import { AITestClass, Assert, PollingAssert } from "@microsoft/ai-test-framework";
import { AppInsightsCore, IPayloadData, ITelemetryItem, TransportType } from "@microsoft/applicationinsights-core-js";
import { Sender } from "../../../src/Sender";
import { SinonSpy, SinonStub } from "sinon";
import { ISenderConfig } from "../../../types/applicationinsights-channel-js";
import { isBeaconApiSupported } from "@microsoft/applicationinsights-common";

export class StatsbeatTests extends AITestClass {
private _core: AppInsightsCore;
private _sender: Sender;
private statsbeatCountSpy: SinonSpy;
private fetchStub: sinon.SinonStub;
private beaconStub: sinon.SinonStub;
private trackSpy: SinonSpy;

public testInitialize() {
this._core = new AppInsightsCore();
this._sender = new Sender();
}

public testFinishedCleanup() {
if (this._sender && this._sender.isInitialized()) {
this._sender.pause();
this._sender._buffer.clear();
this._sender.teardown();
}
this._sender = null;
this._core = null;
if (this.statsbeatCountSpy) {
this.statsbeatCountSpy.restore();
}
if (this.fetchStub) {
this.fetchStub.restore();
}
if (this.beaconStub) {
this.beaconStub.restore();
}
if (this.trackSpy) {
this.trackSpy.restore();
}
}

private initializeCoreAndSender(config: any, instrumentationKey: string) {
const sender = new Sender();
const core = new AppInsightsCore();
const coreConfig = {
instrumentationKey,
_sdk: { stats: true },
extensionConfig: { [sender.identifier]: config }
};

core.initialize(coreConfig, [sender]);
this.statsbeatCountSpy = this.sandbox.spy(core.getStatsBeat(), "count");
this.trackSpy = this.sandbox.spy(core, "track");

this.onDone(() => {
sender.teardown();
});

return { core, sender };
}

private createSenderConfig(transportType: TransportType) {
return {
endpointUrl: "https://test",
emitLineDelimitedJson: false,
maxBatchInterval: 15000,
maxBatchSizeInBytes: 102400,
disableTelemetry: false,
enableSessionStorageBuffer: true,
isRetryDisabled: false,
isBeaconApiDisabled: false,
disableXhr: false,
onunloadDisableFetch: false,
onunloadDisableBeacon: false,
namePrefix: "",
samplingPercentage: 100,
customHeaders: [{ header: "header", value: "val" }],
convertUndefined: "",
eventsLimitInMem: 10000,
transports: [transportType]
};
}

private processTelemetryAndFlush(sender: Sender, telemetryItem: ITelemetryItem) {
try {
sender.processTelemetry(telemetryItem, null);
sender.flush();
} catch (e) {
QUnit.assert.ok(false, "Unexpected error during telemetry processing");
}
this.clock.tick(900000); // Simulate time passing for statsbeat to be sent
}

private assertStatsbeatCall(statusCode: number, eventName: string) {
Assert.equal(this.statsbeatCountSpy.callCount, 1, "Statsbeat count should be called once");
Assert.equal(this.statsbeatCountSpy.firstCall.args[0], statusCode, `Statsbeat count should be called with status ${statusCode}`);
const data = JSON.stringify(this.statsbeatCountSpy.firstCall.args[1]);
Assert.ok(data.includes("startTime"), "Statsbeat count should be called with startTime set");
const statsbeatEvent = this.trackSpy.firstCall.args[0];
Assert.equal(statsbeatEvent.baseType, "MetricData", "Statsbeat event should be of type MetricData");
Assert.equal(statsbeatEvent.baseData.name, eventName, `Statsbeat event should be of type ${eventName}`);
}

public registerTests() {
this.testCase({
name: "Statsbeat initializes when stats is true",
test: () => {
const config = {
_sdk: { stats: true },
instrumentationKey: "Test-iKey"
};

this._core.initialize(config, [this._sender]);
const statsbeat = this._core.getStatsBeat();

QUnit.assert.ok(statsbeat, "Statsbeat is initialized");
QUnit.assert.ok(statsbeat.isInitialized(), "Statsbeat is marked as initialized");
}
});

this.testCaseAsync({
name: "Statsbeat increments success count when fetch sender is called once",
useFakeTimers: true,
stepDelay: 100,
steps: [
() => {
this.fetchStub = this.sandbox.stub(window, "fetch").callsFake(() => {
return Promise.resolve(new Response("{}", { status: 200, statusText: "OK" }));
});

const config = this.createSenderConfig(TransportType.Fetch);
const { sender } = this.initializeCoreAndSender(config, "000e0000-e000-0000-a000-000000000000");

const telemetryItem: ITelemetryItem = {
name: "fake item",
iKey: "testIkey2;ingestionendpoint=testUrl1",
baseType: "some type",
baseData: {}
};

this.processTelemetryAndFlush(sender, telemetryItem);
}
].concat(PollingAssert.createPollingAssert(() => {
if (this.statsbeatCountSpy.called && this.fetchStub.called) {
this.assertStatsbeatCall(200, "Request_Success_Count");
return true;
}
return false;
}, "Waiting for fetch sender and Statsbeat count to be called") as any)
});

this.testCaseAsync({
name: "Statsbeat increments retry count when fetch sender is called once",
useFakeTimers: true,
stepDelay: 100,
steps: [
() => {
this.fetchStub = this.sandbox.stub(window, "fetch").callsFake(() => {
return Promise.resolve(new Response("{}", { status: 439, statusText: "Too Many Requests" }));
});

const config = this.createSenderConfig(TransportType.Fetch);
const { sender } = this.initializeCoreAndSender(config, "000e0000-e000-0000-a000-000000000000");

const telemetryItem: ITelemetryItem = {
name: "fake item",
iKey: "testIkey2;ingestionendpoint=testUrl1",
baseType: "some type",
baseData: {}
};

this.processTelemetryAndFlush(sender, telemetryItem);
}
].concat(PollingAssert.createPollingAssert(() => {
if (this.statsbeatCountSpy.called && this.fetchStub.called) {
this.assertStatsbeatCall(400, "failure");
return true;
}
return false;
}, "Waiting for fetch sender and Statsbeat count to be called") as any)
});



// this.testCaseAsync({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is actually the "default" sender mechanism we really need to test this.

You will most likely need to use the fakeServer and the helper this.sendJsonResponse(request, {}, 200) to simulate the responses examples are in several tests.

// name: "Statsbeat increments success count for xhr sender",useFakeTimers: true,
// stepDelay: 100,
// steps: [
// () => {
// let config = this.createSenderConfig(TransportType.Xhr) && {disableSendBeaconSplit: true};
// const { sender } = this.initializeCoreAndSender(config, "000e0000-e000-0000-a000-000000000000");

// const telemetryItem: ITelemetryItem = {
// name: "fake item",
// iKey: "testIkey2;ingestionendpoint=testUrl1",
// baseType: "some type",
// baseData: {}
// };
// this.processTelemetryAndFlush(sender, telemetryItem);
// QUnit.assert.equal(1, this._getXhrRequests().length, "xhr sender is called");

// }
// ].concat(PollingAssert.createPollingAssert(() => {
// if (this.statsbeatCountSpy.called) {
// // this.assertStatsbeatCall(200, "Request_Success_Count");
// console.log("Statsbeat count called with success count for xhr sender");
// return true;
// }
// return false;
// }, "Waiting for xhr sender and Statsbeat count to be called", 60, 1000) as any)
// });

this.testCaseAsync({
name: "Statsbeat increments success count for beacon sender",
useFakeTimers: true,
stepDelay: 100,
steps: [
() => {
const config = this.createSenderConfig(TransportType.Beacon);
const { sender } = this.initializeCoreAndSender(config, "000e0000-e000-0000-a000-000000000000");

const telemetryItem: ITelemetryItem = {
name: "fake item",
iKey: "testIkey2;ingestionendpoint=testUrl1",
baseType: "some type",
baseData: {}
};
let sendBeaconCalled = false;
this.hookSendBeacon((url: string) => {
sendBeaconCalled = true;
return true;
});
QUnit.assert.ok(isBeaconApiSupported(), "Beacon API is supported");
this.processTelemetryAndFlush(sender, telemetryItem);
}
].concat(PollingAssert.createPollingAssert(() => {
if (this.statsbeatCountSpy.called) {
this.assertStatsbeatCall(200, "Request_Success_Count");
return true;
}
return false;
}, "Waiting for beacon sender and Statsbeat count to be called") as any)
});
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { SenderTests } from "./Sender.tests";
import { SampleTests } from "./Sample.tests";
import { GlobalTestHooks } from "./GlobalTestHooks.Test";
import { StatsbeatTests } from "./StatsBeat.tests";

export function runTests() {
new GlobalTestHooks().registerTests();
new SenderTests().registerTests();
new SampleTests().registerTests();
// new StatsbeatTests().registerTests();
}
2 changes: 2 additions & 0 deletions channels/applicationinsights-channel-js/src/SendBuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ abstract class BaseSendBuffer {
if (!isNullOrUndefined(_maxRetryCnt)) {
if (payload.cnt > _maxRetryCnt) {
// TODO: add log here on dropping payloads
// will log statsbeat exception later here

return;
}
}
Expand Down
Loading
Loading