예제 #1
0
        public async Task VerifyMetricForGaps(Metrics type, bool shouldSucceed)
        {
            // Arrange
            var metric = new Metric
            {
                Type   = type.AsInt(),
                Source = "the-source"
            };
            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            // Act & Assert
            if (shouldSucceed)
            {
                // It will pass metric check, will try to interact with data layer and fail
                await Assert.ThrowsAsync <NullReferenceException>(
                    async() => await discrepancyService.FindGapsAsync(metric, new TimeSpan())
                    );
            }
            else
            {
                await Assert.ThrowsAsync <ArgumentException>(
                    async() => await discrepancyService.FindGapsAsync(metric, new TimeSpan())
                    );
            }
        }
예제 #2
0
        public void PingFailureNoData()
        {
            // Arrange
            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            // Act
            var actual = discrepancyService
                         .FindPingFailuresFromDataPoints(
                new List <PingDataPoint>(),
                new PingSetting {
                MaxFailures = 1
            },
                new Metric
            {
                Type   = Metrics.Ping.AsInt(),
                Source = "the-source"
            }
                );

            // Assert
            Assert.Empty(actual);
        }
        public async Task ResolvesGapInData(bool shouldResolve)
        {
            // Arrange
            var input = new List <Discrepancy> {
                new Discrepancy {
                    DateFirstOffense = DateTime.UtcNow,
                    Type             = DiscrepancyType.GapInData,
                    MetricSource     = "the-source-1",
                    MetricType       = Metrics.CpuLoad,
                }
            };

            var metric = new Metric
            {
                Type   = Metrics.CpuLoad.AsInt(),
                Source = "the-source-1"
            };

            var context = _serviceProvider.GetRequiredService <IDataContext>();
            await context.Metrics.AddAsync(metric);

            await context.NumericDataPoints.AddRangeAsync(
                new NumericDataPoint
            {
                Metric    = metric,
                Value     = 50,
                Timestamp = DateTime.UtcNow.AddMinutes(-2)
            },
                new NumericDataPoint
            {
                Metric    = metric,
                Value     = 92,
                Timestamp = DateTime.UtcNow.AddMinutes(shouldResolve ? 1 : -1)
            }
                );

            await context.SaveChangesAsync();

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            // Act
            var actual = await discrepancyService.FindResolvedDiscrepanciesAsync(input);

            // Assert
            if (shouldResolve)
            {
                Assert.NotEmpty(actual);
                Assert.Equal(input, actual);
            }
            else
            {
                Assert.Empty(actual);
            }
        }
예제 #4
0
        public void MultipleGapsInData()
        {
            // Arrange
            var mockConfig = new Mock <IConfiguration>();

            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Gaps:MaxDifference"])
            .Returns("60");

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                mockConfig.Object
                );

            var input = new List <DateTime>()
            {
                DateTime.UtcNow - new TimeSpan(0, 0, 0),
                DateTime.UtcNow - new TimeSpan(0, 1, 0),
                DateTime.UtcNow - new TimeSpan(0, 4, 0),
                DateTime.UtcNow - new TimeSpan(0, 5, 0),
                DateTime.UtcNow - new TimeSpan(0, 7, 0)
            };

            var expected = new List <Discrepancy> {
                new Discrepancy
                {
                    DateFirstOffense = input[2],
                    Type             = DiscrepancyType.GapInData,
                    MetricType       = Metrics.CpuLoad,
                    MetricSource     = "the-source"
                },
                new Discrepancy
                {
                    DateFirstOffense = input[4],
                    Type             = DiscrepancyType.GapInData,
                    MetricType       = Metrics.CpuLoad,
                    MetricSource     = "the-source"
                }
            }
            .OrderBy(d => d.DateFirstOffense);

            // Act
            var actual = discrepancyService
                         .FindGapsInDataPoints(
                input,
                new Metric
            {
                Type   = Metrics.CpuLoad.AsInt(),
                Source = "the-source"
            }
                )
                         .OrderBy(d => d.DateFirstOffense);

            // Assert
            Assert.Equal(expected, actual);
        }
        public async Task ResolvesLowHealth(bool shouldResolve)
        {
            // Arrange
            var input = new List <Discrepancy> {
                new Discrepancy {
                    DateFirstOffense = DateTime.UtcNow,
                    Type             = DiscrepancyType.LowHealth,
                    MetricSource     = "the-source-1",
                    MetricType       = Metrics.Health,
                }
            };

            var metric = new Metric
            {
                Type   = Metrics.Health.AsInt(),
                Source = "the-source-1"
            };

            var context = _serviceProvider.GetRequiredService <IDataContext>();
            await context.Metrics.AddAsync(metric);

            await context.HealthReports.AddRangeAsync(
                DiscrepancyServiceTest.GenerateHealthReport(true, metric, DateTime.UtcNow.AddMinutes(-1)),
                DiscrepancyServiceTest.GenerateHealthReport(false, metric, DateTime.UtcNow.AddMinutes(1)),
                DiscrepancyServiceTest.GenerateHealthReport(false, metric, DateTime.UtcNow.AddMinutes(2)),
                DiscrepancyServiceTest.GenerateHealthReport(shouldResolve, metric, DateTime.UtcNow.AddMinutes(3))
                );

            await context.SaveChangesAsync();

            var config = new Mock <IConfiguration>();

            config
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Health:Threshold"])
            .Returns(99.ToString());

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                new Mock <INotificationService>().Object,
                config.Object
                );

            // Act
            var actual = await discrepancyService.FindResolvedDiscrepanciesAsync(input);

            // Assert
            if (shouldResolve)
            {
                Assert.NotEmpty(actual);
                Assert.Equal(input, actual);
            }
            else
            {
                Assert.Empty(actual);
            }
        }
