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 QuickPulseTelemetryProcessorStopsCollection()
        {
            // ARRANGE
            var accumulatorManager = new QuickPulseDataAccumulatorManager();
            var telemetryProcessor = new QuickPulseTelemetryProcessor(new SimpleTelemetryProcessorSpy());
            var endpoint           = new Uri("http://microsoft.com");
            var config             = new TelemetryConfiguration()
            {
                InstrumentationKey = "some ikey"
            };

            // ACT
            ((IQuickPulseTelemetryProcessor)telemetryProcessor).StartCollection(accumulatorManager, endpoint, config);
            telemetryProcessor.Process(new RequestTelemetry()
            {
                Context = { InstrumentationKey = "some ikey" }
            });
            ((IQuickPulseTelemetryProcessor)telemetryProcessor).StopCollection();
            telemetryProcessor.Process(new DependencyTelemetry()
            {
                Context = { InstrumentationKey = "some ikey" }
            });

            // ASSERT
            Assert.AreEqual(1, accumulatorManager.CurrentDataAccumulator.AIRequestCount);
            Assert.AreEqual(0, accumulatorManager.CurrentDataAccumulator.AIDependencyCallCount);
        }
        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 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);
        }
 /// <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 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);
        }
        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 PerformanceCounterTelemetry()
            {
                Context = { InstrumentationKey = "some ikey" }
            });
            telemetryProcessor.Process(new SessionStateTelemetry()
            {
                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 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 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 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 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);
        }
Exemple #12
0
        public void QuickPulseDataAccumulatorManagerLocksInSampleCorrectly()
        {
            // ARRANGE
            CollectionConfigurationError[] errors;
            CollectionConfiguration        collectionConfiguration =
                new CollectionConfiguration(
                    new CollectionConfigurationInfo()
            {
                ETag = string.Empty, Metrics = new CalculatedMetricInfo[0]
            },
                    out errors,
                    new ClockMock());
            var accumulatorManager = new QuickPulseDataAccumulatorManager(collectionConfiguration);

            accumulatorManager.CurrentDataAccumulator.AIRequestSuccessCount = 5;

            // ACT
            var completedSample = accumulatorManager.CompleteCurrentDataAccumulator(collectionConfiguration);

            // ASSERT
            Assert.AreEqual(5, completedSample.AIRequestSuccessCount);
            Assert.AreEqual(0, accumulatorManager.CurrentDataAccumulator.AIRequestSuccessCount);
            Assert.AreNotSame(completedSample, accumulatorManager.CurrentDataAccumulator);
        }
        public void QuickPulseTelemetryModuleSupportsMultipleTelemetryProcessorsForMultipleConfigurations()
        {
            if (QuickPulseTelemetryModuleTests.Ignored)
            {
                return;
            }

            // ARRANGE
            var pollingInterval           = TimeSpan.FromMilliseconds(1);
            var collectionInterval        = TimeSpan.FromMilliseconds(1);
            var timings                   = new QuickPulseTimings(pollingInterval, collectionInterval);
            var collectionTimeSlotManager = new QuickPulseCollectionTimeSlotManagerMock(timings);

            CollectionConfigurationError[] errors;
            var accumulatorManager =
                new QuickPulseDataAccumulatorManager(
                    new CollectionConfiguration(
                        new CollectionConfigurationInfo()
            {
                ETag = string.Empty, Metrics = new CalculatedMetricInfo[0]
            },
                        out errors,
                        new ClockMock()));
            var serviceClient = new QuickPulseServiceClientMock {
                ReturnValueFromPing = true, ReturnValueFromSubmitSample = true
            };
            var performanceCollector = new PerformanceCollectorMock();
            var topCpuCollector      = new QuickPulseTopCpuCollectorMock();

            var module = new QuickPulseTelemetryModule(
                collectionTimeSlotManager,
                accumulatorManager,
                serviceClient,
                performanceCollector,
                topCpuCollector,
                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
            int samplesWithSomeRequests     = serviceClient.SnappedSamples.Count(s => s.AIRequestsPerSecond > 0);
            int samplesWithSomeDependencies = serviceClient.SnappedSamples.Count(s => s.AIDependencyCallsPerSecond > 0);

            Assert.AreEqual(TelemetryProcessorCount, QuickPulseTestHelper.GetTelemetryProcessors(module).Count);
            Assert.IsTrue(samplesWithSomeRequests > 0 && samplesWithSomeRequests <= 2);
            Assert.AreEqual(1, serviceClient.SnappedSamples.Count(s => s.AIRequestsFailedPerSecond > 0));
            Assert.IsTrue(samplesWithSomeDependencies > 0 && samplesWithSomeDependencies < 2);
            Assert.AreEqual(1, serviceClient.SnappedSamples.Count(s => s.AIDependencyCallsFailedPerSecond > 0));
        }
        public void CollectionConfigurationCarriesOverQuotaWhenCreatingDocumentStreams()
        {
            // 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"
            };
            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[] documentStreams = newCollectionConfiguration.DocumentStreams.ToArray();
            Assert.AreEqual(5, documentStreams.Length);

            Assert.AreEqual("Stream1", documentStreams[0].Id);
            Assert.AreEqual(2, documentStreams[0].RequestQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[0].DependencyQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[0].ExceptionQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[0].EventQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[0].EventQuotaTracker.CurrentQuota);

            Assert.AreEqual("Stream2", documentStreams[1].Id);
            Assert.AreEqual(3, documentStreams[1].RequestQuotaTracker.CurrentQuota);
            Assert.AreEqual(1, documentStreams[1].DependencyQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[1].ExceptionQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[1].EventQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[1].EventQuotaTracker.CurrentQuota);

            Assert.AreEqual("Stream3", documentStreams[2].Id);
            Assert.AreEqual(3, documentStreams[2].RequestQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[2].DependencyQuotaTracker.CurrentQuota);
            Assert.AreEqual(0, documentStreams[2].ExceptionQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[2].EventQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[2].EventQuotaTracker.CurrentQuota);

            Assert.AreEqual("Stream4", documentStreams[3].Id);
            Assert.AreEqual(3, documentStreams[3].RequestQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[3].DependencyQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[3].ExceptionQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[3].EventQuotaTracker.CurrentQuota);
            Assert.AreEqual(3, documentStreams[3].EventQuotaTracker.CurrentQuota);
        }
        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);
        }