Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion AISKU/Tests/Unit/src/SdkStatsFeature.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ export class SdkStatsFeatureTests extends AITestClass {
Assert.equal("https://" + statsHost + "/v2/track", requests[0].url, "SDK Stats should use the remote-configured endpoint");
let payload = JSON.parse(xhrSendSpy.firstCall.args[0]);
Assert.equal(statsIKey, payload[0].iKey, "SDK Stats should use the dynamically supplied instrumentation key");
Assert.equal("exception", payload[0].data.baseData.metrics[0].name, "The buffered exception should be reported");
Assert.equal("Exception_Count", payload[0].data.baseData.metrics[0].name, "The buffered exception should be reported");
Assert.equal(1, payload[0].data.baseData.metrics[0].value, "The buffered exception count should be preserved");
requests[0].respond(200, {}, "");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export class InternalSdkStatsTests extends AITestClass {
timeout: 0,
disableXhrSync: false,
statsData: {
startTime: Date.now() // Simulated start time (numeric, used in duration arithmetic)
startTime: Date.now() - 20 // Simulated request duration in milliseconds
}
} as IPayloadData;

Expand All @@ -168,19 +168,38 @@ export class InternalSdkStatsTests extends AITestClass {
internalSdkStats.count(200, payloadData, "https://example.endpoint.com");

// Test failed request
internalSdkStats.count(400, payloadData, "https://example.endpoint.com");
internalSdkStats.count(400, payloadData, "https://example.endpoint.com");

// Test retried requests
internalSdkStats.count(500, payloadData, "https://example.endpoint.com");
internalSdkStats.count(500, payloadData, "https://example.endpoint.com");

// Test throttled request
internalSdkStats.count(429, payloadData, "https://example.endpoint.com");

// Test throttled request
internalSdkStats.count(402, payloadData, "https://example.endpoint.com");

// Verify that track is called when the collection timer fires
this.clock.tick(STATS_COLLECTION_SHORT_INTERVAL * 1000 + 1);

// Verify that track was called
Assert.ok(this._trackSpy.called, "track should be called when SDK Stats timer fires");

// When the timer fires, multiple metrics should be sent
Assert.ok(this._trackSpy.callCount >= 3, "Multiple metrics should be tracked");
const expectedMetrics = [
{ name: "Request_Duration", average: 20, statusCode: undefined },
{ name: "Request_Success_Count", average: 1, statusCode: undefined },
{ name: "Request_Failure_Count", average: 2, statusCode: "400" },
{ name: "Retry_Count", average: 1, statusCode: "429" },
{ name: "Retry_Count", average: 2, statusCode: "500" },
{ name: "Throttle_Count", average: 1, statusCode: "402" }
];
Assert.equal(expectedMetrics.length, this._trackSpy.callCount, "Only the expected network metrics should be tracked");
for (let i = 0; i < expectedMetrics.length; i++) {
const expected = expectedMetrics[i];
const item: ITelemetryItem = this._trackSpy.getCall(i).args[0];
Assert.equal(expected.name, item.name, "The telemetry name should match the network metric name");
Assert.equal(expected.name, item.baseData.name, "The metric name should match the Statsbeat specification");
Assert.equal(expected.average, item.baseData.average, "The metric value should preserve aggregation");
Assert.equal(expected.statusCode, item.baseData.properties.statusCode, "The statusCode dimension should be preserved");
Assert.equal(undefined, item.baseData.properties.exceptionType, "Request metrics should not have an exceptionType");
}
}
});

Expand All @@ -204,23 +223,13 @@ export class InternalSdkStatsTests extends AITestClass {
// Verify that track is called when the collection timer fires
this.clock.tick(STATS_COLLECTION_SHORT_INTERVAL * 1000 + 1);

// Verify that track was called
Assert.ok(this._trackSpy.called, "track should be called when SDK Stats timer fires");

// Check that exception metrics are tracked
let foundExceptionMetric = false;
for (let i = 0; i < this._trackSpy.callCount; i++) {
const call = this._trackSpy.getCall(i);
const item: ITelemetryItem = call.args[0];
if (item.baseData &&
item.baseData.properties &&
item.baseData.properties.exceptionType === "NetworkError") {
foundExceptionMetric = true;
break;
}
}

Assert.ok(foundExceptionMetric, "Exception metrics should be tracked");
Assert.equal(1, this._trackSpy.callCount, "Only the exception metric should be tracked");
const item: ITelemetryItem = this._trackSpy.firstCall.args[0];
Assert.equal("Exception_Count", item.name, "The telemetry name should match the network metric name");
Assert.equal("Exception_Count", item.baseData.name, "The metric name should match the Statsbeat specification");
Assert.equal(1, item.baseData.average, "The exception count should be preserved");
Assert.equal("NetworkError", item.baseData.properties.exceptionType, "The exceptionType dimension should be preserved");
Assert.equal(undefined, item.baseData.properties.statusCode, "Exception metrics should not have a statusCode");
}
});

Expand Down Expand Up @@ -940,7 +949,7 @@ export class InternalSdkStatsTests extends AITestClass {
let exceptionCount = 0;
for (let i = 0; i < this._trackSpy.callCount; i++) {
const item: ITelemetryItem = this._trackSpy.getCall(i).args[0];
if (item.name === "exception") {
if (item.name === "Exception_Count") {
exceptionCount = item.baseData.average;
}
}
Expand Down
6 changes: 3 additions & 3 deletions shared/AppInsightsCore/src/core/InternalSdkStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,9 @@ function _createInternalSdkStats(
function _trackSendRequestsCount() {
var currentCounter = _networkCounter;
_sendInternalSdkStatss("Request_Success_Count", currentCounter.success);
_sendCounts(currentCounter.failure, "failure", "statusCode");
_sendCounts(currentCounter.retry, "retry", "statusCode");
_sendCounts(currentCounter.exception, "exception", "exceptionType");
_sendCounts(currentCounter.failure, "Request_Failure_Count", "statusCode");
_sendCounts(currentCounter.retry, "Retry_Count", "statusCode");
_sendCounts(currentCounter.exception, "Exception_Count", "exceptionType");
_sendCounts(currentCounter.throttle, "Throttle_Count", "statusCode");
}

Expand Down
Loading