예제 #6
0
        public void SingleLowHealthInData()
        {
            // Arrange
            var mockConfig = new Mock <IConfiguration>();

            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Health:Threshold"])
            .Returns(90.ToString());
            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Health:MaxFailures"])
            .Returns(2.ToString());                     // 3 is discrepancy

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                mockConfig.Object
                );

            var input = new List <HealthReport>()
            {
                ConfigureHealthReport(95, DateTime.UtcNow),                                     // good
                ConfigureHealthReport(89, DateTime.UtcNow.AddMinutes(-1)),                      // bad
                ConfigureHealthReport(70, DateTime.UtcNow.AddMinutes(-2)),                      // bad
                ConfigureHealthReport(75, DateTime.UtcNow.AddMinutes(-3)),                      // bad
                ConfigureHealthReport(100, DateTime.UtcNow.AddMinutes(-4)),                     // good
                ConfigureHealthReport(56, DateTime.UtcNow.AddMinutes(-5)),                      // bad
                ConfigureHealthReport(69, DateTime.UtcNow.AddMinutes(-6)),                      // bad
                ConfigureHealthReport(99, DateTime.UtcNow.AddMinutes(-7)),                      // good
            };

            var expected = new List <Discrepancy> {
                new Discrepancy
                {
                    DateFirstOffense = input[3].Timestamp,
                    Type             = DiscrepancyType.LowHealth,
                    MetricType       = Metrics.Health,
                    MetricSource     = "the-source"
                }
            };

            // Act
            var actual = discrepancyService
                         .FindLowHealthInDataPoints(
                input,
                new Metric
            {
                Type   = Metrics.Health.AsInt(),
                Source = "the-source"
            }
                );

            // Assert
            Assert.Equal(expected, actual);
        }
예제 #7
0
        public void NoPingFailures()
        {
            // Arrange
            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            var input = new List <PingDataPoint>()
            {
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.OK.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 0, 0)
                },
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.OK.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 1, 0)
                },
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.ServiceUnavailable.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 2, 0)
                },
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.OK.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 3, 0)
                },
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.OK.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 4, 0)
                },
            };

            // Act
            var actual = discrepancyService
                         .FindPingFailuresFromDataPoints(
                input,
                new PingSetting {
                MaxFailures = 1
            },
                new Metric
            {
                Type   = Metrics.Ping.AsInt(),
                Source = "the-source"
            }
                );

            // Assert
            Assert.Empty(actual);
        }
예제 #8
0
        public async Task RecordsDiscrepanciesEmptyList()
        {
            // Arrange
            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            // Act
            var actual = await discrepancyService.RecordDiscrepanciesAsync(new List <Discrepancy>());

            // Assert
            Assert.Empty(actual);
        }
