Example #1
0
        public async Task GetAnomalies(bool populateOptionalMembers)
        {
            MetricsAdvisorClient client = GetMetricsAdvisorClient();

            var options = new GetAnomaliesForDetectionConfigurationOptions(SamplingStartTime, SamplingEndTime);

            if (populateOptionalMembers)
            {
                options.Filter = new GetAnomaliesForDetectionConfigurationFilter(AnomalySeverity.Medium, AnomalySeverity.Medium);

                var groupKey1 = new DimensionKey();
                groupKey1.AddDimensionColumn("city", "Delhi");
                groupKey1.AddDimensionColumn("category", "Handmade");

                var groupKey2 = new DimensionKey();
                groupKey2.AddDimensionColumn("city", "Kolkata");

                options.Filter.SeriesGroupKeys.Add(groupKey1);
                options.Filter.SeriesGroupKeys.Add(groupKey2);
            }

            var anomalyCount = 0;

            await foreach (DataPointAnomaly anomaly in client.GetAnomaliesAsync(DetectionConfigurationId, options))
            {
                Assert.That(anomaly, Is.Not.Null);
                Assert.That(anomaly.AnomalyDetectionConfigurationId, Is.Null);
                Assert.That(anomaly.MetricId, Is.Null);
                Assert.That(anomaly.CreatedTime, Is.Null);
                Assert.That(anomaly.ModifiedTime, Is.Null);
                Assert.That(anomaly.Status, Is.Null);

                Assert.That(anomaly.Timestamp, Is.InRange(SamplingStartTime, SamplingEndTime));
                Assert.That(anomaly.Severity, Is.Not.EqualTo(default(AnomalySeverity)));
                Assert.That(anomaly.SeriesKey, Is.Not.Null);

                Dictionary <string, string> dimensionColumns = anomaly.SeriesKey.AsDictionary();

                Assert.That(dimensionColumns.Count, Is.EqualTo(2));
                Assert.That(dimensionColumns.ContainsKey("city"));
                Assert.That(dimensionColumns.ContainsKey("category"));

                string city     = dimensionColumns["city"];
                string category = dimensionColumns["category"];

                Assert.That(city, Is.Not.Null.And.Not.Empty);
                Assert.That(category, Is.Not.Null.And.Not.Empty);

                if (populateOptionalMembers)
                {
                    Assert.That(anomaly.Severity, Is.EqualTo(AnomalySeverity.Medium));
                    Assert.That((city == "Delhi" && category == "Handmade") || city == "Kolkata");
                }

                if (++anomalyCount >= MaximumSamplesCount)
                {
                    break;
                }
            }

            Assert.That(anomalyCount, Is.GreaterThan(0));
        }
        public async Task CreateAndGetDetectionConfigurationWithSeriesConditions()
        {
            // Set required parameters of the configuration to be created.

            MetricsAdvisorAdministrationClient adminClient = GetMetricsAdvisorAdministrationClient();

            string configName = Recording.GenerateAlphaNumericId("config");

            var wholeConditions = new MetricWholeSeriesDetectionCondition()
            {
                HardThresholdCondition = new (AnomalyDetectorDirection.Both, new (1, 2.0))
                {
                    UpperBound = 20.0,
                    LowerBound = 10.0
                }
            };

            var configToCreate = new AnomalyDetectionConfiguration(MetricId, configName, wholeConditions);

            // Set the series conditions and create the configuration.

            var seriesKey1 = new DimensionKey();
            var seriesKey2 = new DimensionKey();

            seriesKey1.AddDimensionColumn("city", "Delhi");
            seriesKey1.AddDimensionColumn("category", "Handmade");

            seriesKey2.AddDimensionColumn("city", "Koltaka");
            seriesKey2.AddDimensionColumn("category", "Grocery & Gourmet Food");

            var seriesConditions0 = new MetricSingleSeriesDetectionCondition(seriesKey1)
            {
                SmartDetectionCondition = new (30.0, AnomalyDetectorDirection.Both, new (3, 4.0))
            };

            var seriesConditions1 = new MetricSingleSeriesDetectionCondition(seriesKey2)
            {
                ChangeThresholdCondition = new (40.0, 12, false, AnomalyDetectorDirection.Up, new (5, 6.0))
            };

            configToCreate.SeriesDetectionConditions.Add(seriesConditions0);
            configToCreate.SeriesDetectionConditions.Add(seriesConditions1);

            await using var disposableConfig = await DisposableDetectionConfiguration.CreateDetectionConfigurationAsync(adminClient, configToCreate);

            // Get the created configuration and validate top-level members.

            AnomalyDetectionConfiguration createdConfig = await adminClient.GetDetectionConfigurationAsync(disposableConfig.Id);

            Assert.That(createdConfig.Id, Is.EqualTo(disposableConfig.Id));
            Assert.That(createdConfig.MetricId, Is.EqualTo(MetricId));
            Assert.That(createdConfig.Name, Is.EqualTo(configName));
            Assert.That(createdConfig.Description, Is.Empty);
            Assert.That(createdConfig.SeriesGroupDetectionConditions, Is.Not.Null.And.Empty);

            // Validate whole series detection conditions.

            MetricWholeSeriesDetectionCondition createdWholeConditions = createdConfig.WholeSeriesDetectionConditions;

            Assert.That(createdWholeConditions, Is.Not.Null);
            Assert.That(createdWholeConditions.CrossConditionsOperator, Is.Null);
            Assert.That(createdWholeConditions.ChangeThresholdCondition, Is.Null);
            Assert.That(createdWholeConditions.SmartDetectionCondition, Is.Null);

            ValidateHardThresholdCondition(createdWholeConditions.HardThresholdCondition, AnomalyDetectorDirection.Both, 20.0, 10.0, 1, 2.0);

            // Start series conditions validation.

            Assert.That(createdConfig.SeriesDetectionConditions, Is.Not.Null);
            Assert.That(createdConfig.SeriesDetectionConditions.Count, Is.EqualTo(2));

            // Validate first series conditions.

            var createdSeriesConditions0 = createdConfig.SeriesDetectionConditions[0];

            Assert.That(createdSeriesConditions0, Is.Not.Null);

            ValidateSeriesKey(createdSeriesConditions0.SeriesKey);

            Dictionary <string, string> dimensionColumns = createdSeriesConditions0.SeriesKey.AsDictionary();

            Assert.That(dimensionColumns["city"], Is.EqualTo("Delhi"));
            Assert.That(dimensionColumns["category"], Is.EqualTo("Handmade"));

            Assert.That(createdSeriesConditions0.CrossConditionsOperator, Is.Null);
            Assert.That(createdSeriesConditions0.HardThresholdCondition, Is.Null);
            Assert.That(createdSeriesConditions0.ChangeThresholdCondition, Is.Null);

            ValidateSmartDetectionCondition(createdSeriesConditions0.SmartDetectionCondition, 30.0, AnomalyDetectorDirection.Both, 3, 4.0);

            // Validate last series conditions.

            var createdSeriesConditions1 = createdConfig.SeriesDetectionConditions[1];

            Assert.That(createdSeriesConditions1, Is.Not.Null);

            ValidateSeriesKey(createdSeriesConditions1.SeriesKey);

            dimensionColumns = createdSeriesConditions1.SeriesKey.AsDictionary();

            Assert.That(dimensionColumns["city"], Is.EqualTo("Koltaka"));
            Assert.That(dimensionColumns["category"], Is.EqualTo("Grocery & Gourmet Food"));

            Assert.That(createdSeriesConditions1.CrossConditionsOperator, Is.Null);
            Assert.That(createdSeriesConditions1.HardThresholdCondition, Is.Null);
            Assert.That(createdSeriesConditions1.SmartDetectionCondition, Is.Null);

            ValidateChangeThresholdCondition(createdSeriesConditions1.ChangeThresholdCondition, 40.0, 12, false, AnomalyDetectorDirection.Up, 5, 6.0);
        }