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

Control Document Quotas for QuickPulse #2425

Merged
merged 37 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
dd4d02b
save initial work
rambhatt-msft Aug 27, 2021
afc3c60
add tests
rambhatt-msft Aug 27, 2021
4e3cfde
save work
rambhatt-msft Sep 16, 2021
9e7e3db
save ongoing work
rambhatt-msft Sep 24, 2021
611a71e
end fix
rambhatt-msft Sep 25, 2021
9670e8e
fix tests
rambhatt-msft Sep 25, 2021
bb0adf8
Merge branch 'develop' into rambhatt/adjustable-document-quotas
rambhatt-msft Sep 25, 2021
63d1e93
fix test errors
rambhatt-msft Sep 25, 2021
e84bdc8
fix tests
rambhatt-msft Sep 27, 2021
ab499a2
remove debug comments
rambhatt-msft Sep 27, 2021
4ab126e
save PR comment fixes
rambhatt-msft Sep 29, 2021
2c98885
add PR comment fix
rambhatt-msft Sep 29, 2021
f0e4495
tiny fix
rambhatt-msft Sep 29, 2021
6ccf417
add testcase
rambhatt-msft Sep 29, 2021
486ff56
fix PR comments
rambhatt-msft Sep 29, 2021
74e5015
Merge branch 'develop' into rambhatt/adjustable-document-quotas
rambhatt-msft Sep 29, 2021
de7c4c8
fix PR commit
rambhatt-msft Sep 29, 2021
0332166
Merge branch 'rambhatt/adjustable-document-quotas' of https://github.…
rambhatt-msft Sep 29, 2021
95af13a
add PR fix
rambhatt-msft Sep 29, 2021
967ae19
fix compile
rambhatt-msft Sep 29, 2021
736a360
add PR comment fix
rambhatt-msft Sep 29, 2021
f285561
Pr comment fix
rambhatt-msft Sep 29, 2021
a6da204
save Pr comment fix
rambhatt-msft Sep 29, 2021
28e5734
save Pr comment
rambhatt-msft Sep 29, 2021
71873bc
fix PR
rambhatt-msft Sep 30, 2021
308b9a4
Merge branch 'develop' into rambhatt/adjustable-document-quotas
TimothyMothra Oct 20, 2021
cc8be6b
tentative changes for tests
rambhatt-msft Oct 22, 2021
48659d9
Merge branch 'rambhatt/adjustable-document-quotas' of https://github.…
rambhatt-msft Oct 22, 2021
1c19688
fix tests
rambhatt-msft Oct 25, 2021
11fe028
fix tests
rambhatt-msft Oct 25, 2021
3880582
save tests targeting
rambhatt-msft Oct 25, 2021
4e7d2ca
fix Pr comments
rambhatt-msft Oct 26, 2021
f4b8c22
PR comments fixed
rambhatt-msft Oct 26, 2021
99644c2
Merge branch 'develop' into rambhatt/adjustable-document-quotas
TimothyMothra Oct 27, 2021
c4182bf
save PR fix
rambhatt-msft Oct 27, 2021
2a3fd08
Merge branch 'rambhatt/adjustable-document-quotas' of https://github.…
rambhatt-msft Oct 27, 2021
ed0da2c
add changelog edit
rambhatt-msft Oct 27, 2021
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Microsoft.ApplicationInsights.Tests
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Extensibility.Filtering;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.Implementation.QuickPulse;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.Implementation.Service_contract;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse;
using Microsoft.ApplicationInsights.Web.Helpers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down Expand Up @@ -653,6 +654,223 @@ public void CollectionConfigurationCarriesOverQuotaWhenCreatingDocumentStreams()
Assert.AreEqual(3, documentStreams[3].EventQuotaTracker.CurrentQuota);
}