예제 #9
0
        public async Task ResolvesDiscrepanciesAlreadyResolved()
        {
            // Arrange
            var logger  = new Mock <ILogger <DiscrepancyService> >();
            var context = _serviceProvider.GetRequiredService <IDataContext>();

            var discrepancyService = new DiscrepancyService(
                logger.Object,
                context,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            var input = new List <Discrepancy> {
                new Discrepancy {
                    DateFirstOffense = DateTime.UtcNow,
                    Type             = DiscrepancyType.GapInData,
                    MetricSource     = "the-source-1",
                    MetricType       = Metrics.CpuLoad,
                    Resolved         = true
                },
                new Discrepancy {
                    DateFirstOffense = DateTime.UtcNow,
                    Type             = DiscrepancyType.GapInData,
                    MetricSource     = "the-source-2",
                    MetricType       = Metrics.CpuLoad,
                    Resolved         = true
                }
            };

            // Act
            var actual = await discrepancyService.ResolveDiscrepanciesAsync(input);

            // Assert
            Assert.Equal(input, actual);
            logger
            .Verify(
                log => log.Log(
                    LogLevel.Warning,
                    It.IsAny <EventId>(),
                    It.IsAny <FormattedLogValues>(),
                    It.IsAny <Exception>(),
                    It.IsAny <Func <object, Exception, string> >()
                    ),
                Times.Exactly(2)
                );
        }
예제 #10
0
        public void PermanentLowHealthInData()
        {
            // Arrange
            var mockConfig = new Mock <IConfiguration>();

            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Health:Threshold"])
            .Returns(90.ToString());
            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Health:MaxFailures"])
            .Returns(2.ToString());                     // 3 is discrepancy

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                mockConfig.Object
                );

            var input = new List <HealthReport>()
            {
                ConfigureHealthReport(80, DateTime.UtcNow),                                     // bad
                ConfigureHealthReport(89, DateTime.UtcNow.AddMinutes(-1)),                      // bad
                ConfigureHealthReport(70, DateTime.UtcNow.AddMinutes(-2)),                      // bad
                ConfigureHealthReport(60, DateTime.UtcNow.AddMinutes(-3)),                      // bad
                ConfigureHealthReport(85, DateTime.UtcNow.AddMinutes(-4)),                      // bad
                ConfigureHealthReport(56, DateTime.UtcNow.AddMinutes(-5)),                      // bad
                ConfigureHealthReport(69, DateTime.UtcNow.AddMinutes(-6)),                      // bad
                ConfigureHealthReport(9, DateTime.UtcNow.AddMinutes(-7)),                       // bad
            };

            // Act
            var actual = discrepancyService
                         .FindLowHealthInDataPoints(
                input,
                new Metric
            {
                Type   = Metrics.Health.AsInt(),
                Source = "the-source"
            }
                );

            // Assert
            Assert.Empty(actual);
        }
예제 #11
0
        public async Task ResolvesDiscrepancies()
        {
            // Arrange
            var input = new List <Discrepancy> {
                new Discrepancy {
                    DateFirstOffense = DateTime.UtcNow.AddMinutes(-2),
                    Type             = DiscrepancyType.GapInData,
                    MetricSource     = "the-source-1",
                    MetricType       = Metrics.CpuLoad,
                }
            };

            var notifications = new Mock <INotificationService>();
            var context       = _serviceProvider.GetRequiredService <IDataContext>();
            await context.Discrepancies.AddRangeAsync(input);

            await context.SaveChangesAsync();

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                notifications.Object,
                new Mock <IConfiguration>().Object
                );

            // Act
            var actual = await discrepancyService.ResolveDiscrepanciesAsync(input);

            // Assert
            Assert.True(actual.First().Resolved);
            Assert.InRange(actual.First().DateResolved, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1));
            Assert.True(await context.Discrepancies.AnyAsync(d => d.Resolved));

            notifications
            .Verify(
                notif => notif
                .ScheduleNotificationAsync(
                    It.Is <string>(msg => msg.Contains("resolve", StringComparison.OrdinalIgnoreCase)),
                    NotificationSeverity.High
                    )
                );
        }
예제 #12
0
        public async Task UsesCorrectTimeZone()
        {
            // Arrange
            var config = new Mock <IConfiguration>();

            config
            .SetupGet(conf => conf["ServiceManager:NotificationService:TimeZone"])
            .Returns("Asia/Kabul");

            var date = DateTime.SpecifyKind(new DateTime(2017, 07, 14, 18, 25, 43), DateTimeKind.Utc);

            var context           = _serviceProvider.GetRequiredService <IDataContext>();
            var mockNotifications = new Mock <INotificationService>();

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                mockNotifications.Object,
                config.Object
                );

            var input = new List <Discrepancy> {
                new Discrepancy {
                    DateFirstOffense = date,
                    Type             = DiscrepancyType.GapInData,
                    MetricSource     = "the-source",
                    MetricType       = Metrics.CpuLoad
                }
            };

            // Act
            await discrepancyService.RecordDiscrepanciesAsync(input);

            // Assert
            mockNotifications
            .Verify(
                n => n.ScheduleNotificationAsync(
                    It.Is <string>(s => s.Contains(date.ToStringUsingTimeZone("Asia/Kabul"))),
                    NotificationSeverity.High
                    )
                );
        }
