public void GetMetric_RespectsClientContext()
        {
            IList <ITelemetry>     sentTelemetry;
            TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out sentTelemetry);

            telemetryPipeline.InstrumentationKey = "754DD89F-61D6-4539-90C7-D886449E12BC";
            TelemetryClient client = new TelemetryClient(telemetryPipeline);

            Metric animalsSold = client.GetMetric("AnimalsSold", "Species", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryClient);

            animalsSold.TryTrackValue(10, "Cow");
            animalsSold.TryTrackValue(20, "Cow");
            client.GetMetricManager(MetricAggregationScope.TelemetryClient).Flush();

            animalsSold.TryTrackValue(100, "Rabbit");
            animalsSold.TryTrackValue(200, "Rabbit");

            client.Context.InstrumentationKey  = "3A3C34B6-CA2D-4372-B772-3B015E1E83DC";
            client.Context.Device.Model        = "Super-Fancy";
            client.Context.Properties["MyTag"] = "MyValue";

            animalsSold.TryTrackValue(30, "Cow");
            animalsSold.TryTrackValue(40, "Cow");
            animalsSold.TryTrackValue(300, "Rabbit");
            animalsSold.TryTrackValue(400, "Rabbit");
            client.GetMetricManager(MetricAggregationScope.TelemetryClient).Flush();

            Assert.AreEqual(3, sentTelemetry.Count);

            MetricTelemetry[] orderedTelemetry = sentTelemetry
                                                 .OrderByDescending((t) => ((MetricTelemetry)t).Count * 10000 + ((MetricTelemetry)t).Sum)
                                                 .Select((t) => (MetricTelemetry)t)
                                                 .ToArray();

            Util.ValidateNumericAggregateValues(orderedTelemetry[0], "AnimalsSold", 4, 1000, 400, 100, 111.803398874989);
            Assert.AreEqual(3, orderedTelemetry[0].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[0].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
            Assert.AreEqual("Rabbit", orderedTelemetry[0].Context.Properties["Species"]);
            Assert.AreEqual("MyValue", orderedTelemetry[0].Context.Properties["MyTag"]);
            Assert.AreEqual("Super-Fancy", orderedTelemetry[0].Context.Device.Model);
            Assert.AreEqual("3A3C34B6-CA2D-4372-B772-3B015E1E83DC", orderedTelemetry[0].Context.InstrumentationKey);

            Util.ValidateNumericAggregateValues(orderedTelemetry[1], "AnimalsSold", 2, 70, 40, 30, 5);
            Assert.AreEqual(3, orderedTelemetry[1].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[1].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
            Assert.AreEqual("Cow", orderedTelemetry[1].Context.Properties["Species"]);
            Assert.AreEqual("MyValue", orderedTelemetry[1].Context.Properties["MyTag"]);
            Assert.AreEqual("Super-Fancy", orderedTelemetry[1].Context.Device.Model);
            Assert.AreEqual("3A3C34B6-CA2D-4372-B772-3B015E1E83DC", orderedTelemetry[1].Context.InstrumentationKey);

            Util.ValidateNumericAggregateValues(orderedTelemetry[2], "AnimalsSold", 2, 30, 20, 10, 5);
            Assert.AreEqual(2, orderedTelemetry[2].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[2].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
            Assert.AreEqual("Cow", orderedTelemetry[2].Context.Properties["Species"]);
            Assert.IsNull(orderedTelemetry[2].Context.Device.Model);
            Assert.AreEqual("754DD89F-61D6-4539-90C7-D886449E12BC", orderedTelemetry[2].Context.InstrumentationKey);

            Util.CompleteDefaultAggregationCycle(client.GetMetricManager(MetricAggregationScope.TelemetryClient));
            telemetryPipeline.Dispose();
        }
Beispiel #2
0
        public void ResetAggregationDateTimeOffset()
        {
            // Do not start this test in the last 10 secs or first 2 secs of a minute, to make sure the timings below are likely to work out.

            while (DateTimeOffset.Now.Second >= 49 || DateTimeOffset.Now.Second < 3)
            {
                Thread.Sleep(TimeSpan.FromMilliseconds(500));
            }

            DateTimeOffset startTS = DateTimeOffset.Now;

            var aggregateCollector            = new MemoryMetricTelemetryPipeline();
            var manager                       = new MetricManager(aggregateCollector);
            IMetricSeriesConfiguration config = new MetricSeriesConfigurationForMeasurement(restrictToUInt32Values: false);
            MetricSeries series               = manager.CreateNewSeries("ns", "Foo Bar", config);

            series.TrackValue(0.4);
            series.TrackValue(2);
            series.TrackValue(-2);

            Thread.Sleep(TimeSpan.FromMilliseconds(1500));

            DateTimeOffset resetTS = DateTimeOffset.Now;

            series.ResetAggregation(resetTS);

            series.TrackValue(0.17);
            series.TrackValue(0.32);
            series.TrackValue(-0.15);
            series.TrackValue(1.07);

            Assert.AreEqual(0, aggregateCollector.Count);
            manager.Flush();
            Assert.AreEqual(1, aggregateCollector.Count);

            DateTimeOffset endTS = DateTimeOffset.Now;

            Util.ValidateNumericAggregateValues(aggregateCollector[0], name: "Foo Bar", count: 4, sum: 1.41, max: 1.07, min: -0.15, stdDev: 0.447681527427702, aggKindMoniker: "Microsoft.Azure.Measurement");

            // The following might break sometimes!
            // There is a little chance that second boundary is crossed between startTS and the aggregation timestamps are snapped.
            // rerun the test if it happens.

            Assert.AreNotEqual(
                new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                aggregateCollector[0].AggregationPeriodStart);

            Assert.AreEqual(
                new DateTimeOffset(resetTS.Year, resetTS.Month, resetTS.Day, resetTS.Hour, resetTS.Minute, resetTS.Second, 0, resetTS.Offset),
                aggregateCollector[0].AggregationPeriodStart);

            Util.CompleteDefaultAggregationCycle(manager);
        }
Beispiel #3
0
        public void TrackValueDouble()
        {
            DateTimeOffset startTS = DateTimeOffset.Now;

            var aggregateCollector            = new MemoryMetricTelemetryPipeline();
            var manager                       = new MetricManager(aggregateCollector);
            IMetricSeriesConfiguration config = new MetricSeriesConfigurationForMeasurement(restrictToUInt32Values: false);
            MetricSeries series               = manager.CreateNewSeries("ns", "Foo Bar", config);

            Thread.Sleep(1500);

            series.TrackValue(0.4);
            series.TrackValue(0.8);
            series.TrackValue(-0.04);

            Assert.AreEqual(0, aggregateCollector.Count);
            manager.Flush();
            Assert.AreEqual(1, aggregateCollector.Count);

            DateTimeOffset endTSRounded = DateTimeOffset.Now;

            endTSRounded = new DateTimeOffset(endTSRounded.Year, endTSRounded.Month, endTSRounded.Day, endTSRounded.Hour, endTSRounded.Minute, endTSRounded.Second, 0, endTSRounded.Offset);

            Util.ValidateNumericAggregateValues(aggregateCollector[0], name: "Foo Bar", count: 3, sum: 1.16, max: 0.8, min: -0.04, stdDev: 0.343058142140496, aggKindMoniker: "Microsoft.Azure.Measurement");

            // Timestamp checks have to be approximate, since we have no possibilityt to get exact timetamps snapped internally.

            // The following might break sometimes!
            // There is a little chance that second boundary is crossed between startTS and the aggregation timestamps are snapped.
            // rerun the test if it happens.

            Assert.AreEqual(
                new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                aggregateCollector[0].AggregationPeriodStart);

            const int millisecsTollerance = 50;
            long      durationMs          = (long)aggregateCollector[0].AggregationPeriodDuration.TotalMilliseconds;

            Assert.IsTrue(Math.Abs(durationMs - (endTSRounded - aggregateCollector[0].AggregationPeriodStart).TotalMilliseconds) < millisecsTollerance);

            Assert.AreEqual(1, aggregateCollector.Count);
            aggregateCollector.Clear();
            Assert.AreEqual(0, aggregateCollector.Count);

            manager.Flush();
            Assert.AreEqual(0, aggregateCollector.Count);

            Util.CompleteDefaultAggregationCycle(manager);
        }
        public void GetMetric_RespectsAggregationScope()
        {
            IList <ITelemetry>     sentTelemetry1, sentTelemetry2;
            TelemetryConfiguration telemetryPipeline1 = Util.CreateAITelemetryConfig(out sentTelemetry1);
            TelemetryConfiguration telemetryPipeline2 = Util.CreateAITelemetryConfig(out sentTelemetry2);
            TelemetryClient        client11           = new TelemetryClient(telemetryPipeline1);
            TelemetryClient        client12           = new TelemetryClient(telemetryPipeline1);
            TelemetryClient        client21           = new TelemetryClient(telemetryPipeline2);

            Metric metricA111 = client11.GetMetric("Metric A", "Dim1", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryConfiguration);

            metricA111.TrackValue(101);
            metricA111.TrackValue(102);
            metricA111.TryTrackValue(111, "Val");
            metricA111.TryTrackValue(112, "Val");

            Metric metricA112 = client11.GetMetric("Metric A", "Dim1", MetricConfigurations.Common.Measurement());

            metricA112.TrackValue(103);
            metricA112.TrackValue(104);
            metricA112.TryTrackValue(113, "Val");
            metricA112.TryTrackValue(114, "Val");

            Metric metricA113 = client11.GetMetric("Metric A", "Dim1");

            metricA113.TrackValue(105);
            metricA113.TrackValue(106);
            metricA113.TryTrackValue(115, "Val");
            metricA113.TryTrackValue(116, "Val");

            Assert.AreSame(metricA111, metricA112);
            Assert.AreSame(metricA111, metricA113);
            Assert.AreSame(metricA112, metricA113);

            MetricSeries series1, series2;

            Assert.IsTrue(metricA111.TryGetDataSeries(out series1));
            Assert.IsTrue(metricA112.TryGetDataSeries(out series2));
            Assert.AreSame(series1, series2);
            Assert.IsTrue(metricA113.TryGetDataSeries(out series2));
            Assert.AreSame(series1, series2);
            Assert.IsTrue(metricA112.TryGetDataSeries(out series1));
            Assert.AreSame(series1, series2);

            Assert.IsTrue(metricA111.TryGetDataSeries(out series1, "Val"));
            Assert.IsTrue(metricA112.TryGetDataSeries(out series2, "Val"));
            Assert.AreSame(series1, series2);
            Assert.IsTrue(metricA113.TryGetDataSeries(out series2, "Val"));
            Assert.AreSame(series1, series2);
            Assert.IsTrue(metricA112.TryGetDataSeries(out series1, "Val"));
            Assert.AreSame(series1, series2);

            Metric metricA121 = client12.GetMetric("Metric A", "Dim1", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryConfiguration);

            metricA121.TrackValue(107);
            metricA121.TrackValue(108);
            metricA121.TryTrackValue(117, "Val");
            metricA121.TryTrackValue(118, "Val");

            Assert.AreSame(metricA111, metricA121);

            Metric metricA211 = client21.GetMetric("Metric A", "Dim1", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryConfiguration);

            metricA211.TrackValue(201);
            metricA211.TrackValue(202);
            metricA211.TryTrackValue(211, "Val");
            metricA211.TryTrackValue(212, "Val");

            Assert.AreNotSame(metricA111, metricA211);

            Metric metricA11c1 = client11.GetMetric("Metric A", "Dim1", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryClient);

            metricA11c1.TrackValue(301);
            metricA11c1.TrackValue(302);
            metricA11c1.TryTrackValue(311, "Val");
            metricA11c1.TryTrackValue(312, "Val");

            Metric metricA11c2 = client11.GetMetric("Metric A", "Dim1", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryClient);

            metricA11c2.TrackValue(303);
            metricA11c2.TrackValue(304);
            metricA11c2.TryTrackValue(313, "Val");
            metricA11c2.TryTrackValue(314, "Val");

            Assert.AreNotSame(metricA111, metricA11c1);
            Assert.AreSame(metricA11c1, metricA11c2);

            Assert.IsTrue(metricA11c1.TryGetDataSeries(out series1));
            Assert.IsTrue(metricA11c1.TryGetDataSeries(out series2));
            Assert.AreSame(series1, series2);

            Assert.IsTrue(metricA11c1.TryGetDataSeries(out series1, "Val"));
            Assert.IsTrue(metricA11c1.TryGetDataSeries(out series2, "Val"));
            Assert.AreSame(series1, series2);

            Metric metricA12c1 = client12.GetMetric("Metric A", "Dim1", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryClient);

            metricA12c1.TrackValue(305);
            metricA12c1.TrackValue(306);
            metricA12c1.TryTrackValue(315, "Val");
            metricA12c1.TryTrackValue(316, "Val");

            Assert.AreNotSame(metricA11c1, metricA12c1);

            client11.GetMetricManager(MetricAggregationScope.TelemetryClient).Flush();
            client12.GetMetricManager(MetricAggregationScope.TelemetryClient).Flush();
            client21.GetMetricManager(MetricAggregationScope.TelemetryClient).Flush();
            telemetryPipeline1.GetMetricManager().Flush();
            telemetryPipeline2.GetMetricManager().Flush();

            Assert.AreEqual(6, sentTelemetry1.Count);
            Assert.AreEqual(2, sentTelemetry2.Count);

            MetricTelemetry[] orderedTelemetry = sentTelemetry1
                                                 .OrderByDescending((t) => ((MetricTelemetry)t).Count * 10000 + ((MetricTelemetry)t).Sum)
                                                 .Select((t) => (MetricTelemetry)t)
                                                 .ToArray();

            Util.ValidateNumericAggregateValues(orderedTelemetry[0], "Metric A", 8, 916, 118, 111, 2.29128784747792);
            Assert.AreEqual(2, orderedTelemetry[0].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[0].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
            Assert.AreEqual("Val", orderedTelemetry[0].Context.Properties["Dim1"]);

            Util.ValidateNumericAggregateValues(orderedTelemetry[1], "Metric A", 8, 836, 108, 101, 2.29128784747792);
            Assert.AreEqual(1, orderedTelemetry[1].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[1].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

            Util.ValidateNumericAggregateValues(orderedTelemetry[2], "Metric A", 4, 1250, 314, 311, 1.11803398874989);
            Assert.AreEqual(2, orderedTelemetry[2].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[2].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
            Assert.AreEqual("Val", orderedTelemetry[2].Context.Properties["Dim1"]);

            Util.ValidateNumericAggregateValues(orderedTelemetry[3], "Metric A", 4, 1210, 304, 301, 1.11803398874989);
            Assert.AreEqual(1, orderedTelemetry[3].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[3].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

            Util.ValidateNumericAggregateValues(orderedTelemetry[4], "Metric A", 2, 631, 316, 315, 0.5);
            Assert.AreEqual(2, orderedTelemetry[4].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[4].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
            Assert.AreEqual("Val", orderedTelemetry[4].Context.Properties["Dim1"]);

            Util.ValidateNumericAggregateValues(orderedTelemetry[5], "Metric A", 2, 611, 306, 305, 0.5);
            Assert.AreEqual(1, orderedTelemetry[5].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[5].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));

            orderedTelemetry = sentTelemetry2
                               .OrderByDescending((t) => ((MetricTelemetry)t).Count * 10000 + ((MetricTelemetry)t).Sum)
                               .Select((t) => (MetricTelemetry)t)
                               .ToArray();

            Util.ValidateNumericAggregateValues(orderedTelemetry[0], "Metric A", 2, 423, 212, 211, 0.5);
            Assert.AreEqual(2, orderedTelemetry[0].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[0].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
            Assert.AreEqual("Val", orderedTelemetry[0].Context.Properties["Dim1"]);

            Util.ValidateNumericAggregateValues(orderedTelemetry[1], "Metric A", 2, 403, 202, 201, 0.5);
            Assert.AreEqual(1, orderedTelemetry[1].Context.Properties.Count);
            Assert.IsTrue(orderedTelemetry[1].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));


            Metric metricB21c1 = client21.GetMetric("Metric B", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryClient);

            TelemetryClient client22 = new TelemetryClient(telemetryPipeline2);
            TelemetryClient client23 = new TelemetryClient(telemetryPipeline2);

            Assert.AreNotSame(metricB21c1, client22.GetMetric("Metric B", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryClient));
            Assert.AreSame(metricB21c1, client21.GetMetric("Metric B", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryClient));
            Assert.ThrowsException <ArgumentException>(() => client21.GetMetric("Metric B", MetricConfigurations.Common.Accumulator(), MetricAggregationScope.TelemetryClient));
            Assert.IsNotNull(client23.GetMetric("Metric B", MetricConfigurations.Common.Accumulator(), MetricAggregationScope.TelemetryClient));

            Metric metricB211 = client21.GetMetric("Metric B", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryConfiguration);

            TelemetryClient client24 = new TelemetryClient(telemetryPipeline2);
            TelemetryClient client25 = new TelemetryClient(telemetryPipeline2);

            Assert.AreSame(metricB211, client24.GetMetric("Metric B", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryConfiguration));
            Assert.AreSame(metricB211, client21.GetMetric("Metric B", MetricConfigurations.Common.Measurement(), MetricAggregationScope.TelemetryConfiguration));
            Assert.ThrowsException <ArgumentException>(() => client21.GetMetric("Metric B", MetricConfigurations.Common.Accumulator(), MetricAggregationScope.TelemetryConfiguration));
            Assert.ThrowsException <ArgumentException>(() => client25.GetMetric("Metric B", MetricConfigurations.Common.Accumulator(), MetricAggregationScope.TelemetryConfiguration));

            Assert.ThrowsException <ArgumentException>(() => client11.GetMetric("Metric C", MetricConfigurations.Common.Accumulator(), (MetricAggregationScope)42));

            Util.CompleteDefaultAggregationCycle(
                client11.GetMetricManager(MetricAggregationScope.TelemetryClient),
                client12.GetMetricManager(MetricAggregationScope.TelemetryClient),
                client21.GetMetricManager(MetricAggregationScope.TelemetryClient),
                client22.GetMetricManager(MetricAggregationScope.TelemetryClient),
                client23.GetMetricManager(MetricAggregationScope.TelemetryClient),
                client24.GetMetricManager(MetricAggregationScope.TelemetryClient),
                client25.GetMetricManager(MetricAggregationScope.TelemetryClient),
                telemetryPipeline2.GetMetricManager(),
                telemetryPipeline1.GetMetricManager());

            telemetryPipeline1.Dispose();
            telemetryPipeline2.Dispose();
        }
        public void GetMetric_SendsData()
        {
            IList <ITelemetry>     sentTelemetry;
            TelemetryConfiguration telemetryPipeline = Util.CreateAITelemetryConfig(out sentTelemetry);
            TelemetryClient        client            = new TelemetryClient(telemetryPipeline);

            {
                Metric metric = client.GetMetric("CowsSold");
                Assert.IsNotNull(metric);
                Assert.AreEqual(0, metric.Identifier.DimensionsCount);
                Assert.AreEqual("CowsSold", metric.Identifier.MetricId);
                Assert.AreEqual(MetricConfigurations.Common.Measurement(), metric.GetConfiguration());

                metric.TrackValue(0.5);
                metric.TrackValue(0.6);
                Assert.ThrowsException <ArgumentException>(() => metric.TryTrackValue(1.5, "A"));
                Assert.ThrowsException <ArgumentException>(() => metric.TryTrackValue(2.5, "A", "X"));

                telemetryPipeline.GetMetricManager().Flush();
                Assert.AreEqual(1, sentTelemetry.Count);
                Util.ValidateNumericAggregateValues(sentTelemetry[0], "CowsSold", 2, 1.1, 0.6, 0.5, 0.05);
                Assert.AreEqual(1, sentTelemetry[0].Context.Properties.Count);
                Assert.IsTrue(sentTelemetry[0].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                sentTelemetry.Clear();

                metric.TrackValue(0.7);
                metric.TrackValue(0.8);

                telemetryPipeline.GetMetricManager().Flush();
                Assert.AreEqual(1, sentTelemetry.Count);
                Util.ValidateNumericAggregateValues(sentTelemetry[0], "CowsSold", 2, 1.5, 0.8, 0.7, 0.05);
                Assert.AreEqual(1, sentTelemetry[0].Context.Properties.Count);
                Assert.IsTrue(sentTelemetry[0].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                sentTelemetry.Clear();
            }
            {
                Metric metric = client.GetMetric("CowsSold", "Color", MetricConfigurations.Common.Accumulator());
                Assert.IsNotNull(metric);
                Assert.AreEqual(1, metric.Identifier.DimensionsCount);
                Assert.AreEqual("CowsSold", metric.Identifier.MetricId);
                Assert.AreEqual(MetricConfigurations.Common.Accumulator(), metric.GetConfiguration());

                metric.TryTrackValue(0.5, "Purple");
                metric.TryTrackValue(0.6, "Purple");
                Assert.ThrowsException <ArgumentException>(() => metric.TryTrackValue(2.5, "A", "X"));

                telemetryPipeline.GetMetricManager().Flush();
                Assert.AreEqual(1, sentTelemetry.Count);
                Util.ValidateNumericAggregateValues(sentTelemetry[0], "CowsSold", 1, 1.1, 1.1, 0.5, null);
                Assert.AreEqual(2, sentTelemetry[0].Context.Properties.Count);
                Assert.IsTrue(sentTelemetry[0].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                Assert.AreEqual("Purple", sentTelemetry[0].Context.Properties["Color"]);
                sentTelemetry.Clear();

                metric.TryTrackValue(0.7, "Purple");
                metric.TryTrackValue(0.8, "Purple");

                telemetryPipeline.GetMetricManager().Flush();
                Assert.AreEqual(1, sentTelemetry.Count);
                Util.ValidateNumericAggregateValues(sentTelemetry[0], "CowsSold", 1, 2.6, 2.6, 0.5, null);
                Assert.AreEqual(2, sentTelemetry[0].Context.Properties.Count);
                Assert.IsTrue(sentTelemetry[0].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                Assert.AreEqual("Purple", sentTelemetry[0].Context.Properties["Color"]);
                sentTelemetry.Clear();
            }
            {
                Metric metric = client.GetMetric("CowsSold", "Color", "Size", MetricConfigurations.Common.Accumulator());
                Assert.IsNotNull(metric);
                Assert.AreEqual(2, metric.Identifier.DimensionsCount);
                Assert.AreEqual("CowsSold", metric.Identifier.MetricId);
                Assert.AreEqual(MetricConfigurations.Common.Accumulator(), metric.GetConfiguration());

                metric.TryTrackValue(0.5, "Purple", "Large");
                metric.TryTrackValue(0.6, "Purple", "Large");

                telemetryPipeline.GetMetricManager().Flush();
                Assert.AreEqual(2, sentTelemetry.Count);

                MetricTelemetry[] orderedTelemetry = sentTelemetry
                                                     .OrderByDescending((t) => ((MetricTelemetry)t).Count * 10000 + ((MetricTelemetry)t).Sum)
                                                     .Select((t) => (MetricTelemetry)t)
                                                     .ToArray();

                // This one is from the prev section:
                Util.ValidateNumericAggregateValues(orderedTelemetry[0], "CowsSold", 1, 2.6, 2.6, 0.5, null);
                Assert.AreEqual(2, orderedTelemetry[0].Context.Properties.Count);
                Assert.IsTrue(orderedTelemetry[0].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                Assert.AreEqual("Purple", orderedTelemetry[0].Context.Properties["Color"]);

                Util.ValidateNumericAggregateValues(orderedTelemetry[1], "CowsSold", 1, 1.1, 1.1, 0.5, null);
                Assert.AreEqual(3, orderedTelemetry[1].Context.Properties.Count);
                Assert.IsTrue(orderedTelemetry[1].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                Assert.AreEqual("Purple", orderedTelemetry[1].Context.Properties["Color"]);
                Assert.AreEqual("Large", orderedTelemetry[1].Context.Properties["Size"]);
                sentTelemetry.Clear();

                metric.TryTrackValue(0.7, "Purple", "Large");
                metric.TryTrackValue(0.8, "Purple", "Small");

                telemetryPipeline.GetMetricManager().Flush();
                Assert.AreEqual(3, sentTelemetry.Count);

                orderedTelemetry = sentTelemetry
                                   .OrderByDescending((t) => ((MetricTelemetry)t).Count * 10000 + ((MetricTelemetry)t).Sum)
                                   .Select((t) => (MetricTelemetry)t)
                                   .ToArray();

                // This one is from the prev section:
                Util.ValidateNumericAggregateValues(orderedTelemetry[0], "CowsSold", 1, 2.6, 2.6, 0.5, null);
                Assert.AreEqual(2, orderedTelemetry[0].Context.Properties.Count);
                Assert.IsTrue(orderedTelemetry[0].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                Assert.AreEqual("Purple", orderedTelemetry[0].Context.Properties["Color"]);

                Util.ValidateNumericAggregateValues(orderedTelemetry[1], "CowsSold", 1, 1.8, 1.8, 0.5, null);
                Assert.AreEqual(3, orderedTelemetry[1].Context.Properties.Count);
                Assert.IsTrue(orderedTelemetry[1].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                Assert.AreEqual("Purple", orderedTelemetry[1].Context.Properties["Color"]);
                Assert.AreEqual("Large", orderedTelemetry[1].Context.Properties["Size"]);

                Util.ValidateNumericAggregateValues(orderedTelemetry[2], "CowsSold", 1, 0.8, 0.8, 0.8, null);
                Assert.AreEqual(3, orderedTelemetry[2].Context.Properties.Count);
                Assert.IsTrue(orderedTelemetry[2].Context.Properties.ContainsKey(Util.AggregationIntervalMonikerPropertyKey));
                Assert.AreEqual("Purple", orderedTelemetry[2].Context.Properties["Color"]);
                Assert.AreEqual("Small", orderedTelemetry[2].Context.Properties["Size"]);

                sentTelemetry.Clear();
            }

            Util.CompleteDefaultAggregationCycle(telemetryPipeline.GetMetricManager());
            telemetryPipeline.Dispose();
        }
Beispiel #6
0
        public void GetCurrentAggregateUnsafe_MetricAggregationCycleKind_DateTimeOffset_Accumulator()
        {
            IMetricSeriesConfiguration seriesConfig = new MetricSeriesConfigurationForAccumulator(restrictToUInt32Values: false);
            const string aggregationKindMoniker     = "Microsoft.Azure.Accumulator";

            // Do not start this test in the last 10 secs or first 2 secs of a minute, to make sure the timings below are likely to work out.

            while (DateTimeOffset.Now.Second >= 49 || DateTimeOffset.Now.Second < 3)
            {
                Thread.Sleep(TimeSpan.FromMilliseconds(500));
            }

            DateTimeOffset startTS = DateTimeOffset.Now;

            var          aggregateCollector = new MemoryMetricTelemetryPipeline();
            var          manager            = new MetricManager(aggregateCollector);
            MetricSeries series             = manager.CreateNewSeries("ns", "Foo Bar", seriesConfig);

            DateTimeOffset stepTS        = startTS.AddMinutes(2);
            DateTimeOffset stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);
                Assert.IsNull(aggregate);

                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);
                Assert.IsNull(aggregate);

                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);
                Assert.IsNull(aggregate);
            }

            series.TrackValue(0.4);
            series.TrackValue(2);
            series.TrackValue(-2);

            stepTS        = stepTS.AddMinutes(2);
            stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);


            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);

                Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 0.4, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                Assert.AreEqual(
                    new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                    aggregate.AggregationPeriodStart);

                Assert.AreEqual(
                    (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                    aggregate.AggregationPeriodDuration.TotalMilliseconds);

                {
                    Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);

                    aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);
                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 0.4, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);


                    aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);
                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 0.4, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }
            }

            DateTimeOffset customCycleStartTS = stepTS.AddMinutes(1);

            manager.StartOrCycleAggregators(MetricAggregationCycleKind.Custom, customCycleStartTS, futureFilter: null);

            series.TrackValue(0.17);
            series.TrackValue(0.32);
            series.TrackValue(-0.15);
            series.TrackValue(1.07);

            stepTS        = stepTS.AddMinutes(2);
            stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);

                Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 1.81, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.

                Assert.AreEqual(
                    new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                    aggregate.AggregationPeriodStart);

                Assert.AreEqual(
                    (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                    aggregate.AggregationPeriodDuration.TotalMilliseconds);


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);

                {
                    Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 1.81, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.

                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }

                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);

                {
                    Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 1.81, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.

                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }
            }

            Thread.Sleep(1500);
            DateTimeOffset flushTS = DateTimeOffset.Now;

            manager.Flush();


            DateTimeOffset quickPulseCycleStartTS = stepTS.AddMinutes(1);

            manager.StartOrCycleAggregators(MetricAggregationCycleKind.QuickPulse, quickPulseCycleStartTS, futureFilter: null);

            stepTS        = stepTS.AddMinutes(2);
            stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);

                {
                    Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 1.81, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.

                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);

                {
                    Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 1.81, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.

                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);

                {
                    Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 1.81, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.

                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }
            }

            series.TrackValue(0);
            series.TrackValue(-10);

            stepTS        = stepTS.AddMinutes(2);
            stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);

            manager.StopAggregators(MetricAggregationCycleKind.Custom, stepTS);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);

                {
                    Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: -8.19, max: 2.4, min: -8.19, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);

                if (seriesConfig.RequiresPersistentAggregation)
                {
                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: -8.19, max: 2.4, min: -8.19, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }
                else
                {
                    Assert.IsNull(aggregate);
                }


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);

                {
                    Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: -8.19, max: 2.4, min: -8.19, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                    Assert.AreEqual(
                        new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }
            }

            Util.CompleteDefaultAggregationCycle(manager);
        }