[TestMethod]
public void CollectionConfigurationWithMaxAndInitialQuotas()
{
// ARRANGE
var timeProvider = new ClockMock();

CollectionConfigurationError[] errors;
var oldDocumentStreamInfos = new[]
{
new DocumentStreamInfo()
{
Id = "Stream1",
DocumentFilterGroups =
new[]
{
new DocumentFilterConjunctionGroupInfo()
{
TelemetryType = TelemetryType.Request,
Filters = new FilterConjunctionGroupInfo() { Filters = new FilterInfo[0] }
}
}
},
new DocumentStreamInfo()
{
Id = "Stream2",
DocumentFilterGroups =
new[]
{
new DocumentFilterConjunctionGroupInfo()
{
TelemetryType = TelemetryType.Dependency,
Filters = new FilterConjunctionGroupInfo() { Filters = new FilterInfo[0] }
}
}
},
new DocumentStreamInfo()
{
Id = "Stream3",
DocumentFilterGroups =
new[]
{
new DocumentFilterConjunctionGroupInfo()
{
TelemetryType = TelemetryType.Exception,
Filters = new FilterConjunctionGroupInfo() { Filters = new FilterInfo[0] }
}
}
}
};

var newDocumentStreamInfos = new[]
{
new DocumentStreamInfo()
{
Id = "Stream1",
DocumentFilterGroups =
new[]
{
new DocumentFilterConjunctionGroupInfo()
{
TelemetryType = TelemetryType.Request,
Filters = new FilterConjunctionGroupInfo() { Filters = new FilterInfo[0] }
}
}
},
new DocumentStreamInfo()
{
Id = "Stream2",
DocumentFilterGroups =
new[]
{
new DocumentFilterConjunctionGroupInfo()
{
TelemetryType = TelemetryType.Dependency,
Filters = new FilterConjunctionGroupInfo() { Filters = new FilterInfo[0] }
}
}
},
new DocumentStreamInfo()
{
Id = "Stream3",
DocumentFilterGroups =
new[]
{
new DocumentFilterConjunctionGroupInfo()
{
TelemetryType = TelemetryType.Exception,
Filters = new FilterConjunctionGroupInfo() { Filters = new FilterInfo[0] }
}
}
},
new DocumentStreamInfo()
{
Id = "Stream4",
DocumentFilterGroups =
new[]
{
new DocumentFilterConjunctionGroupInfo()
{
TelemetryType = TelemetryType.Event,
Filters = new FilterConjunctionGroupInfo() { Filters = new FilterInfo[0] }
}
}
},
new DocumentStreamInfo()
{
Id = "Stream5",
DocumentFilterGroups =
new[]
{
new DocumentFilterConjunctionGroupInfo()
{
TelemetryType = TelemetryType.Trace,
Filters = new FilterConjunctionGroupInfo() { Filters = new FilterInfo[0] }
}
}
}
};

var oldCollectionConfigurationInfo = new CollectionConfigurationInfo()
{
DocumentStreams = oldDocumentStreamInfos,
ETag = "ETag1",
QuotaInfo = new QuotaConfigurationInfo()
{
InitialQuota = 10,
MaxQuota = 30,
QuotaAccrualRatePerSec = null
}
};
var oldCollectionConfiguration = new CollectionConfiguration(oldCollectionConfigurationInfo, out errors, timeProvider);

// spend some quota on the old configuration
var accumulatorManager = new QuickPulseDataAccumulatorManager(oldCollectionConfiguration);
var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy());
((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection(
accumulatorManager,
new Uri("http://microsoft.com"),
new TelemetryConfiguration() { InstrumentationKey = "some ikey" });

// ACT
// the initial quota is 3
telemetryProcessor.Process(new RequestTelemetry() { Context = { InstrumentationKey = "some ikey" } });

telemetryProcessor.Process(new DependencyTelemetry() { Context = { InstrumentationKey = "some ikey" } });
telemetryProcessor.Process(new DependencyTelemetry() { Context = { InstrumentationKey = "some ikey" } });

telemetryProcessor.Process(new ExceptionTelemetry() { Context = { InstrumentationKey = "some ikey" } });
telemetryProcessor.Process(new ExceptionTelemetry() { Context = { InstrumentationKey = "some ikey" } });
telemetryProcessor.Process(new ExceptionTelemetry() { Context = { InstrumentationKey = "some ikey" } });

// ACT
// the new configuration must carry the quotas over from the old one (only for those document streams that already existed)
var newCollectionConfigurationInfo = new CollectionConfigurationInfo() { DocumentStreams = newDocumentStreamInfos, ETag = "ETag1" };
var newCollectionConfiguration = new CollectionConfiguration(
newCollectionConfigurationInfo,
out errors,
timeProvider,
oldCollectionConfiguration.DocumentStreams);

// ASSERT
DocumentStream[] oldDocumentStreams = oldCollectionConfiguration.DocumentStreams.ToArray();
Assert.AreEqual(3, oldDocumentStreams.Length);

Assert.AreEqual("Stream1", oldDocumentStreams[0].Id);
Assert.AreEqual(9, oldDocumentStreams[0].RequestQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[0].DependencyQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[0].ExceptionQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[0].EventQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[0].EventQuotaTracker.CurrentQuota);

Assert.AreEqual("Stream2", oldDocumentStreams[1].Id);
Assert.AreEqual(10, oldDocumentStreams[1].RequestQuotaTracker.CurrentQuota);
Assert.AreEqual(8, oldDocumentStreams[1].DependencyQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[1].ExceptionQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[1].EventQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[1].EventQuotaTracker.CurrentQuota);

Assert.AreEqual("Stream3", oldDocumentStreams[2].Id);
Assert.AreEqual(10, oldDocumentStreams[2].RequestQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[2].DependencyQuotaTracker.CurrentQuota);
Assert.AreEqual(7, oldDocumentStreams[2].ExceptionQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[2].EventQuotaTracker.CurrentQuota);
Assert.AreEqual(10, oldDocumentStreams[2].EventQuotaTracker.CurrentQuota);

DocumentStream[] newDocumentStreams = newCollectionConfiguration.DocumentStreams.ToArray();
Assert.AreEqual(5, newDocumentStreams.Length);

Assert.AreEqual("Stream1", newDocumentStreams[0].Id);
Assert.AreEqual(9, newDocumentStreams[0].RequestQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[0].DependencyQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[0].ExceptionQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[0].EventQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[0].EventQuotaTracker.CurrentQuota);

Assert.AreEqual("Stream2", newDocumentStreams[1].Id);
Assert.AreEqual(10, newDocumentStreams[1].RequestQuotaTracker.CurrentQuota);
Assert.AreEqual(8, newDocumentStreams[1].DependencyQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[1].ExceptionQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[1].EventQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[1].EventQuotaTracker.CurrentQuota);

Assert.AreEqual("Stream3", newDocumentStreams[2].Id);
Assert.AreEqual(10, newDocumentStreams[2].RequestQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[2].DependencyQuotaTracker.CurrentQuota);
Assert.AreEqual(7, newDocumentStreams[2].ExceptionQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[2].EventQuotaTracker.CurrentQuota);
Assert.AreEqual(10, newDocumentStreams[2].EventQuotaTracker.CurrentQuota);

Assert.AreEqual("Stream4", newDocumentStreams[3].Id);
Assert.AreEqual(3, newDocumentStreams[3].RequestQuotaTracker.CurrentQuota);
Assert.AreEqual(3, newDocumentStreams[3].DependencyQuotaTracker.CurrentQuota);
Assert.AreEqual(3, newDocumentStreams[3].ExceptionQuotaTracker.CurrentQuota);
Assert.AreEqual(3, newDocumentStreams[3].EventQuotaTracker.CurrentQuota);
Assert.AreEqual(3, newDocumentStreams[3].EventQuotaTracker.CurrentQuota);
}

[TestMethod]
public void CollectionConfigurationReportsDocumentStreamsWithDuplicateIds()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,5 +163,28 @@ public void QuickPulseQuotaTrackerIsThreadSafe()
Assert.AreEqual(correctResult, passedQuotaCount);
Assert.IsFalse(quotaTracker.ApplyQuota());
}