예제 #13
0
        public void NoGapsInData()
        {
            // Arrange
            var mockConfig = new Mock <IConfiguration>();

            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Gaps:MaxDifference"])
            .Returns("60");

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                mockConfig.Object
                );

            var input = new List <DateTime>()
            {
                DateTime.UtcNow - new TimeSpan(0, 0, 0),
                DateTime.UtcNow - new TimeSpan(0, 1, 0),
                DateTime.UtcNow - new TimeSpan(0, 2, 0),
                DateTime.UtcNow - new TimeSpan(0, 3, 0),
                DateTime.UtcNow - new TimeSpan(0, 4, 0),
                DateTime.UtcNow - new TimeSpan(0, 5, 0)
            };

            // Act
            var actual = discrepancyService
                         .FindGapsInDataPoints(
                input,
                new Metric
            {
                Type   = Metrics.CpuLoad.AsInt(),
                Source = "the-source"
            }
                );

            // Assert
            Assert.Empty(actual);
        }
예제 #14
0
        public void GapNoData()
        {
            // Arrange
            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            // Act
            var actual = discrepancyService
                         .FindGapsInDataPoints(
                new List <DateTime>(),
                new Metric
            {
                Type   = Metrics.CpuLoad.AsInt(),
                Source = "the-source"
            }
                );

            // Assert
            Assert.Empty(actual);
        }
예제 #15
0
        public void SinglePingFailure()
        {
            // Arrange
            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            var input = new List <PingDataPoint>()
            {
                new PingDataPoint {
                    Success   = true,
                    Timestamp = DateTime.UtcNow - new TimeSpan(0, 0, 0)
                },
                new PingDataPoint {
                    Success   = false,
                    Timestamp = DateTime.UtcNow - new TimeSpan(0, 1, 0)
                },
                new PingDataPoint {
                    Success   = false,
                    Timestamp = DateTime.UtcNow - new TimeSpan(0, 2, 0)
                },
                new PingDataPoint {
                    Success   = true,
                    Timestamp = DateTime.UtcNow - new TimeSpan(0, 3, 0)
                },
                new PingDataPoint {
                    Success   = true,
                    Timestamp = DateTime.UtcNow - new TimeSpan(0, 4, 0)
                },
            };

            var expected = new List <Discrepancy> {
                new Discrepancy
                {
                    DateFirstOffense = input[2].Timestamp,
                    Type             = DiscrepancyType.PingFailedNTimes,
                    MetricType       = Metrics.Ping,
                    MetricSource     = "the-source"
                }
            };

            // Act
            var actual = discrepancyService
                         .FindPingFailuresFromDataPoints(
                input,
                new PingSetting {
                MaxFailures = 1
            },
                new Metric
            {
                Type   = Metrics.Ping.AsInt(),
                Source = "the-source"
            }
                );

            // Assert
            Assert.Equal(expected, actual);
        }
예제 #16
0
        public async Task FindsLowHealth()
        {
            // Arrange
            var mockConfig = new Mock <IConfiguration>();

            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Health:Threshold"])
            .Returns(99.ToString());
            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:LoHealthad:MaxFailures"])
            .Returns(1.ToString());                     // 3 is discrepancy

            var context = _serviceProvider.GetRequiredService <IDataContext>();
            var metric  = await context.Metrics.AddAsync(
                new Metric
            {
                Source = "the-source",
                Type   = Metrics.Health.AsInt()
            }
                );

            var dataPoints = new List <HealthReport>()
            {
                new HealthReport {                 // good
                    Data = new List <HealthReportDataPoint> {
                        new HealthReportDataPoint {
                            Label = AutoLabels.Normal.ToString()
                        },
                        new HealthReportDataPoint {
                            Label = AutoLabels.Normal.ToString()
                        },
                    },
                    Timestamp = DateTime.UtcNow,
                    Metric    = metric.Entity
                },
                new HealthReport {
                    Data = new List <HealthReportDataPoint> {                    // bad
                        new HealthReportDataPoint {
                            Label = AutoLabels.Normal.ToString()
                        },
                        new HealthReportDataPoint {
                            Label = AutoLabels.Critical.ToString()
                        },
                    },
                    Timestamp = DateTime.UtcNow.AddMinutes(-1),
                    Metric    = metric.Entity
                },
                new HealthReport {
                    Data = new List <HealthReportDataPoint> {                    // bad
                        new HealthReportDataPoint {
                            Label = AutoLabels.Normal.ToString()
                        },
                        new HealthReportDataPoint {
                            Label = AutoLabels.Warning.ToString()
                        },
                    },
                    Timestamp = DateTime.UtcNow.AddMinutes(-2),
                    Metric    = metric.Entity
                },
                new HealthReport {                 // good
                    Data = new List <HealthReportDataPoint> {
                        new HealthReportDataPoint {
                            Label = AutoLabels.Normal.ToString()
                        },
                        new HealthReportDataPoint {
                            Label = AutoLabels.Normal.ToString()
                        },
                    },
                    Timestamp = DateTime.UtcNow.AddMinutes(-3),
                    Metric    = metric.Entity
                }
            };

            await context.HealthReports.AddRangeAsync(dataPoints);

            await context.SaveChangesAsync();

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                new Mock <INotificationService>().Object,
                mockConfig.Object
                );

            var expected = new List <Discrepancy> {
                new Discrepancy
                {
                    DateFirstOffense = dataPoints[2].Timestamp,
                    Type             = DiscrepancyType.LowHealth,
                    MetricType       = Metrics.Health,
                    MetricSource     = "the-source"
                }
            };

            // Act
            var actual = await discrepancyService
                         .FindLowHealthsAsync(
                metric.Entity,
                new TimeSpan(0, 30, 0)
                );

            // Assert
            Assert.Equal(expected, actual);
        }
