Example #1
0
        public void Ctor()
        {
            Assert.ThrowsException <ArgumentNullException>(() => new MetricManager(telemetryPipeline: null));

            var manager = new MetricManager(new MemoryMetricTelemetryPipeline());

            Assert.IsNotNull(manager);

            Util.CompleteDefaultAggregationCycle(manager);
        }
Example #2
0
        public DefaultAggregationPeriodCycle(MetricAggregationManager aggregationManager, MetricManager metricManager)
        {
            Util.ValidateNotNull(aggregationManager, nameof(aggregationManager));
            Util.ValidateNotNull(metricManager, nameof(metricManager));

            this.aggregationManager = aggregationManager;
            this.metricManager      = metricManager;

            this.runningState = RunningState_NotStarted;
            this.workerTaskCompletionControl = new TaskCompletionSource <bool>();
            this.aggregationThread           = null;
        }
        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;

            TestUtil.ValidateNumericAggregateValues(aggregateCollector[0], ns: "ns", 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);

            TestUtil.CompleteDefaultAggregationCycle(manager);
        }
        public void Properties()
        {
            var manager = new MetricManager(new MemoryMetricTelemetryPipeline());
            IMetricSeriesConfiguration config = new MetricSeriesConfigurationForMeasurement(restrictToUInt32Values: false);
            MetricSeries series = manager.CreateNewSeries("Foo Bar", config);

            Assert.AreEqual("Foo Bar", series.MetricId);

            Assert.AreEqual(config, series.GetConfiguration());
            Assert.AreSame(config, series.GetConfiguration());

            Util.CompleteDefaultAggregationCycle(manager);
        }
        public DefaultAggregationPeriodCycle(MetricAggregationManager aggregationManager, MetricManager metricManager)
        {
            Util.ValidateNotNull(aggregationManager, nameof(aggregationManager));
            Util.ValidateNotNull(metricManager, nameof(metricManager));

            _workerMethod = this.Run;

            _aggregationManager = aggregationManager;
            _metricManager      = metricManager;

            _runningState = RunningState_NotStarted;
            _workerTask   = null;
        }
Example #6
0
        public void Flush()
        {
            {
                var metricsCollector = new MemoryMetricTelemetryPipeline();
                var manager          = new MetricManager(metricsCollector);
                manager.Flush();

                Assert.AreEqual(0, metricsCollector.Count);
                TestUtil.CompleteDefaultAggregationCycle(manager);
            }
            {
                var metricsCollector = new MemoryMetricTelemetryPipeline();
                var manager          = new MetricManager(metricsCollector);

                IMetricSeriesConfiguration measurementConfig = new MetricSeriesConfigurationForMeasurement(restrictToUInt32Values: false);

                MetricSeries series1 = manager.CreateNewSeries("Test Metrics", "Measurement 1", measurementConfig);
                MetricSeries series2 = manager.CreateNewSeries("Test Metrics", "Measurement 2", measurementConfig);

                series1.TrackValue(1);
                series1.TrackValue(1);
                series1.TrackValue(1);

                series2.TrackValue(-1);
                series2.TrackValue(-1);
                series2.TrackValue(-1);

                manager.Flush();

                Assert.AreEqual(2, metricsCollector.Count);

                Assert.AreEqual(1, metricsCollector.Where((item) => item.MetricId.Equals("Measurement 1")).Count());
                Assert.AreEqual("Test Metrics", (metricsCollector.First((item) => item.MetricId.Equals("Measurement 1"))).MetricNamespace);
                Assert.AreEqual(3, (metricsCollector.First((item) => item.MetricId.Equals("Measurement 1"))).Data["Count"]);
                Assert.AreEqual(3.0, (metricsCollector.First((item) => item.MetricId.Equals("Measurement 1"))).Data["Sum"]);

                Assert.AreEqual(1, metricsCollector.Where((item) => item.MetricId.Equals("Measurement 2")).Count());
                Assert.AreEqual("Test Metrics", (metricsCollector.First((item) => item.MetricId.Equals("Measurement 2"))).MetricNamespace);
                Assert.AreEqual(3, (metricsCollector.First((item) => item.MetricId.Equals("Measurement 2"))).Data["Count"]);
                Assert.AreEqual(-3.0, (metricsCollector.First((item) => item.MetricId.Equals("Measurement 2"))).Data["Sum"]);

                metricsCollector.Clear();
                Assert.AreEqual(0, metricsCollector.Count);

                manager.Flush();

                Assert.AreEqual(0, metricsCollector.Count);

                TestUtil.CompleteDefaultAggregationCycle(manager);
            }
        }
        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);

            TestUtil.ValidateNumericAggregateValues(aggregateCollector[0], ns: "ns", 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);

            TestUtil.CompleteDefaultAggregationCycle(manager);
        }