[TestMethod]
public void QuickPulseQuotaTrackerParameters()
{
// ARRANGE
int maxQuota = 500;
int experimentLengthInSeconds = 499;
var mockTimeProvider = new ClockMock();
var quotaTracker = new QuickPulseQuotaTracker(mockTimeProvider, maxQuota, 900, 1);

// ACT
for (int i = 0; i < experimentLengthInSeconds; i++)
{
mockTimeProvider.FastForward(TimeSpan.FromSeconds(1));

quotaTracker.ApplyQuota();
}

// ASSERT
Assert.AreEqual(499, quotaTracker.CurrentQuota);
Assert.AreEqual(500, quotaTracker.MaxQuota);
Assert.AreEqual(false, quotaTracker.QuotaExhausted);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Microsoft.ApplicationInsights.Extensibility.Implementation;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.Implementation.QuickPulse;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.Implementation.QuickPulse.Helpers;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.Implementation.Service_contract;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse;
using Microsoft.ApplicationInsights.TestFramework;
using Microsoft.ApplicationInsights.Web.Helpers;
Expand Down Expand Up @@ -802,6 +803,69 @@ public void QuickPulseTelemetryModuleUpdatesCollectionConfiguration()
Assert.AreEqual("ETag2", serviceClient.SnappedSamples.Last().CollectionConfigurationAccumulator.CollectionConfiguration.ETag);
}