예제 #17
0
        public void MultiplePingFailures()
        {
            // Arrange
            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            var input = new List <PingDataPoint>()
            {
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.OK.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 0, 0)
                },
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.ServiceUnavailable.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 1, 0)
                },
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.ServiceUnavailable.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 2, 0)
                },
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.OK.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 3, 0)
                },
                new PingDataPoint {
                    HttpStatusCode = HttpStatusCode.ServiceUnavailable.AsInt(),
                    Timestamp      = DateTime.UtcNow - new TimeSpan(0, 4, 0)
                },
            };

            var expected = new List <Discrepancy> {
                new Discrepancy
                {
                    DateFirstOffense = input[4].Timestamp,
                    Type             = DiscrepancyType.PingFailedNTimes,
                    MetricType       = Metrics.Ping,
                    MetricSource     = "the-source"
                },
                new Discrepancy
                {
                    DateFirstOffense = input[2].Timestamp,
                    Type             = DiscrepancyType.PingFailedNTimes,
                    MetricType       = Metrics.Ping,
                    MetricSource     = "the-source"
                }
            }
            .OrderBy(d => d.DateFirstOffense);;

            // Act
            var actual = discrepancyService
                         .FindPingFailuresFromDataPoints(
                input,
                new PingSetting {
                MaxFailures = 0
            },
                new Metric
            {
                Type   = Metrics.Ping.AsInt(),
                Source = "the-source"
            }
                )
                         .OrderBy(d => d.DateFirstOffense);;

            // Assert
            Assert.Equal(expected, actual);
        }
