public void QuickPulseDataAccumulatorManagerLocksInSampleCorrectlyMultithreaded() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); int taskCount = 100; var writeTasks = new List<Task>(taskCount); var pause = TimeSpan.FromMilliseconds(10); for (int i = 0; i < taskCount; i++) { var task = new Task(() => { Interlocked.Increment(ref accumulatorManager.CurrentDataAccumulator.AIRequestSuccessCount); // sleep to increase the probability of sample completion happening right now Thread.Sleep(pause); Interlocked.Increment(ref accumulatorManager.CurrentDataAccumulator.AIDependencyCallSuccessCount); }); writeTasks.Add(task); } var completionTask = new Task(() => { // sleep to increase the probability of more write tasks being between the two writes Thread.Sleep(TimeSpan.FromTicks(pause.Ticks / 2)); accumulatorManager.CompleteCurrentDataAccumulator(); }); // shuffle the completion task into the middle of the pile to have it fire roughly halfway through writeTasks.Insert(writeTasks.Count / 2, completionTask); // ACT var sample1 = accumulatorManager.CurrentDataAccumulator; var result = Parallel.For(0, writeTasks.Count, new ParallelOptions() { MaxDegreeOfParallelism = taskCount }, i => writeTasks[i].RunSynchronously()); while (!result.IsCompleted) { } var sample2 = accumulatorManager.CurrentDataAccumulator; // ASSERT // we expect some "telemetry items" to get "sprayed" over the two neighboring samples Assert.IsTrue(sample1.AIRequestSuccessCount > sample1.AIDependencyCallSuccessCount); Assert.IsTrue(sample2.AIRequestSuccessCount < sample2.AIDependencyCallSuccessCount); // overall numbers should match exactly Assert.AreEqual(taskCount, sample1.AIRequestSuccessCount + sample2.AIRequestSuccessCount); Assert.AreEqual(taskCount, sample1.AIDependencyCallSuccessCount + sample2.AIDependencyCallSuccessCount); }
public void QuickPulseDataAccumulatorManagerLocksInSampleCorrectly() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); accumulatorManager.CurrentDataAccumulator.AIRequestSuccessCount = 5; // ACT var completedSample = accumulatorManager.CompleteCurrentDataAccumulator(); // ASSERT Assert.AreEqual(5, completedSample.AIRequestSuccessCount); Assert.AreEqual(0, accumulatorManager.CurrentDataAccumulator.AIRequestSuccessCount); Assert.AreNotSame(completedSample, accumulatorManager.CurrentDataAccumulator); }
/// <summary> /// Initializes a new instance of the <see cref="QuickPulseTelemetryModule"/> class. Internal constructor for unit tests only. /// </summary> /// <param name="collectionTimeSlotManager">Collection time slot manager.</param> /// <param name="dataAccumulatorManager">Data hub to sink QuickPulse data to.</param> /// <param name="serviceClient">QPS service client.</param> /// <param name="performanceCollector">Performance counter collector.</param> /// <param name="timings">Timings for the module.</param> internal QuickPulseTelemetryModule( QuickPulseCollectionTimeSlotManager collectionTimeSlotManager, QuickPulseDataAccumulatorManager dataAccumulatorManager, IQuickPulseServiceClient serviceClient, IPerformanceCollector performanceCollector, QuickPulseTimings timings) : this() { this.collectionTimeSlotManager = collectionTimeSlotManager; this.dataAccumulatorManager = dataAccumulatorManager; this.serviceClient = serviceClient; this.performanceCollector = performanceCollector; this.timings = timings; }
public void QuickPulseTelemetryProcessorKeepsAccurateCountOfRequests() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = "some ikey" }); // ACT telemetryProcessor.Process( new RequestTelemetry() { Success = false, ResponseCode = "200", Duration = TimeSpan.FromSeconds(1), Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process( new RequestTelemetry() { Success = true, ResponseCode = "200", Duration = TimeSpan.FromSeconds(2), Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process( new RequestTelemetry() { Success = false, ResponseCode = string.Empty, Duration = TimeSpan.FromSeconds(3), Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process( new RequestTelemetry() { Success = null, ResponseCode = string.Empty, Duration = TimeSpan.FromSeconds(4), Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process( new RequestTelemetry() { Success = true, ResponseCode = string.Empty, Duration = TimeSpan.FromSeconds(5), Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process( new RequestTelemetry() { Success = null, ResponseCode = "404", Duration = TimeSpan.FromSeconds(6), Context = { InstrumentationKey = "some ikey" } }); // ASSERT Assert.AreEqual(6, accumulatorManager.CurrentDataAccumulator.AIRequestCount); Assert.AreEqual( 1 + 2 + 3 + 4 + 5 + 6, TimeSpan.FromTicks(accumulatorManager.CurrentDataAccumulator.AIRequestDurationInTicks).TotalSeconds); Assert.AreEqual(4, accumulatorManager.CurrentDataAccumulator.AIRequestSuccessCount); Assert.AreEqual(2, accumulatorManager.CurrentDataAccumulator.AIRequestFailureCount); }
public void QuickPulseTelemetryProcessorKeepsAccurateCountOfExceptions() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = "some ikey" }); // ACT telemetryProcessor.Process(new ExceptionTelemetry() { Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process(new ExceptionTelemetry() { Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process(new ExceptionTelemetry() { Context = { InstrumentationKey = "some ikey" } }); // ASSERT Assert.AreEqual(3, accumulatorManager.CurrentDataAccumulator.AIExceptionCount); }
public void QuickPulseTelemetryProcessorKeepsAccurateCountOfDependencies() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = "some ikey" }); // ACT telemetryProcessor.Process( new DependencyTelemetry() { Success = true, Duration = TimeSpan.FromSeconds(1), Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process( new DependencyTelemetry() { Success = true, Duration = TimeSpan.FromSeconds(1), Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process( new DependencyTelemetry() { Success = false, Duration = TimeSpan.FromSeconds(2), Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process( new DependencyTelemetry() { Success = null, Duration = TimeSpan.FromSeconds(3), Context = { InstrumentationKey = "some ikey" } }); // ASSERT Assert.AreEqual(4, accumulatorManager.CurrentDataAccumulator.AIDependencyCallCount); Assert.AreEqual(1 + 1 + 2 + 3, TimeSpan.FromTicks(accumulatorManager.CurrentDataAccumulator.AIDependencyCallDurationInTicks).TotalSeconds); Assert.AreEqual(2, accumulatorManager.CurrentDataAccumulator.AIDependencyCallSuccessCount); Assert.AreEqual(1, accumulatorManager.CurrentDataAccumulator.AIDependencyCallFailureCount); }
public void QuickPulseTelemetryProcessorTruncatesLongFullExceptionTelemetryItemProperties() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); // ACT var exceptionShort = new ExceptionTelemetry(new ArgumentException()) { Properties = { { new string('p', MaxFieldLength), new string('v', MaxFieldLength) } }, Message = new string('m', MaxFieldLength), Context = { InstrumentationKey = instrumentationKey } }; var exceptionLong = new ExceptionTelemetry(new ArgumentException()) { Properties = { { new string('p', MaxFieldLength + 1), new string('v', MaxFieldLength + 1) } }, Message = new string('m', MaxFieldLength), Context = { InstrumentationKey = instrumentationKey } }; // process in the opposite order to allow for an easier validation order telemetryProcessor.Process(exceptionLong); telemetryProcessor.Process(exceptionShort); // ASSERT var telemetryDocuments = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Cast<ExceptionTelemetryDocument>().ToList(); var expected = exceptionShort.Properties.First(); var actual = telemetryDocuments[0].Properties.First(); Assert.AreEqual(expected.Key, actual.Key); Assert.AreEqual(expected.Value, actual.Value); actual = telemetryDocuments[1].Properties.First(); Assert.AreEqual(expected.Key, actual.Key); Assert.AreEqual(expected.Value, actual.Value); }
public void QuickPulseTelemetryProcessorTruncatesLongFullDependencyTelemetryItemName() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); // ACT var dependencyShort = new DependencyTelemetry( new string('c', MaxFieldLength), new string('c', MaxFieldLength), new string('c', MaxFieldLength), new string('c', MaxFieldLength), DateTimeOffset.Now, TimeSpan.FromSeconds(1), new string('c', MaxFieldLength), false) { Context = { InstrumentationKey = instrumentationKey } }; var dependencyLong = new DependencyTelemetry( new string('c', MaxFieldLength + 1), new string('c', MaxFieldLength + 1), new string('c', MaxFieldLength + 1), new string('c', MaxFieldLength + 1), DateTimeOffset.Now, TimeSpan.FromSeconds(1), new string('c', MaxFieldLength + 1), false) { Context = { InstrumentationKey = instrumentationKey } }; // process in the opposite order to allow for an easier validation order telemetryProcessor.Process(dependencyLong); telemetryProcessor.Process(dependencyShort); // ASSERT var telemetryDocuments = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Cast<DependencyTelemetryDocument>().ToList(); Assert.AreEqual(telemetryDocuments[0].Name, dependencyShort.Name); Assert.AreEqual(telemetryDocuments[1].Name, dependencyLong.Name.Substring(0, MaxFieldLength)); }
public void QuickPulseTelemetryProcessorFiltersOutDependencyCallsToQuickPulseServiceDuringCollection() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var simpleTelemetryProcessorSpy = new SimpleTelemetryProcessorSpy(); var telemetryProcessor = new QuickPulseTelemetryProcessor(simpleTelemetryProcessorSpy); var config = new TelemetryConfiguration() { InstrumentationKey = "some ikey" }; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("https://qps.cloudapp.net/endpoint.svc"), config); // ACT telemetryProcessor.Process( new DependencyTelemetry() { Name = "http://microsoft.ru", Context = { InstrumentationKey = config.InstrumentationKey } }); telemetryProcessor.Process( new DependencyTelemetry() { Name = "http://qps.cloudapp.net/blabla", Context = { InstrumentationKey = config.InstrumentationKey } }); telemetryProcessor.Process( new DependencyTelemetry() { Name = "https://bing.com", Context = { InstrumentationKey = config.InstrumentationKey } }); // ASSERT Assert.AreEqual(2, simpleTelemetryProcessorSpy.ReceivedCalls); Assert.AreEqual("http://microsoft.ru", (simpleTelemetryProcessorSpy.ReceivedItems[0] as DependencyTelemetry).Name); Assert.AreEqual("https://bing.com", (simpleTelemetryProcessorSpy.ReceivedItems[1] as DependencyTelemetry).Name); Assert.AreEqual(2, accumulatorManager.CurrentDataAccumulator.AIDependencyCallCount); }
public void QuickPulseTelemetryProcessorExpandsExceptionMessageWhenSingleInnerException() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); var exception = new Exception("Exception 1", new Exception("Exception 2")); // ACT var exceptionTelemetry = new ExceptionTelemetry(exception) { Context = { InstrumentationKey = instrumentationKey } }; telemetryProcessor.Process(exceptionTelemetry); // ASSERT var telemetryDocuments = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Cast<ExceptionTelemetryDocument>().ToList(); Assert.AreEqual("Exception 1 <--- Exception 2", telemetryDocuments[0].ExceptionMessage); }
public void QuickPulseTelemetryProcessorCollectsFullTelemetryItems() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); // ACT var request = new RequestTelemetry() { Name = Guid.NewGuid().ToString(), Success = false, ResponseCode = "500", Duration = TimeSpan.FromSeconds(1), Properties = { { "Prop1", "Val1" }, { "Prop2", "Val2" }, { "Prop3", "Val3" }, { "Prop4", "Val4" } }, Context = { InstrumentationKey = instrumentationKey } }; var dependency = new DependencyTelemetry() { Name = Guid.NewGuid().ToString(), Success = false, Duration = TimeSpan.FromSeconds(1), Properties = { { "Prop1", "Val1" }, { "Prop2", "Val2" }, { "Prop3", "Val3" }, { "Prop4", "Val4" }, { "ErrorMessage", "EMValue" } }, Context = { InstrumentationKey = instrumentationKey } }; var exception = new ExceptionTelemetry(new ArgumentNullException()) { Properties = { { "Prop1", "Val1" }, { "Prop2", "Val2" }, { "Prop3", "Val3" }, { "Prop4", "Val4" } }, Context = { InstrumentationKey = instrumentationKey } }; telemetryProcessor.Process(request); telemetryProcessor.Process(dependency); telemetryProcessor.Process(exception); // ASSERT var collectedTelemetry = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.ToArray().Reverse().ToArray(); Assert.AreEqual(3, accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Count); Assert.AreEqual(TelemetryDocumentType.Request, Enum.Parse(typeof(TelemetryDocumentType), collectedTelemetry[0].DocumentType)); Assert.AreEqual(request.Name, ((RequestTelemetryDocument)collectedTelemetry[0]).Name); Assert.AreEqual(3, collectedTelemetry[0].Properties.Length); Assert.IsTrue(collectedTelemetry[0].Properties.ToList().TrueForAll(pair => pair.Key.Contains("Prop") && pair.Value.Contains("Val"))); Assert.AreEqual(TelemetryDocumentType.RemoteDependency, Enum.Parse(typeof(TelemetryDocumentType), collectedTelemetry[1].DocumentType)); Assert.AreEqual(dependency.Name, ((DependencyTelemetryDocument)collectedTelemetry[1]).Name); Assert.AreEqual(3 + 1, collectedTelemetry[1].Properties.Length); Assert.IsTrue(collectedTelemetry[1].Properties.ToList().TrueForAll(pair => (pair.Key.Contains("Prop") && pair.Value.Contains("Val")) || (pair.Key == "ErrorMessage" && pair.Value == "EMValue"))); Assert.AreEqual(TelemetryDocumentType.Exception, Enum.Parse(typeof(TelemetryDocumentType), collectedTelemetry[2].DocumentType)); Assert.AreEqual(exception.Exception.ToString(), ((ExceptionTelemetryDocument)collectedTelemetry[2]).Exception); Assert.AreEqual(3, collectedTelemetry[2].Properties.Length); Assert.IsTrue(collectedTelemetry[2].Properties.ToList().TrueForAll(pair => (pair.Key.Contains("Prop") && pair.Value.Contains("Val")))); }
public void QuickPulseTelemetryProcessorDoesNotCollectSucceededFullTelemetryItems() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); // ACT var request = new RequestTelemetry() { Success = true, ResponseCode = "200", Duration = TimeSpan.FromSeconds(1), Context = { InstrumentationKey = instrumentationKey } }; var dependency = new DependencyTelemetry() { Success = true, Duration = TimeSpan.FromSeconds(1), Context = { InstrumentationKey = instrumentationKey } }; var exception = new ExceptionTelemetry(new ArgumentException("bla")) { Context = { InstrumentationKey = instrumentationKey } }; telemetryProcessor.Process(request); telemetryProcessor.Process(dependency); telemetryProcessor.Process(exception); // ASSERT var collectedTelemetry = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.ToArray().Reverse().ToArray(); Assert.AreEqual(1, accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Count); Assert.AreEqual(exception.Exception.ToString(), ((ExceptionTelemetryDocument)collectedTelemetry[0]).Exception); }
public void QuickPulseTelemetryProcessorDoesNotCollectFullTelemetryItemsWhenSwitchIsOff() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }, disableFullTelemetryItems: true); // ACT var request = new RequestTelemetry() { Success = false, ResponseCode = "500", Duration = TimeSpan.FromSeconds(1), Context = { InstrumentationKey = instrumentationKey } }; var dependency = new DependencyTelemetry() { Success = false, Duration = TimeSpan.FromSeconds(1), Context = { InstrumentationKey = instrumentationKey } }; var exception = new ExceptionTelemetry(new ArgumentException("bla")) { Context = { InstrumentationKey = instrumentationKey } }; telemetryProcessor.Process(request); telemetryProcessor.Process(dependency); telemetryProcessor.Process(exception); // ASSERT Assert.AreEqual(0, accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Count); }
public void QuickPulseTelemetryProcessorDoesNotCollectFullRequestTelemetryItemsOnceQuotaIsExhausted() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var timeProvider = new ClockMock(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy(), timeProvider, 60, 5); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); // ACT int counter = 0; for (int i = 0; i < 100; i++) { var request = new RequestTelemetry() { Success = false, ResponseCode = "400", Duration = TimeSpan.FromSeconds(counter++), Context = { InstrumentationKey = instrumentationKey } }; telemetryProcessor.Process(request); } timeProvider.FastForward(TimeSpan.FromSeconds(30)); for (int i = 0; i < 100; i++) { var request = new RequestTelemetry() { Success = false, ResponseCode = "400", Duration = TimeSpan.FromSeconds(counter++), Context = { InstrumentationKey = instrumentationKey } }; telemetryProcessor.Process(request); } // ASSERT var collectedTelemetry = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.ToArray().Reverse().Cast<RequestTelemetryDocument>().ToArray(); Assert.AreEqual(5 + 30, accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Count); // out of the first 100 items we expect to see items 0 through 4 (the initial quota) for (int i = 0; i < 5; i++) { Assert.AreEqual(i, collectedTelemetry[i].Duration.TotalSeconds); } // out of the second 100 items we expect to see items 100 through 129 (the new quota for 30 seconds) for (int i = 5; i < 35; i++) { Assert.AreEqual(95 + i, collectedTelemetry[i].Duration.TotalSeconds); } }
public void QuickPulseTelemetryProcessorDoesNotCollectFullExceptionTelemetryItemsOnceQuotaIsExhausted() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var timeProvider = new ClockMock(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy(), timeProvider, 60, 5); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); // ACT int counter = 0; for (int i = 0; i < 100; i++) { var exception = new ExceptionTelemetry(new Exception((counter++).ToString(CultureInfo.InvariantCulture))) { Context = { InstrumentationKey = instrumentationKey } }; telemetryProcessor.Process(exception); } timeProvider.FastForward(TimeSpan.FromSeconds(30)); for (int i = 0; i < 100; i++) { var exception = new ExceptionTelemetry(new Exception((counter++).ToString(CultureInfo.InvariantCulture))) { Context = { InstrumentationKey = instrumentationKey } }; telemetryProcessor.Process(exception); } // ASSERT var collectedTelemetry = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.ToArray().Reverse().Cast<ExceptionTelemetryDocument>().ToArray(); Assert.AreEqual(5 + 30, accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Count); // out of the first 100 items we expect to see items 0 through 4 (the initial quota) for (int i = 0; i < 5; i++) { Assert.AreEqual(i, int.Parse(collectedTelemetry[i].ExceptionMessage, CultureInfo.InvariantCulture)); } // out of the second 100 items we expect to see items 100 through 129 (the new quota for 30 seconds) for (int i = 5; i < 35; i++) { Assert.AreEqual(95 + i, int.Parse(collectedTelemetry[i].ExceptionMessage, CultureInfo.InvariantCulture)); } }
public void QuickPulseTelemetryProcessorMustBeStoppedBeforeReceivingStartCommand() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://test.com"), new TelemetryConfiguration()); // ACT ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://test.com"), new TelemetryConfiguration()); // ASSERT // must throw }
public void QuickPulseTelemetryProcessorSwitchesBetweenMultipleAccumulatorManagers() { // ARRANGE var accumulatorManager1 = new QuickPulseDataAccumulatorManager(); var accumulatorManager2 = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); // ACT var serviceEndpoint = new Uri("http://microsoft.com"); var config = new TelemetryConfiguration() { InstrumentationKey = "some ikey" }; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager1, serviceEndpoint, config); telemetryProcessor.Process(new RequestTelemetry() { Context = { InstrumentationKey = "some ikey" } }); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StopCollection(); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager2, serviceEndpoint, config); telemetryProcessor.Process(new DependencyTelemetry() { Context = { InstrumentationKey = "some ikey" } }); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StopCollection(); // ASSERT Assert.AreEqual(1, accumulatorManager1.CurrentDataAccumulator.AIRequestCount); Assert.AreEqual(0, accumulatorManager1.CurrentDataAccumulator.AIDependencyCallCount); Assert.AreEqual(0, accumulatorManager2.CurrentDataAccumulator.AIRequestCount); Assert.AreEqual(1, accumulatorManager2.CurrentDataAccumulator.AIDependencyCallCount); }
public void QuickPulseTelemetryProcessorHandlesDuplicatePropertyNamesDueToTruncation() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); // ACT var exception = new ExceptionTelemetry(new ArgumentException()) { Properties = { { new string('p', MaxFieldLength + 1), "Val1" }, { new string('p', MaxFieldLength + 2), "Val2" } }, Message = "Message", Context = { InstrumentationKey = instrumentationKey } }; telemetryProcessor.Process(exception); // ASSERT var telemetryDocuments = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Cast<ExceptionTelemetryDocument>().ToList(); Assert.AreEqual(1, telemetryDocuments[0].Properties.Length); Assert.AreEqual(new string('p', MaxFieldLength), telemetryDocuments[0].Properties.First().Key); }
public void QuickPulseTelemetryProcessorTruncatesLongFullDependencyTelemetryItemProperties() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); // ACT var dependencyShort = new DependencyTelemetry( "dependencyShort", "dependencyShort", "dependencyShort", "dependencyShort", DateTimeOffset.Now, TimeSpan.FromSeconds(1), "dependencyShort", false) { Properties = { { new string('p', MaxFieldLength), new string('v', MaxFieldLength) } }, Context = { InstrumentationKey = instrumentationKey } }; var dependencyLong = new DependencyTelemetry( "dependencyLong", "dependencyLong", "dependencyLong", "dependencyLong", DateTimeOffset.Now, TimeSpan.FromSeconds(1), "dependencyLong", false) { Properties = { { new string('p', MaxFieldLength + 1), new string('v', MaxFieldLength + 1) } }, Context = { InstrumentationKey = instrumentationKey } }; // process in the opposite order to allow for an easier validation order telemetryProcessor.Process(dependencyLong); telemetryProcessor.Process(dependencyShort); // ASSERT var telemetryDocuments = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Cast<DependencyTelemetryDocument>().ToList(); var expected = dependencyShort.Properties.First(); var actual = telemetryDocuments[0].Properties.First(); Assert.AreEqual(expected.Key, actual.Key); Assert.AreEqual(expected.Value, actual.Value); actual = telemetryDocuments[1].Properties.First(); Assert.AreEqual(expected.Key, actual.Key); Assert.AreEqual(expected.Value, actual.Value); }
public void QuickPulseTelemetryProcessorHandlesMultipleThreadsCorrectly() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = "some ikey" }); // expected data loss if threading is misimplemented is around 10% (established through experiment) int taskCount = 10000; var tasks = new List<Task>(taskCount); for (int i = 0; i < taskCount; i++) { var requestTelemetry = new RequestTelemetry() { ResponseCode = (i % 2 == 0) ? "200" : "500", Duration = TimeSpan.FromMilliseconds(i), Context = { InstrumentationKey = "some ikey" } }; var task = new Task(() => telemetryProcessor.Process(requestTelemetry)); tasks.Add(task); } // ACT tasks.ForEach(task => task.Start()); Task.WaitAll(tasks.ToArray()); // ASSERT Assert.AreEqual(taskCount, accumulatorManager.CurrentDataAccumulator.AIRequestCount); Assert.AreEqual(taskCount / 2, accumulatorManager.CurrentDataAccumulator.AIRequestSuccessCount); }
public void QuickPulseTelemetryModuleSupportsMultipleTelemetryProcessorsForMultipleConfigurations() { // ARRANGE var pollingInterval = TimeSpan.FromMilliseconds(1); var collectionInterval = TimeSpan.FromMilliseconds(1); var timings = new QuickPulseTimings(pollingInterval, collectionInterval); var collectionTimeSlotManager = new QuickPulseCollectionTimeSlotManagerMock(timings); var accumulatorManager = new QuickPulseDataAccumulatorManager(); var serviceClient = new QuickPulseServiceClientMock { ReturnValueFromPing = true, ReturnValueFromSubmitSample = true }; var performanceCollector = new PerformanceCollectorMock(); var module = new QuickPulseTelemetryModule(collectionTimeSlotManager, accumulatorManager, serviceClient, performanceCollector, timings); const int TelemetryProcessorCount = 4; var ikey = "some ikey"; var config = new TelemetryConfiguration { InstrumentationKey = ikey }; // spawn a bunch of configurations, each one having an individual instance of QuickPulseTelemetryProcessor var telemetryProcessors = new List<QuickPulseTelemetryProcessor>(); for (int i = 0; i < TelemetryProcessorCount; i++) { var configuration = new TelemetryConfiguration(); var builder = configuration.TelemetryProcessorChainBuilder; builder = builder.Use(current => new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy())); builder.Build(); telemetryProcessors.Add(configuration.TelemetryProcessors.OfType<QuickPulseTelemetryProcessor>().Single()); } // ACT foreach (var telemetryProcessor in telemetryProcessors) { module.RegisterTelemetryProcessor(telemetryProcessor); } module.Initialize(config); Thread.Sleep(TimeSpan.FromMilliseconds(100)); // send data to each instance of QuickPulseTelemetryProcessor var request = new RequestTelemetry() { ResponseCode = "200", Success = true, Context = { InstrumentationKey = ikey } }; telemetryProcessors[0].Process(request); request = new RequestTelemetry() { ResponseCode = "500", Success = false, Context = { InstrumentationKey = ikey } }; telemetryProcessors[1].Process(request); var dependency = new DependencyTelemetry() { Success = true, Context = { InstrumentationKey = ikey } }; telemetryProcessors[2].Process(dependency); dependency = new DependencyTelemetry() { Success = false, Context = { InstrumentationKey = ikey } }; telemetryProcessors[3].Process(dependency); Thread.Sleep(TimeSpan.FromMilliseconds(100)); // ASSERT // verify that every telemetry processor has contributed to the accumulator Assert.AreEqual(TelemetryProcessorCount, QuickPulseTestHelper.GetTelemetryProcessors(module).Count); Assert.AreEqual(1, serviceClient.SnappedSamples.Count(s => s.AIRequestsPerSecond > 0)); Assert.AreEqual(1, serviceClient.SnappedSamples.Count(s => s.AIRequestsFailedPerSecond > 0)); Assert.AreEqual(1, serviceClient.SnappedSamples.Count(s => s.AIDependencyCallsPerSecond > 0)); Assert.AreEqual(1, serviceClient.SnappedSamples.Count(s => s.AIDependencyCallsFailedPerSecond > 0)); }
public void QuickPulseTelemetryProcessorIgnoresTelemetryItemsToDifferentInstrumentationKeys() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = "some ikey" }); // ACT telemetryProcessor.Process(new RequestTelemetry() { Context = { InstrumentationKey = "some other ikey" } }); telemetryProcessor.Process(new RequestTelemetry() { Context = { InstrumentationKey = "some ikey" } }); // ASSERT Assert.AreEqual(1, accumulatorManager.CurrentDataAccumulator.AIRequestCount); }
public void QuickPulseTelemetryProcessorIgnoresUnrelatedTelemetryItems() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = "some ikey" }); // ACT telemetryProcessor.Process(new EventTelemetry() { Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process(new ExceptionTelemetry() { Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process(new MetricTelemetry() { Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process(new PageViewTelemetry() { Context = { InstrumentationKey = "some ikey" } }); telemetryProcessor.Process(new TraceTelemetry() { Context = { InstrumentationKey = "some ikey" } }); // ASSERT Assert.AreEqual(0, accumulatorManager.CurrentDataAccumulator.AIRequestCount); Assert.AreEqual(0, accumulatorManager.CurrentDataAccumulator.AIDependencyCallCount); }
public void QuickPulseTelemetryProcessorTruncatesLongFullExceptionTelemetryItemMessage() { // ARRANGE var accumulatorManager = new QuickPulseDataAccumulatorManager(); var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy()); var instrumentationKey = "some ikey"; ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection( accumulatorManager, new Uri("http://microsoft.com"), new TelemetryConfiguration() { InstrumentationKey = instrumentationKey }); // ACT var exceptionShort = new ExceptionTelemetry(new ArgumentException(new string('m', MaxFieldLength))) { Context = { InstrumentationKey = instrumentationKey } }; var exceptionLong = new ExceptionTelemetry(new ArgumentException(new string('m', MaxFieldLength + 1))) { Context = { InstrumentationKey = instrumentationKey } }; // process in the opposite order to allow for an easier validation order telemetryProcessor.Process(exceptionLong); telemetryProcessor.Process(exceptionShort); // ASSERT var telemetryDocuments = accumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Cast<ExceptionTelemetryDocument>().ToList(); Assert.AreEqual(telemetryDocuments[0].ExceptionMessage, exceptionShort.Exception.Message); Assert.AreEqual(telemetryDocuments[1].ExceptionMessage, exceptionLong.Exception.Message.Substring(0, MaxFieldLength)); }