[TestMethod]
public void QuickPulseTelemetryModuleUpdatesCollectionConfigurationWithCutomQuotas()
rambhatt-msft marked this conversation as resolved.
Show resolved Hide resolved
{
if (QuickPulseTelemetryModuleTests.Ignored)
{
return;
}

// ARRANGE
var pollingInterval = TimeSpan.FromSeconds(1);
var collectionInterval = TimeSpan.FromMilliseconds(400);
var timings = new QuickPulseTimings(pollingInterval, collectionInterval);
var collectionTimeSlotManager = new QuickPulseCollectionTimeSlotManagerMock(timings);
var serviceClient = new QuickPulseServiceClientMock { ReturnValueFromPing = true, ReturnValueFromSubmitSample = true };
var performanceCollector = new PerformanceCollectorMock();
var topCpuCollector = new QuickPulseTopCpuCollectorMock();
var module = new QuickPulseTelemetryModule(collectionTimeSlotManager, null, serviceClient, performanceCollector, topCpuCollector, timings);

// ACT & ASSERT
CollectionConfigurationInfo collectionConfigurationInfo = new CollectionConfigurationInfo()
{
ETag = "ETag1",
DocumentStreams = new[] { new DocumentStreamInfo() { Id = "wx3", DocumentFilterGroups = new[] { new DocumentFilterConjunctionGroupInfo() { TelemetryType = TelemetryType.Request, Filters = new FilterConjunctionGroupInfo() { Filters = new FilterInfo[0] } } } } },
QuotaInfo = new QuotaConfigurationInfo()
{
InitialQuota = 50,
QuotaAccrualRatePerSec = 10,
MaxQuota = 500
}
};
serviceClient.CollectionConfigurationInfo = collectionConfigurationInfo;
QuickPulseTelemetryProcessor telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy());
module.RegisterTelemetryProcessor(telemetryProcessor);
module.Initialize(new TelemetryConfiguration() { InstrumentationKey = "some ikey" });
var collectionConfiguration = new CollectionConfiguration(collectionConfigurationInfo, out _, new Clock());
var accumulatorManager = new QuickPulseDataAccumulatorManager(collectionConfiguration);
((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection(
accumulatorManager,
new Uri("http://microsoft.com"),
new TelemetryConfiguration() { InstrumentationKey = "some ikey" });

for (int i=0;i<100;i++)
rambhatt-msft marked this conversation as resolved.
Show resolved Hide resolved
{
telemetryProcessor.Process(new RequestTelemetry() { Id = "1", Name = "Request1", Context = { InstrumentationKey = "some ikey" } });
}


Thread.Sleep(pollingInterval);
Assert.AreEqual(accumulatorManager.CurrentDataAccumulator.AIRequestCount, 50);
for (int i = 0; i < 100; i++)
{
telemetryProcessor.Process(new RequestTelemetry() { Id = "1", Name = "Request1", Context = { InstrumentationKey = "some ikey" } });
}

Thread.Sleep((int)(10 * collectionInterval.TotalMilliseconds));
Assert.AreEqual("ETag1", serviceClient.SnappedSamples.Last().CollectionConfigurationAccumulator.CollectionConfiguration.ETag);

Assert.AreEqual(accumulatorManager.CurrentDataAccumulator.AIRequestCount, 60);
serviceClient.CollectionConfigurationInfo = new CollectionConfigurationInfo() { ETag = "ETag2" };
Thread.Sleep((int)(10 * collectionInterval.TotalMilliseconds));
Assert.AreEqual("ETag2", serviceClient.SnappedSamples.Last().CollectionConfigurationAccumulator.CollectionConfiguration.ETag);
}

[TestMethod]
public void QuickPulseTelemetryModuleUpdatesPerformanceCollectorWhenUpdatingCollectionConfiguration()
{
Expand Down
Loading