예제 #18
0
        public async Task FindsGap()
        {
            // Arrange
            var mockConfig = new Mock <IConfiguration>();

            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Gaps:MaxDifference"])
            .Returns(60.ToString());
            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:DataTimeframe"])
            .Returns(1800.ToString());

            var context = _serviceProvider.GetRequiredService <IDataContext>();
            var metric  = await context.Metrics.AddAsync(
                new Metric
            {
                Source = "the-source",
                Type   = Metrics.CpuLoad.AsInt()
            }
                );

            var dataPoints = new List <NumericDataPoint> {
                new NumericDataPoint {
                    Timestamp = DateTime.UtcNow.AddMinutes(0),
                    Metric    = metric.Entity
                },
                new NumericDataPoint {
                    Timestamp = DateTime.UtcNow.AddMinutes(-1),
                    Metric    = metric.Entity
                },
                new NumericDataPoint {
                    Timestamp = DateTime.UtcNow.AddMinutes(-2),
                    Metric    = metric.Entity
                },
                new NumericDataPoint {
                    Timestamp = DateTime.UtcNow.AddMinutes(-4),
                    Metric    = metric.Entity
                },
                new NumericDataPoint {
                    Timestamp = DateTime.UtcNow.AddMinutes(-5),
                    Metric    = metric.Entity
                }
            };
            await context.NumericDataPoints.AddRangeAsync(dataPoints);

            await context.SaveChangesAsync();

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                new Mock <INotificationService>().Object,
                mockConfig.Object
                );

            var expected = new List <Discrepancy> {
                new Discrepancy
                {
                    DateFirstOffense = dataPoints[3].Timestamp,
                    Type             = DiscrepancyType.GapInData,
                    MetricType       = Metrics.CpuLoad,
                    MetricSource     = "the-source"
                }
            };

            // Act
            var actual = await discrepancyService
                         .FindGapsAsync(
                metric.Entity,
                new TimeSpan(0, 30, 0)
                );

            // Assert
            Assert.Equal(expected, actual);
        }
        public async Task ResolvesPingFailure(bool shouldResolve)
        {
            // Arrange
            var input = new List <Discrepancy> {
                new Discrepancy {
                    DateFirstOffense = DateTime.UtcNow,
                    Type             = DiscrepancyType.PingFailedNTimes,
                    MetricSource     = "lolchik.com",
                    MetricType       = Metrics.Ping,
                }
            };

            var metric = new Metric
            {
                Type   = Metrics.Ping.AsInt(),
                Source = "lolchik.com"
            };

            var context = _serviceProvider.GetRequiredService <IDataContext>();
            await context.Metrics.AddAsync(metric);

            await context.PingDataPoints.AddRangeAsync(
                new PingDataPoint
            {
                Metric    = metric,
                Success   = true,
                Timestamp = DateTime.UtcNow.AddMinutes(-1)
            },
                new PingDataPoint
            {
                Metric    = metric,
                Success   = false,
                Timestamp = DateTime.UtcNow.AddMinutes(1)
            },
                new PingDataPoint
            {
                Metric    = metric,
                Success   = false,
                Timestamp = DateTime.UtcNow.AddMinutes(2)
            },
                new PingDataPoint
            {
                Metric    = metric,
                Success   = shouldResolve,
                Timestamp = DateTime.UtcNow.AddMinutes(3)
            }
                );

            await context.SaveChangesAsync();

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            // Act
            var actual = await discrepancyService.FindResolvedDiscrepanciesAsync(input);

            // Assert
            if (shouldResolve)
            {
                Assert.NotEmpty(actual);
                Assert.Equal(input, actual);
            }
            else
            {
                Assert.Empty(actual);
            }
        }
        public async Task ResolvesHighLoad(bool shouldResolve)
        {
            // Arrange
            var input = new List <Discrepancy> {
                new Discrepancy {
                    DateFirstOffense = DateTime.UtcNow,
                    Type             = DiscrepancyType.HighLoad,
                    MetricSource     = "the-source-1",
                    MetricType       = Metrics.CpuLoad,
                }
            };

            var metric = new Metric
            {
                Type   = Metrics.CpuLoad.AsInt(),
                Source = "the-source-1"
            };

            var context = _serviceProvider.GetRequiredService <IDataContext>();
            await context.Metrics.AddAsync(metric);

            await context.NumericDataPoints.AddRangeAsync(
                new NumericDataPoint
            {
                Metric    = metric,
                Value     = 50,
                Timestamp = DateTime.UtcNow.AddMinutes(-1)
            },
                new NumericDataPoint
            {
                Metric    = metric,
                Value     = 95,
                Timestamp = DateTime.UtcNow.AddMinutes(1)
            },
                new NumericDataPoint
            {
                Metric    = metric,
                Value     = 91,
                Timestamp = DateTime.UtcNow.AddMinutes(2)
            },
                new NumericDataPoint
            {
                Metric    = metric,
                Value     = shouldResolve ? 85 : 92,
                Timestamp = DateTime.UtcNow.AddMinutes(3)
            }
                );

            await context.SaveChangesAsync();

            var config = new Mock <IConfiguration>();

            config
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Load:Threshold"])
            .Returns(90.ToString());

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                new Mock <INotificationService>().Object,
                config.Object
                );

            // Act
            var actual = await discrepancyService.FindResolvedDiscrepanciesAsync(input);

            // Assert
            if (shouldResolve)
            {
                Assert.NotEmpty(actual);
                Assert.Equal(input, actual);
            }
            else
            {
                Assert.Empty(actual);
            }
        }