Beispiel #7
0
        public void GetCurrentAggregateUnsafe_Accumulator()
        {
            IMetricSeriesConfiguration seriesConfig = new MetricSeriesConfigurationForAccumulator(restrictToUInt32Values: false);
            const string aggregationKindMoniker     = "Microsoft.Azure.Accumulator";

            // Do not start this test in the last 10 secs or first 2 secs of a minute, to make sure the timings below are likely to work out.

            while (DateTimeOffset.Now.Second >= 49 || DateTimeOffset.Now.Second < 3)
            {
                Thread.Sleep(TimeSpan.FromMilliseconds(500));
            }

            DateTimeOffset startTS = DateTimeOffset.Now;

            var          aggregateCollector = new MemoryMetricTelemetryPipeline();
            var          manager            = new MetricManager(aggregateCollector);
            MetricSeries series             = manager.CreateNewSeries("ns", "Foo Bar", seriesConfig);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe();
                Assert.IsNull(aggregate);
            }

            series.TrackValue(0.4);
            series.TrackValue(2);
            series.TrackValue(-2);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe();
                Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 0.4, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                // The following might break sometimes!
                // There is a little chance that second boundary is crossed between test TS and the aggregation timestamps are snapped.
                // rerun the test if it happens.

                Assert.AreEqual(
                    new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                    aggregate.AggregationPeriodStart);
            }

            series.TrackValue(0.17);
            series.TrackValue(0.32);
            series.TrackValue(-0.15);
            series.TrackValue(1.07);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe();

                Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 1.81, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                // The following might break sometimes!
                // There is a little chance that second boundary is crossed between test TS and the aggregation timestamps are snapped.
                // rerun the test if it happens.

                Assert.AreEqual(
                    new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                    aggregate.AggregationPeriodStart);
            }

            Thread.Sleep(1500);
            DateTimeOffset flushTS = DateTimeOffset.Now;

            manager.Flush();
            {
                Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe();

                Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 1.81, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                // The following might break sometimes!
                // There is a little chance that second boundary is crossed between test TS and the aggregation timestamps are snapped.
                // rerun the test if it happens.

                Assert.AreEqual(
                    new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                    aggregate.AggregationPeriodStart);
            }

            series.TrackValue(0);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe();

                Assert.IsTrue(seriesConfig.RequiresPersistentAggregation);
                Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 0, sum: 1.81, max: 2.4, min: 0.4, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                // The following might break sometimes!
                // There is a little chance that second boundary is crossed between test TS and the aggregation timestamps are snapped.
                // rerun the test if it happens.

                Assert.AreEqual(
                    new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                    aggregate.AggregationPeriodStart);
            }

            Util.CompleteDefaultAggregationCycle(manager);
        }
        public void GetCurrentAggregateUnsafe_MetricAggregationCycleKind_DateTimeOffset_Measurement()
        {
            IMetricSeriesConfiguration seriesConfig = new MetricSeriesConfigurationForMeasurement(restrictToUInt32Values: false);
            const string aggregationKindMoniker     = "Microsoft.Azure.Measurement";

            // Do not start this test in the last 10 secs or first 2 secs of a minute, to make sure the timings below are likely to work out.

            while (DateTimeOffset.Now.Second >= 49 || DateTimeOffset.Now.Second < 3)
            {
                Thread.Sleep(TimeSpan.FromMilliseconds(500));
            }

            DateTimeOffset startTS = DateTimeOffset.Now;

            var          aggregateCollector = new MemoryMetricTelemetryPipeline();
            var          manager            = new MetricManager(aggregateCollector);
            MetricSeries series             = manager.CreateNewSeries("Foo Bar", seriesConfig);

            DateTimeOffset stepTS        = startTS.AddMinutes(2);
            DateTimeOffset stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);
                Assert.IsNull(aggregate);

                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);
                Assert.IsNull(aggregate);

                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);
                Assert.IsNull(aggregate);
            }

            series.TrackValue(0.4);
            series.TrackValue(2);
            series.TrackValue(-2);

            stepTS        = stepTS.AddMinutes(2);
            stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);


            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);

                Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 3, sum: 0.4, max: 2, min: -2, stdDev: 1.64384373412506, aggKindMoniker: aggregationKindMoniker);

                // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                Assert.AreEqual(
                    new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                    aggregate.AggregationPeriodStart);

                Assert.AreEqual(
                    (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                    aggregate.AggregationPeriodDuration.TotalMilliseconds);

                {
                    Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);

                    aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);
                    Assert.IsNull(aggregate);

                    aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);
                    Assert.IsNull(aggregate);
                }
            }

            DateTimeOffset customCycleStartTS = stepTS.AddMinutes(1);

            manager.StartOrCycleAggregators(MetricAggregationCycleKind.Custom, customCycleStartTS, futureFilter: null);

            series.TrackValue(0.17);
            series.TrackValue(0.32);
            series.TrackValue(-0.15);
            series.TrackValue(1.07);

            stepTS        = stepTS.AddMinutes(2);
            stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);

                Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 7, sum: 1.81, max: 2, min: -2, stdDev: 1.13330652229191, aggKindMoniker: aggregationKindMoniker);

                // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.

                Assert.AreEqual(
                    new DateTimeOffset(startTS.Year, startTS.Month, startTS.Day, startTS.Hour, startTS.Minute, startTS.Second, 0, startTS.Offset),
                    aggregate.AggregationPeriodStart);

                Assert.AreEqual(
                    (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                    aggregate.AggregationPeriodDuration.TotalMilliseconds);


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);

                {
                    Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 4, sum: 1.41, max: 1.07, min: -0.15, stdDev: 0.447681527427702, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.

                    Assert.AreEqual(
                        new DateTimeOffset(customCycleStartTS.Year, customCycleStartTS.Month, customCycleStartTS.Day, customCycleStartTS.Hour, customCycleStartTS.Minute, customCycleStartTS.Second, 0, customCycleStartTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }

                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);

                {
                    Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);
                    Assert.IsNull(aggregate);
                }
            }

            Thread.Sleep(1500);
            DateTimeOffset flushTS = DateTimeOffset.Now;

            manager.Flush();


            DateTimeOffset quickPulseCycleStartTS = stepTS.AddMinutes(1);

            manager.StartOrCycleAggregators(MetricAggregationCycleKind.QuickPulse, quickPulseCycleStartTS, futureFilter: null);

            stepTS        = stepTS.AddMinutes(2);
            stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);

                {
                    Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);
                    Assert.IsNull(aggregate);
                }


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);

                {
                    Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);

                    // Custom was not cycled by Flush.
                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 4, sum: 1.41, max: 1.07, min: -0.15, stdDev: 0.447681527427702, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                    Assert.AreEqual(
                        new DateTimeOffset(customCycleStartTS.Year, customCycleStartTS.Month, customCycleStartTS.Day, customCycleStartTS.Hour, customCycleStartTS.Minute, customCycleStartTS.Second, 0, customCycleStartTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);

                    manager.StartOrCycleAggregators(MetricAggregationCycleKind.Custom, flushTS, null);

                    aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);
                    Assert.IsNull(aggregate);
                }


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);

                {
                    Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);

                    // We started QP cycle now, but we did not write values since then.
                    Assert.IsNull(aggregate);
                }
            }

            series.TrackValue(0);

            stepTS        = stepTS.AddMinutes(2);
            stepTSRounded = new DateTimeOffset(stepTS.Year, stepTS.Month, stepTS.Day, stepTS.Hour, stepTS.Minute, stepTS.Second, 0, stepTS.Offset);

            manager.StopAggregators(MetricAggregationCycleKind.Custom, stepTS);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Default, stepTS);

                {
                    Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 1, sum: 0, max: 0, min: 0, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                    Assert.AreEqual(
                        new DateTimeOffset(flushTS.Year, flushTS.Month, flushTS.Day, flushTS.Hour, flushTS.Minute, flushTS.Second, 0, flushTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.Custom, stepTS);

                {
                    Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);

                    Assert.IsNull(aggregate);
                }


                aggregate = series.GetCurrentAggregateUnsafe(MetricAggregationCycleKind.QuickPulse, stepTS);

                {
                    Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);

                    Util.ValidateNumericAggregateValues(aggregate, name: "Foo Bar", count: 1, sum: 0, max: 0, min: 0, stdDev: 0, aggKindMoniker: aggregationKindMoniker);

                    // This might break: Second boundary might be crossed between snapping test and the aggregation timestamps. Try re-running.
                    Assert.AreEqual(
                        new DateTimeOffset(quickPulseCycleStartTS.Year, quickPulseCycleStartTS.Month, quickPulseCycleStartTS.Day, quickPulseCycleStartTS.Hour, quickPulseCycleStartTS.Minute, quickPulseCycleStartTS.Second, 0, quickPulseCycleStartTS.Offset),
                        aggregate.AggregationPeriodStart);

                    Assert.AreEqual(
                        (stepTSRounded - aggregate.AggregationPeriodStart).TotalMilliseconds,
                        aggregate.AggregationPeriodDuration.TotalMilliseconds);
                }
            }

            Util.CompleteDefaultAggregationCycle(manager);
        }