From 80231c8c67034c85f00dff9acd7880b580647b06 Mon Sep 17 00:00:00 2001 From: Kevin BEAUGRAND <9513635+kbeaugrand@users.noreply.github.com> Date: Sun, 11 Sep 2022 12:46:12 +0200 Subject: [PATCH] Fix #1200 - Add Metrics services to Quartz Jobs (#1203) --- .../ConcentratorMetricExporterServiceTests.cs | 12 +--- .../ConcentratorMetricLoaderServiceTests.cs | 29 ++------- .../DeviceMetricExporterServiceTests.cs | 12 +--- .../DeviceMetricLoaderServiceTests.cs | 29 ++------- .../EdgeDeviceMetricExporterServiceTests.cs | 12 +--- .../EdgeDeviceMetricLoaderServiceTests.cs | 32 ++-------- .../Extensions/QuartzConfiguratorExtension.cs | 32 ++++++++++ .../ConcentratorMetricExporterService.cs | 28 ++++----- .../ConcentratorMetricLoaderService.cs | 49 ++++----------- .../Services/DeviceMetricExporterService.cs | 27 ++++----- .../Services/DeviceMetricLoaderService.cs | 50 ++++------------ .../EdgeDeviceMetricExporterService.cs | 29 ++++----- .../Services/EdgeDeviceMetricLoaderService.cs | 60 ++++++------------- src/AzureIoTHub.Portal/Server/Startup.cs | 16 ++--- 14 files changed, 130 insertions(+), 287 deletions(-) create mode 100644 src/AzureIoTHub.Portal/Server/Extensions/QuartzConfiguratorExtension.cs diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/ConcentratorMetricExporterServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/ConcentratorMetricExporterServiceTests.cs index e5e36a00c..f273c4ec3 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/ConcentratorMetricExporterServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/ConcentratorMetricExporterServiceTests.cs @@ -4,8 +4,6 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services { using System; - using System.Threading; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Shared.Constants; using AzureIoTHub.Portal.Server.Services; using AzureIoTHub.Portal.Shared.Models.v1._0; @@ -23,7 +21,6 @@ public class ConcentratorMetricExporterServiceTests : IDisposable private PortalMetric portalMetric; private Mock> mockLogger; - private Mock mockConfigHandler; private readonly Counter concentratorCounter = Metrics.CreateCounter(MetricName.ConcentratorCount, "Concentrators count"); private readonly Counter connectedConcentratorCounter = Metrics.CreateCounter(MetricName.ConnectedConcentratorCount, "Connected concentrators count"); @@ -34,12 +31,11 @@ public void SetUp() this.mockRepository = new MockRepository(MockBehavior.Strict); this.mockLogger = this.mockRepository.Create>(); - this.mockConfigHandler = this.mockRepository.Create(); this.portalMetric = new PortalMetric(); this.concentratorMetricExporterService = - new ConcentratorMetricExporterService(this.mockLogger.Object, this.mockConfigHandler.Object, this.portalMetric); + new ConcentratorMetricExporterService(this.mockLogger.Object, this.portalMetric); } [Test] @@ -47,16 +43,12 @@ public void ConcentratorMetricExporterServiceShouldExportConcentratorCountAndCon { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricExporterRefreshIntervalInSeconds).Returns(1); this.portalMetric.ConcentratorCount = 15; this.portalMetric.ConnectedConcentratorCount = 8; - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.concentratorMetricExporterService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.concentratorMetricExporterService.Execute(null); // Assert _ = this.concentratorCounter.Value.Should().Be(this.portalMetric.ConcentratorCount); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/ConcentratorMetricLoaderServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/ConcentratorMetricLoaderServiceTests.cs index 5508d5df7..a71f90dbc 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/ConcentratorMetricLoaderServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/ConcentratorMetricLoaderServiceTests.cs @@ -4,13 +4,10 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services { using System; - using System.Threading; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Exceptions; using AzureIoTHub.Portal.Server.Services; using AzureIoTHub.Portal.Shared.Models.v1._0; using FluentAssertions; - using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; @@ -23,7 +20,6 @@ public class ConcentratorMetricLoaderServiceTests : IDisposable private PortalMetric portalMetric; private Mock> mockLogger; - private Mock mockConfigHandler; private Mock mockDeviceService; [SetUp] @@ -32,17 +28,12 @@ public void SetUp() this.mockRepository = new MockRepository(MockBehavior.Strict); this.mockLogger = this.mockRepository.Create>(); - this.mockConfigHandler = this.mockRepository.Create(); this.mockDeviceService = this.mockRepository.Create(); this.portalMetric = new PortalMetric(); - var services = new ServiceCollection(); - - _ = services.AddTransient(_ => this.mockDeviceService.Object); - this.concentratorMetricLoaderService = - new ConcentratorMetricLoaderService(this.mockLogger.Object, this.mockConfigHandler.Object, this.portalMetric, services.BuildServiceProvider()); + new ConcentratorMetricLoaderService(this.mockLogger.Object, this.portalMetric, this.mockDeviceService.Object); } [Test] @@ -50,16 +41,12 @@ public void ConcentratorMetricLoaderServiceShouldLoadConcentratorCountAndConnect { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetConcentratorsCount()).ReturnsAsync(10); _ = this.mockDeviceService.Setup(service => service.GetConnectedConcentratorsCount()).ReturnsAsync(3); - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.concentratorMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.concentratorMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.ConcentratorCount.Should().Be(10); @@ -72,16 +59,12 @@ public void ConcentratorMetricLoaderServiceShouldHandleInternalServerErrorExcept { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetConcentratorsCount()).ThrowsAsync(new InternalServerErrorException("test")); _ = this.mockDeviceService.Setup(service => service.GetConnectedConcentratorsCount()).ReturnsAsync(3); - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.concentratorMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.concentratorMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.ConcentratorCount.Should().Be(0); @@ -95,16 +78,12 @@ public void ConcentratorMetricLoaderServiceShouldHandleInternalServerErrorExcept { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetConcentratorsCount()).ReturnsAsync(10); _ = this.mockDeviceService.Setup(service => service.GetConnectedConcentratorsCount()).ThrowsAsync(new InternalServerErrorException("test")); - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.concentratorMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.concentratorMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.ConcentratorCount.Should().Be(10); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceMetricExporterServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceMetricExporterServiceTests.cs index 9572dc55d..70edbb899 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceMetricExporterServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceMetricExporterServiceTests.cs @@ -4,8 +4,6 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services { using System; - using System.Threading; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Shared.Constants; using AzureIoTHub.Portal.Server.Services; using AzureIoTHub.Portal.Shared.Models.v1._0; @@ -23,7 +21,6 @@ public class DeviceMetricExporterServiceTests : IDisposable private PortalMetric portalMetric; private Mock> mockLogger; - private Mock mockConfigHandler; private readonly Counter deviceCounter = Metrics.CreateCounter(MetricName.DeviceCount, "Devices count"); private readonly Counter connectedDeviceCounter = Metrics.CreateCounter(MetricName.ConnectedDeviceCount, "Connected devices count"); @@ -34,12 +31,11 @@ public void SetUp() this.mockRepository = new MockRepository(MockBehavior.Strict); this.mockLogger = this.mockRepository.Create>(); - this.mockConfigHandler = this.mockRepository.Create(); this.portalMetric = new PortalMetric(); this.deviceMetricExporterService = - new DeviceMetricExporterService(this.mockLogger.Object, this.mockConfigHandler.Object, this.portalMetric); + new DeviceMetricExporterService(this.mockLogger.Object, this.portalMetric); } [Test] @@ -47,16 +43,12 @@ public void DeviceMetricExporterServiceShouldExportDeviceCountAndConnectedConnec { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricExporterRefreshIntervalInSeconds).Returns(1); this.portalMetric.DeviceCount = 15; this.portalMetric.ConnectedDeviceCount = 8; - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.deviceMetricExporterService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.deviceMetricExporterService.Execute(null); // Assert _ = this.deviceCounter.Value.Should().Be(this.portalMetric.DeviceCount); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceMetricLoaderServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceMetricLoaderServiceTests.cs index 764244206..1a483f1bf 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceMetricLoaderServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceMetricLoaderServiceTests.cs @@ -4,13 +4,10 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services { using System; - using System.Threading; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Exceptions; using AzureIoTHub.Portal.Server.Services; using AzureIoTHub.Portal.Shared.Models.v1._0; using FluentAssertions; - using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; @@ -23,7 +20,6 @@ public class DeviceMetricLoaderServiceTests : IDisposable private PortalMetric portalMetric; private Mock> mockLogger; - private Mock mockConfigHandler; private Mock mockDeviceService; [SetUp] @@ -32,17 +28,12 @@ public void SetUp() this.mockRepository = new MockRepository(MockBehavior.Strict); this.mockLogger = this.mockRepository.Create>(); - this.mockConfigHandler = this.mockRepository.Create(); this.mockDeviceService = this.mockRepository.Create(); this.portalMetric = new PortalMetric(); - var services = new ServiceCollection(); - - _ = services.AddTransient(_ => this.mockDeviceService.Object); - this.deviceMetricLoaderService = - new DeviceMetricLoaderService(this.mockLogger.Object, this.mockConfigHandler.Object, this.portalMetric, services.BuildServiceProvider()); + new DeviceMetricLoaderService(this.mockLogger.Object, this.portalMetric, this.mockDeviceService.Object); } [Test] @@ -50,16 +41,12 @@ public void DeviceMetricLoaderServiceShouldLoadDeviceCountAndConnectedDeviceCoun { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetDevicesCount()).ReturnsAsync(10); _ = this.mockDeviceService.Setup(service => service.GetConnectedDevicesCount()).ReturnsAsync(3); - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.deviceMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.deviceMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.DeviceCount.Should().Be(10); @@ -72,16 +59,12 @@ public void DeviceMetricLoaderServiceShouldHandleInternalServerErrorExceptionWhe { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetDevicesCount()).ThrowsAsync(new InternalServerErrorException("test")); _ = this.mockDeviceService.Setup(service => service.GetConnectedDevicesCount()).ReturnsAsync(3); - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.deviceMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.deviceMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.DeviceCount.Should().Be(0); @@ -95,16 +78,12 @@ public void DeviceMetricLoaderServiceShouldHandleInternalServerErrorExceptionWhe { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetDevicesCount()).ReturnsAsync(10); _ = this.mockDeviceService.Setup(service => service.GetConnectedDevicesCount()).ThrowsAsync(new InternalServerErrorException("test")); - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.deviceMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.deviceMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.DeviceCount.Should().Be(10); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceMetricExporterServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceMetricExporterServiceTests.cs index a7c000758..558b3503f 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceMetricExporterServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceMetricExporterServiceTests.cs @@ -4,8 +4,6 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services { using System; - using System.Threading; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Shared.Constants; using AzureIoTHub.Portal.Server.Services; using AzureIoTHub.Portal.Shared.Models.v1._0; @@ -23,7 +21,6 @@ public class EdgeDeviceMetricExporterServiceTests : IDisposable private PortalMetric portalMetric; private Mock> mockLogger; - private Mock mockConfigHandler; private readonly Counter edgeDeviceCounter = Metrics.CreateCounter(MetricName.EdgeDeviceCount, "Edge devices count"); private readonly Counter connectedEdgeDeviceCounter = Metrics.CreateCounter(MetricName.ConnectedEdgeDeviceCount, "Connected edge devices count"); @@ -35,12 +32,11 @@ public void SetUp() this.mockRepository = new MockRepository(MockBehavior.Strict); this.mockLogger = this.mockRepository.Create>(); - this.mockConfigHandler = this.mockRepository.Create(); this.portalMetric = new PortalMetric(); this.edgeDeviceMetricExporterService = - new EdgeDeviceMetricExporterService(this.mockLogger.Object, this.mockConfigHandler.Object, this.portalMetric); + new EdgeDeviceMetricExporterService(this.mockLogger.Object, this.portalMetric); } [Test] @@ -48,17 +44,13 @@ public void DeviceMetricExporterServiceShouldExportDeviceCountAndConnectedConnec { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricExporterRefreshIntervalInSeconds).Returns(1); this.portalMetric.EdgeDeviceCount = 15; this.portalMetric.ConnectedEdgeDeviceCount = 8; this.portalMetric.FailedDeploymentCount = 3; - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.edgeDeviceMetricExporterService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.edgeDeviceMetricExporterService.Execute(null); // Assert _ = this.edgeDeviceCounter.Value.Should().Be(this.portalMetric.EdgeDeviceCount); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceMetricLoaderServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceMetricLoaderServiceTests.cs index ded1f5a87..d55b3a696 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceMetricLoaderServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceMetricLoaderServiceTests.cs @@ -10,7 +10,6 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services using AzureIoTHub.Portal.Server.Services; using AzureIoTHub.Portal.Shared.Models.v1._0; using FluentAssertions; - using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; @@ -23,7 +22,6 @@ public class EdgeDeviceMetricLoaderServiceTests : IDisposable private PortalMetric portalMetric; private Mock> mockLogger; - private Mock mockConfigHandler; private Mock mockDeviceService; private Mock mockConfigService; @@ -33,19 +31,13 @@ public void SetUp() this.mockRepository = new MockRepository(MockBehavior.Strict); this.mockLogger = this.mockRepository.Create>(); - this.mockConfigHandler = this.mockRepository.Create(); this.mockDeviceService = this.mockRepository.Create(); this.mockConfigService = this.mockRepository.Create(); this.portalMetric = new PortalMetric(); - var services = new ServiceCollection(); - - _ = services.AddTransient(_ => this.mockDeviceService.Object); - _ = services.AddTransient(_ => this.mockConfigService.Object); - this.edgeDeviceMetricLoaderService = - new EdgeDeviceMetricLoaderService(this.mockLogger.Object, this.mockConfigHandler.Object, this.portalMetric, services.BuildServiceProvider()); + new EdgeDeviceMetricLoaderService(this.mockLogger.Object, this.portalMetric, this.mockDeviceService.Object, this.mockConfigService.Object); } [Test] @@ -53,7 +45,6 @@ public void EdgeDeviceMetricLoaderServiceShouldLoadEdgeDeviceCountAndConnectedEd { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetEdgeDevicesCount()).ReturnsAsync(10); _ = this.mockDeviceService.Setup(service => service.GetConnectedEdgeDevicesCount()).ReturnsAsync(3); @@ -62,8 +53,7 @@ public void EdgeDeviceMetricLoaderServiceShouldLoadEdgeDeviceCountAndConnectedEd using var cancellationToken = new CancellationTokenSource(); // Act - _ = this.edgeDeviceMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.edgeDeviceMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.EdgeDeviceCount.Should().Be(10); @@ -77,17 +67,13 @@ public void EdgeDeviceMetricLoaderServiceShouldHandleInternalServerErrorExceptio { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetEdgeDevicesCount()).ThrowsAsync(new InternalServerErrorException("test")); _ = this.mockDeviceService.Setup(service => service.GetConnectedEdgeDevicesCount()).ReturnsAsync(3); _ = this.mockConfigService.Setup(service => service.GetFailedDeploymentsCount()).ReturnsAsync(1); - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.edgeDeviceMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.edgeDeviceMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.EdgeDeviceCount.Should().Be(0); @@ -102,17 +88,13 @@ public void EdgeDeviceMetricLoaderServiceShouldHandleInternalServerErrorExceptio { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetEdgeDevicesCount()).ReturnsAsync(10); _ = this.mockDeviceService.Setup(service => service.GetConnectedEdgeDevicesCount()).ThrowsAsync(new InternalServerErrorException("test")); _ = this.mockConfigService.Setup(service => service.GetFailedDeploymentsCount()).ReturnsAsync(1); - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.edgeDeviceMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.edgeDeviceMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.EdgeDeviceCount.Should().Be(10); @@ -126,17 +108,13 @@ public void EdgeDeviceMetricLoaderServiceShouldHandleInternalServerErrorExceptio { // Arrange _ = this.mockLogger.Setup(x => x.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - _ = this.mockConfigHandler.Setup(handler => handler.MetricLoaderRefreshIntervalInMinutes).Returns(1); _ = this.mockDeviceService.Setup(service => service.GetEdgeDevicesCount()).ReturnsAsync(10); _ = this.mockDeviceService.Setup(service => service.GetConnectedEdgeDevicesCount()).ReturnsAsync(3); _ = this.mockConfigService.Setup(service => service.GetFailedDeploymentsCount()).ThrowsAsync(new InternalServerErrorException("test")); - using var cancellationToken = new CancellationTokenSource(); - // Act - _ = this.edgeDeviceMetricLoaderService.StartAsync(cancellationToken.Token); - cancellationToken.Cancel(); + _ = this.edgeDeviceMetricLoaderService.Execute(null); // Assert _ = this.portalMetric.EdgeDeviceCount.Should().Be(10); diff --git a/src/AzureIoTHub.Portal/Server/Extensions/QuartzConfiguratorExtension.cs b/src/AzureIoTHub.Portal/Server/Extensions/QuartzConfiguratorExtension.cs new file mode 100644 index 000000000..b5019f401 --- /dev/null +++ b/src/AzureIoTHub.Portal/Server/Extensions/QuartzConfiguratorExtension.cs @@ -0,0 +1,32 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Server.Extensions +{ + using AzureIoTHub.Portal.Domain; + using Quartz; + + public static class QuartzConfiguratorExtension + { + public static void AddMetricsService(this IServiceCollectionQuartzConfigurator q, ConfigHandler configuration) + where TExporterService : class, IJob + where TLoaderService : class, IJob + { + _ = q.AddJob(j => j.WithIdentity(typeof(TExporterService).Name)) + .AddTrigger(t => t + .WithIdentity($"{typeof(TExporterService).Name}") + .ForJob(typeof(TExporterService).Name) + .WithSimpleSchedule(s => s + .WithIntervalInSeconds(configuration.MetricExporterRefreshIntervalInSeconds) + .RepeatForever())); + + _ = q.AddJob(j => j.WithIdentity(typeof(TLoaderService).Name)) + .AddTrigger(t => t + .WithIdentity($"{typeof(TLoaderService).Name}") + .ForJob(typeof(TLoaderService).Name) + .WithSimpleSchedule(s => s + .WithIntervalInMinutes(configuration.MetricLoaderRefreshIntervalInMinutes) + .RepeatForever())); + } + } +} diff --git a/src/AzureIoTHub.Portal/Server/Services/ConcentratorMetricExporterService.cs b/src/AzureIoTHub.Portal/Server/Services/ConcentratorMetricExporterService.cs index ed6cd7761..a562ab3d2 100644 --- a/src/AzureIoTHub.Portal/Server/Services/ConcentratorMetricExporterService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/ConcentratorMetricExporterService.cs @@ -3,46 +3,38 @@ namespace AzureIoTHub.Portal.Server.Services { - using System; - using System.Threading; using System.Threading.Tasks; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Shared.Constants; - using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Prometheus; + using Quartz; using Shared.Models.v1._0; - public class ConcentratorMetricExporterService : BackgroundService + [DisallowConcurrentExecution] + public class ConcentratorMetricExporterService : IJob { private readonly ILogger logger; - private readonly ConfigHandler configHandler; private readonly PortalMetric portalMetric; private readonly Counter concentratorCounter = Metrics.CreateCounter(MetricName.ConcentratorCount, "Concentrators count"); private readonly Counter connectedConcentratorCounter = Metrics.CreateCounter(MetricName.ConnectedConcentratorCount, "Connected concentrators count"); - public ConcentratorMetricExporterService(ILogger logger, ConfigHandler configHandler, PortalMetric portalMetric) + public ConcentratorMetricExporterService(ILogger logger, PortalMetric portalMetric) { this.logger = logger; - this.configHandler = configHandler; this.portalMetric = portalMetric; } - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + public Task Execute(IJobExecutionContext context) { - using var timer = new PeriodicTimer(TimeSpan.FromSeconds(this.configHandler.MetricExporterRefreshIntervalInSeconds)); + this.logger.LogInformation("Start exporting concentrators metrics"); - do - { - this.logger.LogInformation("Start exporting concentrators metrics"); + this.concentratorCounter.IncTo(this.portalMetric.ConcentratorCount); + this.connectedConcentratorCounter.IncTo(this.portalMetric.ConnectedConcentratorCount); - this.concentratorCounter.IncTo(this.portalMetric.ConcentratorCount); - this.connectedConcentratorCounter.IncTo(this.portalMetric.ConnectedConcentratorCount); + this.logger.LogInformation("End exporting concentrators metrics"); - this.logger.LogInformation("End exporting concentrators metrics"); - } while (await timer.WaitForNextTickAsync(stoppingToken)); + return Task.CompletedTask; } } } diff --git a/src/AzureIoTHub.Portal/Server/Services/ConcentratorMetricLoaderService.cs b/src/AzureIoTHub.Portal/Server/Services/ConcentratorMetricLoaderService.cs index 720372d90..d51238051 100644 --- a/src/AzureIoTHub.Portal/Server/Services/ConcentratorMetricLoaderService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/ConcentratorMetricLoaderService.cs @@ -3,59 +3,41 @@ namespace AzureIoTHub.Portal.Server.Services { - using System; - using System.Threading; using System.Threading.Tasks; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Exceptions; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; + using Quartz; using Shared.Models.v1._0; - public class ConcentratorMetricLoaderService : BackgroundService + [DisallowConcurrentExecution] + public class ConcentratorMetricLoaderService : IJob { private readonly ILogger logger; - private readonly ConfigHandler configHandler; private readonly PortalMetric portalMetric; + private readonly IDeviceService deviceService; - public ConcentratorMetricLoaderService(ILogger logger, ConfigHandler configHandler, PortalMetric portalMetric, IServiceProvider services) + public ConcentratorMetricLoaderService(ILogger logger, PortalMetric portalMetric, IDeviceService deviceService) { this.logger = logger; - this.configHandler = configHandler; this.portalMetric = portalMetric; - Services = services; + this.deviceService = deviceService; } - public IServiceProvider Services { get; } - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + public async Task Execute(IJobExecutionContext context) { - using var timer = new PeriodicTimer(TimeSpan.FromMinutes(this.configHandler.MetricLoaderRefreshIntervalInMinutes)); - - do - { - this.logger.LogInformation("Start loading concentrators metrics"); - - using var scope = Services.CreateScope(); + this.logger.LogInformation("Start loading concentrators metrics"); - await LoadConcentratorsCountMetric(scope); - await LoadConnectedConcentratorsCountMetric(scope); + await LoadConcentratorsCountMetric(); + await LoadConnectedConcentratorsCountMetric(); - this.logger.LogInformation("End loading concentrators metrics"); - } while (await timer.WaitForNextTickAsync(stoppingToken)); + this.logger.LogInformation("End loading concentrators metrics"); } - private async Task LoadConcentratorsCountMetric(IServiceScope scope) + private async Task LoadConcentratorsCountMetric() { try { - var deviceService = - scope.ServiceProvider - .GetRequiredService(); - this.portalMetric.ConcentratorCount = await deviceService.GetConcentratorsCount(); - } catch (InternalServerErrorException e) { @@ -63,16 +45,11 @@ private async Task LoadConcentratorsCountMetric(IServiceScope scope) } } - private async Task LoadConnectedConcentratorsCountMetric(IServiceScope scope) + private async Task LoadConnectedConcentratorsCountMetric() { try { - var deviceService = - scope.ServiceProvider - .GetRequiredService(); - this.portalMetric.ConnectedConcentratorCount = await deviceService.GetConnectedConcentratorsCount(); - } catch (InternalServerErrorException e) { diff --git a/src/AzureIoTHub.Portal/Server/Services/DeviceMetricExporterService.cs b/src/AzureIoTHub.Portal/Server/Services/DeviceMetricExporterService.cs index e3fdc3343..deab02b1c 100644 --- a/src/AzureIoTHub.Portal/Server/Services/DeviceMetricExporterService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/DeviceMetricExporterService.cs @@ -3,45 +3,38 @@ namespace AzureIoTHub.Portal.Server.Services { - using System; - using System.Threading; using System.Threading.Tasks; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Shared.Constants; - using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Prometheus; + using Quartz; using Shared.Models.v1._0; - public class DeviceMetricExporterService : BackgroundService + [DisallowConcurrentExecution] + public class DeviceMetricExporterService : IJob { private readonly ILogger logger; - private readonly ConfigHandler configHandler; private readonly PortalMetric portalMetric; private readonly Counter deviceCounter = Metrics.CreateCounter(MetricName.DeviceCount, "Devices count"); private readonly Counter connectedDeviceCounter = Metrics.CreateCounter(MetricName.ConnectedDeviceCount, "Connected devices count"); - public DeviceMetricExporterService(ILogger logger, ConfigHandler configHandler, PortalMetric portalMetric) + public DeviceMetricExporterService(ILogger logger, PortalMetric portalMetric) { this.logger = logger; - this.configHandler = configHandler; this.portalMetric = portalMetric; } - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + public Task Execute(IJobExecutionContext context) { - using var timer = new PeriodicTimer(TimeSpan.FromSeconds(this.configHandler.MetricExporterRefreshIntervalInSeconds)); + this.logger.LogInformation("Start exporting devices metrics"); - do - { - this.logger.LogInformation("Start exporting devices metrics"); + this.deviceCounter.IncTo(this.portalMetric.DeviceCount); + this.connectedDeviceCounter.IncTo(this.portalMetric.ConnectedDeviceCount); - this.deviceCounter.IncTo(this.portalMetric.DeviceCount); - this.connectedDeviceCounter.IncTo(this.portalMetric.ConnectedDeviceCount); + this.logger.LogInformation("End exporting devices metrics"); - this.logger.LogInformation("End exporting devices metrics"); - } while (await timer.WaitForNextTickAsync(stoppingToken)); + return Task.CompletedTask; } } } diff --git a/src/AzureIoTHub.Portal/Server/Services/DeviceMetricLoaderService.cs b/src/AzureIoTHub.Portal/Server/Services/DeviceMetricLoaderService.cs index 732e8b1c3..8865f76c6 100644 --- a/src/AzureIoTHub.Portal/Server/Services/DeviceMetricLoaderService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/DeviceMetricLoaderService.cs @@ -3,60 +3,41 @@ namespace AzureIoTHub.Portal.Server.Services { - using System; - using System.Threading; using System.Threading.Tasks; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Exceptions; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; + using Quartz; using Shared.Models.v1._0; - public class DeviceMetricLoaderService : BackgroundService + [DisallowConcurrentExecution] + public class DeviceMetricLoaderService : IJob { private readonly ILogger logger; - private readonly ConfigHandler configHandler; private readonly PortalMetric portalMetric; + private readonly IDeviceService deviceService; - public DeviceMetricLoaderService(ILogger logger, ConfigHandler configHandler, PortalMetric portalMetric, IServiceProvider services) + public DeviceMetricLoaderService(ILogger logger, PortalMetric portalMetric, IDeviceService deviceService) { this.logger = logger; - this.configHandler = configHandler; this.portalMetric = portalMetric; - Services = services; + this.deviceService = deviceService; } - public IServiceProvider Services { get; } - - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + public async Task Execute(IJobExecutionContext context) { - using var timer = new PeriodicTimer(TimeSpan.FromMinutes(this.configHandler.MetricLoaderRefreshIntervalInMinutes)); - - do - { - this.logger.LogInformation("Start loading devices metrics"); - - using var scope = Services.CreateScope(); + this.logger.LogInformation("Start loading devices metrics"); - await LoadDevicesCountMetric(scope); - await LoadConnectedDevicesCountMetric(scope); + await LoadDevicesCountMetric(); + await LoadConnectedDevicesCountMetric(); - this.logger.LogInformation("End loading devices metrics"); - } while (await timer.WaitForNextTickAsync(stoppingToken)); + this.logger.LogInformation("End loading devices metrics"); } - private async Task LoadDevicesCountMetric(IServiceScope scope) + private async Task LoadDevicesCountMetric() { try { - var deviceService = - scope.ServiceProvider - .GetRequiredService(); - this.portalMetric.DeviceCount = await deviceService.GetDevicesCount(); - } catch (InternalServerErrorException e) { @@ -64,16 +45,11 @@ private async Task LoadDevicesCountMetric(IServiceScope scope) } } - private async Task LoadConnectedDevicesCountMetric(IServiceScope scope) + private async Task LoadConnectedDevicesCountMetric() { try { - var deviceService = - scope.ServiceProvider - .GetRequiredService(); - this.portalMetric.ConnectedDeviceCount = await deviceService.GetConnectedDevicesCount(); - } catch (InternalServerErrorException e) { diff --git a/src/AzureIoTHub.Portal/Server/Services/EdgeDeviceMetricExporterService.cs b/src/AzureIoTHub.Portal/Server/Services/EdgeDeviceMetricExporterService.cs index 528484b63..bfa5ca279 100644 --- a/src/AzureIoTHub.Portal/Server/Services/EdgeDeviceMetricExporterService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/EdgeDeviceMetricExporterService.cs @@ -3,48 +3,41 @@ namespace AzureIoTHub.Portal.Server.Services { - using System; - using System.Threading; using System.Threading.Tasks; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Shared.Constants; - using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Prometheus; + using Quartz; using Shared.Models.v1._0; - public class EdgeDeviceMetricExporterService : BackgroundService + [DisallowConcurrentExecution] + public class EdgeDeviceMetricExporterService : IJob { private readonly ILogger logger; - private readonly ConfigHandler configHandler; private readonly PortalMetric portalMetric; private readonly Counter edgeDeviceCounter = Metrics.CreateCounter(MetricName.EdgeDeviceCount, "Edge devices count"); private readonly Counter connectedEdgeDeviceCounter = Metrics.CreateCounter(MetricName.ConnectedEdgeDeviceCount, "Connected edge devices count"); private readonly Counter failedDeploymentCount = Metrics.CreateCounter(MetricName.FailedDeploymentCount, "Failed deployments count"); - public EdgeDeviceMetricExporterService(ILogger logger, ConfigHandler configHandler, PortalMetric portalMetric) + public EdgeDeviceMetricExporterService(ILogger logger, PortalMetric portalMetric) { this.logger = logger; - this.configHandler = configHandler; this.portalMetric = portalMetric; } - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + public Task Execute(IJobExecutionContext context) { - using var timer = new PeriodicTimer(TimeSpan.FromSeconds(this.configHandler.MetricExporterRefreshIntervalInSeconds)); + this.logger.LogInformation("Start exporting edge devices metrics"); - do - { - this.logger.LogInformation("Start exporting edge devices metrics"); + this.edgeDeviceCounter.IncTo(this.portalMetric.EdgeDeviceCount); + this.connectedEdgeDeviceCounter.IncTo(this.portalMetric.ConnectedEdgeDeviceCount); - this.edgeDeviceCounter.IncTo(this.portalMetric.EdgeDeviceCount); - this.connectedEdgeDeviceCounter.IncTo(this.portalMetric.ConnectedEdgeDeviceCount); + this.failedDeploymentCount.IncTo(this.portalMetric.FailedDeploymentCount); - this.failedDeploymentCount.IncTo(this.portalMetric.FailedDeploymentCount); + this.logger.LogInformation("End exporting edge devices metrics"); - this.logger.LogInformation("End exporting edge devices metrics"); - } while (await timer.WaitForNextTickAsync(stoppingToken)); + return Task.CompletedTask; } } } diff --git a/src/AzureIoTHub.Portal/Server/Services/EdgeDeviceMetricLoaderService.cs b/src/AzureIoTHub.Portal/Server/Services/EdgeDeviceMetricLoaderService.cs index d5d1cf3d3..fbdee7522 100644 --- a/src/AzureIoTHub.Portal/Server/Services/EdgeDeviceMetricLoaderService.cs +++ b/src/AzureIoTHub.Portal/Server/Services/EdgeDeviceMetricLoaderService.cs @@ -3,61 +3,45 @@ namespace AzureIoTHub.Portal.Server.Services { - using System; - using System.Threading; using System.Threading.Tasks; - using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Exceptions; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; + using Quartz; using Shared.Models.v1._0; - public class EdgeDeviceMetricLoaderService : BackgroundService + [DisallowConcurrentExecution] + public class EdgeDeviceMetricLoaderService : IJob { private readonly ILogger logger; - private readonly ConfigHandler configHandler; private readonly PortalMetric portalMetric; + private readonly IDeviceService deviceService; + private readonly IConfigService configService; - public EdgeDeviceMetricLoaderService(ILogger logger, ConfigHandler configHandler, PortalMetric portalMetric, IServiceProvider services) + public EdgeDeviceMetricLoaderService(ILogger logger, PortalMetric portalMetric, IDeviceService deviceService, IConfigService configService) { this.logger = logger; - this.configHandler = configHandler; this.portalMetric = portalMetric; - Services = services; + this.deviceService = deviceService; + this.configService = configService; } - public IServiceProvider Services { get; } - - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + public async Task Execute(IJobExecutionContext context) { - using var timer = new PeriodicTimer(TimeSpan.FromMinutes(this.configHandler.MetricLoaderRefreshIntervalInMinutes)); + this.logger.LogInformation("Start loading edge devices metrics"); - do - { - this.logger.LogInformation("Start loading edge devices metrics"); + await LoadEdgeDevicesCountMetric(); + await LoadConnectedEdgeDevicesCountMetric(); + await LoadFailedDeploymentsCountMetric(); - using var scope = Services.CreateScope(); + this.logger.LogInformation("End loading edge devices metrics"); - await LoadEdgeDevicesCountMetric(scope); - await LoadConnectedEdgeDevicesCountMetric(scope); - await LoadFailedDeploymentsCountMetric(scope); - - this.logger.LogInformation("End loading edge devices metrics"); - } while (await timer.WaitForNextTickAsync(stoppingToken)); } - private async Task LoadEdgeDevicesCountMetric(IServiceScope scope) + private async Task LoadEdgeDevicesCountMetric() { try { - var deviceService = - scope.ServiceProvider - .GetRequiredService(); - this.portalMetric.EdgeDeviceCount = await deviceService.GetEdgeDevicesCount(); - } catch (InternalServerErrorException e) { @@ -65,16 +49,11 @@ private async Task LoadEdgeDevicesCountMetric(IServiceScope scope) } } - private async Task LoadConnectedEdgeDevicesCountMetric(IServiceScope scope) + private async Task LoadConnectedEdgeDevicesCountMetric() { try { - var deviceService = - scope.ServiceProvider - .GetRequiredService(); - this.portalMetric.ConnectedEdgeDeviceCount = await deviceService.GetConnectedEdgeDevicesCount(); - } catch (InternalServerErrorException e) { @@ -82,16 +61,11 @@ private async Task LoadConnectedEdgeDevicesCountMetric(IServiceScope scope) } } - private async Task LoadFailedDeploymentsCountMetric(IServiceScope scope) + private async Task LoadFailedDeploymentsCountMetric() { try { - var configService = - scope.ServiceProvider - .GetRequiredService(); - this.portalMetric.FailedDeploymentCount = await configService.GetFailedDeploymentsCount(); - } catch (InternalServerErrorException e) { diff --git a/src/AzureIoTHub.Portal/Server/Startup.cs b/src/AzureIoTHub.Portal/Server/Startup.cs index eb2363184..851f70ba8 100644 --- a/src/AzureIoTHub.Portal/Server/Startup.cs +++ b/src/AzureIoTHub.Portal/Server/Startup.cs @@ -283,17 +283,7 @@ Specify the authorization token got from your IDP as a header. .AddCheck("tableStorageHealth") .AddCheck("dpsHealth") .AddCheck("loraManagementFacadeHealth") - .AddCheck("databaseHealthCheck"); ; - - // Register metric loaders as Hosted Services - _ = services.AddHostedService(); - _ = services.AddHostedService(); - _ = services.AddHostedService(); - - // Register metric exporters as Hosted Services - _ = services.AddHostedService(); - _ = services.AddHostedService(); - _ = services.AddHostedService(); + .AddCheck("databaseHealthCheck"); // Add the required Quartz.NET services _ = services.AddQuartz(q => @@ -314,6 +304,10 @@ Specify the authorization token got from your IDP as a header. c.ConnectionString = configuration.PostgreSQLConnectionString; }); }); + + q.AddMetricsService(configuration); + q.AddMetricsService(configuration); + q.AddMetricsService(configuration); }); // Add the Quartz.NET hosted service