예제 #21
0
        public async Task FindsPingFailure()
        {
            // Arrange
            var mockConfig = new Mock <IConfiguration>();

            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:DataTimeframe"])
            .Returns(1800.ToString());

            var context = _serviceProvider.GetRequiredService <IDataContext>();
            var metric  = await context.Metrics.AddAsync(
                new Metric
            {
                Source = "the-source",
                Type   = Metrics.Ping.AsInt()
            }
                );

            var dataPoints = new List <PingDataPoint> {
                new PingDataPoint {
                    Timestamp      = DateTime.UtcNow.AddMinutes(0),
                    Metric         = metric.Entity,
                    HttpStatusCode = HttpStatusCode.OK.AsInt()
                },
                new PingDataPoint {
                    Timestamp      = DateTime.UtcNow.AddMinutes(-1),
                    Metric         = metric.Entity,
                    HttpStatusCode = HttpStatusCode.ServiceUnavailable.AsInt()
                },
                new PingDataPoint {
                    Timestamp      = DateTime.UtcNow.AddMinutes(-2),
                    Metric         = metric.Entity,
                    HttpStatusCode = HttpStatusCode.ServiceUnavailable.AsInt()
                },
                new PingDataPoint {
                    Timestamp      = DateTime.UtcNow.AddMinutes(-3),
                    Metric         = metric.Entity,
                    HttpStatusCode = HttpStatusCode.OK.AsInt()
                },
                new PingDataPoint {
                    Timestamp      = DateTime.UtcNow.AddMinutes(-4),
                    Metric         = metric.Entity,
                    HttpStatusCode = HttpStatusCode.OK.AsInt()
                }
            };
            await context.PingDataPoints.AddRangeAsync(dataPoints);

            await context.PingSettings.AddAsync(
                new PingSetting
            {
                ServerUrl   = "the-source",
                MaxFailures = 1
            }
                );

            await context.SaveChangesAsync();

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                new Mock <INotificationService>().Object,
                mockConfig.Object
                );

            var expected = new List <Discrepancy> {
                new Discrepancy
                {
                    DateFirstOffense = dataPoints[2].Timestamp,
                    Type             = DiscrepancyType.PingFailedNTimes,
                    MetricType       = Metrics.Ping,
                    MetricSource     = "the-source"
                }
            };

            // Act
            var actual = await discrepancyService
                         .FindPingFailuresAsync(
                metric.Entity,
                new TimeSpan(0, 30, 0)
                );

            // Assert
            Assert.Equal(expected, actual);
        }
예제 #22
0
        public void PingFailuresDataStartsWithFailure()
        {
            // Arrange
            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                new Mock <IConfiguration>().Object
                );

            var input = new List <PingDataPoint>()
            {
                new PingDataPoint {
                    Success   = true,
                    Timestamp = DateTime.UtcNow.AddMinutes(0)
                },
                new PingDataPoint {
                    Success   = false,
                    Timestamp = DateTime.UtcNow.AddMinutes(-1)
                },
                new PingDataPoint {
                    Success   = false,
                    Timestamp = DateTime.UtcNow.AddMinutes(-2)
                },
                new PingDataPoint {
                    Success   = true,
                    Timestamp = DateTime.UtcNow.AddMinutes(-3)
                },
                new PingDataPoint {
                    Success   = false,
                    Timestamp = DateTime.UtcNow.AddMinutes(-4)
                },
                new PingDataPoint {
                    Success   = false,
                    Timestamp = DateTime.UtcNow.AddMinutes(-5)
                }
            };

            var expected = new List <Discrepancy> {
                new Discrepancy
                {
                    DateFirstOffense = input[2].Timestamp,
                    Type             = DiscrepancyType.PingFailedNTimes,
                    MetricType       = Metrics.Ping,
                    MetricSource     = "the-source"
                }
            }
            .OrderBy(d => d.DateFirstOffense);;

            // Act
            var actual = discrepancyService
                         .FindPingFailuresFromDataPoints(
                input,
                new PingSetting {
                MaxFailures = 0
            },
                new Metric
            {
                Type   = Metrics.Ping.AsInt(),
                Source = "the-source"
            }
                )
                         .OrderBy(d => d.DateFirstOffense);;

            // Assert
            Assert.Equal(expected, actual);
        }