Example #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="telemetryPipeline"></param>
        /// <returns></returns>
        public static MetricManager Metrics(this TelemetryConfiguration telemetryPipeline)
        {
            if (telemetryPipeline == null)
            {
                return(null);
            }

            // Fast path for the default configuration:
            if (telemetryPipeline == TelemetryConfiguration.Active)
            {
                MetricManager manager = s_defaultMetricManager;
                if (manager == null)
                {
                    var           pipelineAdapter = new ApplicationInsightsTelemetryPipeline(telemetryPipeline);
                    MetricManager newManager      = new MetricManager(pipelineAdapter);
                    MetricManager prevManager     = Interlocked.CompareExchange(ref s_defaultMetricManager, newManager, null);

                    if (prevManager == null)
                    {
                        return(newManager);
                    }
                    else
                    {
                        Task fireAndForget = newManager.StopDefaultAggregationCycleAsync();
                        return(prevManager);
                    }
                }

                return(manager);
            }

            // Ok, we have a non-default config. Get the table:

            ConditionalWeakTable <TelemetryConfiguration, MetricManager> metricManagers = s_metricManagers;

            if (metricManagers == null)
            {
                ConditionalWeakTable <TelemetryConfiguration, MetricManager> newTable  = new ConditionalWeakTable <TelemetryConfiguration, MetricManager>();
                ConditionalWeakTable <TelemetryConfiguration, MetricManager> prevTable = Interlocked.CompareExchange(ref s_metricManagers, newTable, null);
                metricManagers = prevTable ?? newTable;
            }

            // Get the manager from the table:
            {
                MetricManager manager = GetOrGreateFromTable(telemetryPipeline, metricManagers);
                return(manager);
            }
        }
        public void CreateNewSeries()
        {
            var manager = new MetricManager(new MemoryMetricTelemetryPipeline());

            IMetricSeriesConfiguration config = new SimpleMetricSeriesConfiguration(restrictToUInt32Values: false);

            Assert.ThrowsException <ArgumentNullException>(() => manager.CreateNewSeries(null, config));
            Assert.ThrowsException <ArgumentNullException>(() => manager.CreateNewSeries("Foo Bar", null));

            MetricSeries series = manager.CreateNewSeries("Foo Bar", config);

            Assert.IsNotNull(series);

            Assert.AreEqual(config, series.GetConfiguration());
            Assert.AreSame(config, series.GetConfiguration());

            Assert.AreEqual("Foo Bar", series.MetricId);

            Util.CompleteDefaultAggregationCycle(manager);
        }
Example #10
0
        private static MetricManager GetOrGreateFromTable(
            TelemetryConfiguration telemetryPipeline,
            ConditionalWeakTable <TelemetryConfiguration, MetricManager> metricManagers)
        {
            MetricManager createdManager = null;

            MetricManager chosenManager = metricManagers.GetValue(
                telemetryPipeline,
                (tp) =>
            {
                createdManager = new MetricManager(new ApplicationInsightsTelemetryPipeline(tp));
                return(createdManager);
            });

            // If there was a race and we did not end up returning the manager we just created, we will notify it to give up its agregation cycle thread.
            if (createdManager != null && false == Object.ReferenceEquals(createdManager, chosenManager))
            {
                Task fireAndForget = createdManager.StopDefaultAggregationCycleAsync();
            }

            return(chosenManager);
        }
 /// <summary>Initializes a metric collection.</summary>
 /// <param name="metricManager">The manager that owns the scope of this metric collection.</param>
 internal MetricsCollection(MetricManager metricManager)
 {
     Util.ValidateNotNull(metricManager, nameof(metricManager));
     this.metricManager = metricManager;
 }
        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("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);

                TestUtil.ValidateNumericAggregateValues(aggregate, ns: "ns", 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);

                TestUtil.ValidateNumericAggregateValues(aggregate, ns: "ns", 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);

                    TestUtil.ValidateNumericAggregateValues(aggregate, ns: "ns", 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.
                    TestUtil.ValidateNumericAggregateValues(aggregate, ns: "ns", 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);

                    TestUtil.ValidateNumericAggregateValues(aggregate, ns: "ns", 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);

                    TestUtil.ValidateNumericAggregateValues(aggregate, ns: "ns", 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);
                }
            }

            TestUtil.CompleteDefaultAggregationCycle(manager);
        }
        public void GetCurrentAggregateUnsafe_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("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();
                TestUtil.ValidateNumericAggregateValues(aggregate, ns: "NS", name: "Foo Bar", count: 3, sum: 0.4, max: 2, min: -2, stdDev: 1.64384373412506, 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();

                TestUtil.ValidateNumericAggregateValues(aggregate, ns: "NS", name: "Foo Bar", count: 7, sum: 1.81, max: 2, min: -2, stdDev: 1.13330652229191, 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.IsFalse(seriesConfig.RequiresPersistentAggregation);
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe();
                Assert.IsNull(aggregate);
            }

            series.TrackValue(0);

            {
                MetricAggregate aggregate = series.GetCurrentAggregateUnsafe();

                Assert.IsFalse(seriesConfig.RequiresPersistentAggregation);
                TestUtil.ValidateNumericAggregateValues(aggregate, ns: "NS", name: "Foo Bar", count: 1, sum: 0, max: 0, min: 0, 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(flushTS.Year, flushTS.Month, flushTS.Day, flushTS.Hour, flushTS.Minute, flushTS.Second, 0, flushTS.Offset),
                    aggregate.AggregationPeriodStart);
            }

            TestUtil.CompleteDefaultAggregationCycle(manager);
        }
Example #14
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);
        }
 /// <summary>
 /// Ctor facade that can be used to pass as a function pointer without a local lambda instantiation.
 /// </summary>
 /// <param name="metricManager"></param>
 /// <returns></returns>
 public static MetricsCache CreateNewInstance(MetricManager metricManager)
 {
     return(new MetricsCache(metricManager));
 }
 private MetricsCache(MetricManager metricManager)
 {
     Util.ValidateNotNull(metricManager, nameof(metricManager));
     _metricManager = metricManager;
 }