예제 #23
0
        public async Task RecordsDiscrepancies()
        {
            // Arrange
            var twoDaysAgo = DateTime.UtcNow.AddDays(-2);
            var hourAgo    = DateTime.UtcNow.AddHours(-1);
            var now        = DateTime.UtcNow;

            var context = _serviceProvider.GetRequiredService <IDataContext>();
            await context.Discrepancies.AddRangeAsync(
                new List <Discrepancy> {
                new Discrepancy {
                    DateFirstOffense = now,
                    Type             = DiscrepancyType.GapInData,
                    MetricSource     = "the-source",
                    MetricType       = Metrics.CpuLoad
                },
                new Discrepancy {
                    DateFirstOffense = hourAgo,
                    Type             = DiscrepancyType.PingFailedNTimes,
                    MetricSource     = "the-source",
                    MetricType       = Metrics.Ping
                },
                new Discrepancy {
                    DateFirstOffense = twoDaysAgo,
                    Type             = DiscrepancyType.GapInData,
                    MetricSource     = "the-source",
                    MetricType       = Metrics.CpuLoad
                }
            }
                );

            await context.SaveChangesAsync();

            var mockNotifications = new Mock <INotificationService>();

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                context,
                mockNotifications.Object,
                new Mock <IConfiguration>().Object
                );

            var input = new List <Discrepancy> {
                new Discrepancy {                 // already exists
                    DateFirstOffense = now,
                    Type             = DiscrepancyType.GapInData,
                    MetricSource     = "the-source",
                    MetricType       = Metrics.CpuLoad
                },
                new Discrepancy {                 // new
                    DateFirstOffense = hourAgo,
                    Type             = DiscrepancyType.PingFailedNTimes,
                    MetricSource     = "the-other-source",
                    MetricType       = Metrics.Ping
                },
                new Discrepancy {                 // new
                    DateFirstOffense = twoDaysAgo.AddHours(1),
                    Type             = DiscrepancyType.GapInData,
                    MetricSource     = "the-source",
                    MetricType       = Metrics.CpuLoad
                }
            };

            var expected = new List <Discrepancy> {
                input[1],
                input[2]
            };

            // Act
            var actual = await discrepancyService.RecordDiscrepanciesAsync(input);

            // Assert
            Assert.Equal(
                expected.OrderBy(d => d.DateFirstOffense),
                actual.OrderBy(d => d.DateFirstOffense)
                );
            mockNotifications
            .Verify(
                n => n.ScheduleNotificationAsync(
                    It.IsAny <string>(),
                    NotificationSeverity.High
                    ),
                Times.Exactly(expected.Count)
                );
            Assert.Equal(5, context.Discrepancies.Count());
        }
예제 #24
0
        public void MultipleHighLoadInData()
        {
            // Arrange
            var mockConfig = new Mock <IConfiguration>();

            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Load:Threshold"])
            .Returns(90.ToString());
            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Load:MaxFailures"])
            .Returns(2.ToString());                     // 3 is discrepancy

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                mockConfig.Object
                );

            var input = new List <NumericDataPoint>()
            {
                new NumericDataPoint {                 // Good
                    Timestamp = DateTime.UtcNow.AddMinutes(0),
                    Value     = 68
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-1),
                    Value     = 91
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-2),
                    Value     = 99
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-3),
                    Value     = 95
                },
                new NumericDataPoint {                 // Good
                    Timestamp = DateTime.UtcNow.AddMinutes(-4),
                    Value     = 68
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-5),
                    Value     = 99
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-6),
                    Value     = 98
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-7),
                    Value     = 92
                },
                new NumericDataPoint {                 // Good
                    Timestamp = DateTime.UtcNow.AddMinutes(-8),
                    Value     = 68
                }
            };

            var expected = new List <Discrepancy> {
                new Discrepancy
                {
                    DateFirstOffense = input[3].Timestamp,
                    Type             = DiscrepancyType.HighLoad,
                    MetricType       = Metrics.CpuLoad,
                    MetricSource     = "the-source"
                },
                new Discrepancy
                {
                    DateFirstOffense = input[7].Timestamp,
                    Type             = DiscrepancyType.HighLoad,
                    MetricType       = Metrics.CpuLoad,
                    MetricSource     = "the-source"
                }
            };

            // Act
            var actual = discrepancyService
                         .FindHighLoadInDataPoints(
                input,
                new Metric
            {
                Type   = Metrics.CpuLoad.AsInt(),
                Source = "the-source"
            }
                );

            // Assert
            Assert.Equal(expected, actual);
        }
예제 #25
0
        public void PermanentHighLoadInData()
        {
            // Arrange
            var mockConfig = new Mock <IConfiguration>();

            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Load:Threshold"])
            .Returns(90.ToString());
            mockConfig
            .SetupGet(conf => conf["ServiceManager:DiscrepancyService:Load:MaxFailures"])
            .Returns(3.ToString());                     // 4 is discrepancy

            var discrepancyService = new DiscrepancyService(
                new Mock <ILogger <DiscrepancyService> >().Object,
                new Mock <IDataContext>().Object,
                new Mock <INotificationService>().Object,
                mockConfig.Object
                );

            var input = new List <NumericDataPoint>()
            {
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(0),
                    Value     = 93
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-1),
                    Value     = 91
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-2),
                    Value     = 99
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-3),
                    Value     = 95
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-4),
                    Value     = 98
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-5),
                    Value     = 99
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-6),
                    Value     = 98
                },
                new NumericDataPoint {                 // Bad
                    Timestamp = DateTime.UtcNow.AddMinutes(-7),
                    Value     = 90
                }
            };

            // Act
            var actual = discrepancyService
                         .FindHighLoadInDataPoints(
                input,
                new Metric
            {
                Type   = Metrics.CpuLoad.AsInt(),
                Source = "the-source"
            }
                );

            // Assert
            Assert.Empty(actual);
        }