From f35092dd518e8dca5b6b3bf4ffa934556fd27471 Mon Sep 17 00:00:00 2001 From: Mikhail Trubnikov Date: Thu, 23 May 2024 14:09:37 +1000 Subject: [PATCH] =?UTF-8?q?feat(api,=20bll):=20IMqService=20-=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D0=BE=D0=B4=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81=D1=82=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BE=20=D0=BE=D1=87=D0=B5=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B8.=20StatRabbitMqController=20-=20=D1=81=D1=82=D0=B0=D1=82?= =?UTF-8?q?=D0=B8=D1=81=D1=82=D0=B8=D0=BA=D0=B0=20=D0=BF=D0=BE=20RabbitMq?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PARR.API/Contracts/V1/ApiRoutes.cs | 5 ++ .../Statistics/StatRabbitMqQueueResponse.cs | 13 +++++ .../V1/Statistics/StatRabbitMqController.cs | 56 +++++++++++++++++++ PARR.API/Settings/MqSettings.cs | 15 +++++ PARR.API/appsettings.Development.json | 6 ++ PARR.API/appsettings.json | 8 +++ PARR.BLL/Domain/Mq/MqQueueCountResult.cs | 16 ++++++ .../Services/Implementations/MqService.cs | 29 ++++++++++ PARR.BLL/Services/Interfaces/IMqService.cs | 1 + 9 files changed, 149 insertions(+) create mode 100644 PARR.API/Contracts/V1/Responses/Statistics/StatRabbitMqQueueResponse.cs create mode 100644 PARR.API/Controllers/V1/Statistics/StatRabbitMqController.cs create mode 100644 PARR.BLL/Domain/Mq/MqQueueCountResult.cs diff --git a/PARR.API/Contracts/V1/ApiRoutes.cs b/PARR.API/Contracts/V1/ApiRoutes.cs index 0c87ad44..3ca29558 100644 --- a/PARR.API/Contracts/V1/ApiRoutes.cs +++ b/PARR.API/Contracts/V1/ApiRoutes.cs @@ -212,6 +212,11 @@ public const string GetStatusesLastDay = BaseStat + "/orders/statuses/last-day/{statusCode}"; } + public static class StatRabbitMq + { + public const string GetQueueStats = BaseStat + "/rabbitmq-queues/"; + } + #endregion #region Наряды diff --git a/PARR.API/Contracts/V1/Responses/Statistics/StatRabbitMqQueueResponse.cs b/PARR.API/Contracts/V1/Responses/Statistics/StatRabbitMqQueueResponse.cs new file mode 100644 index 00000000..275d8a95 --- /dev/null +++ b/PARR.API/Contracts/V1/Responses/Statistics/StatRabbitMqQueueResponse.cs @@ -0,0 +1,13 @@ +using PARR.DAL.Services.Interfaces; + +namespace PARR.API.Contracts.V1.Responses.Statistics +{ + public class StatRabbitMqQueueResponse + { + public required string Name { get; set; } + + public int Consumers { get; set; } + + public int MessagesTotal { get; set; } + } +} diff --git a/PARR.API/Controllers/V1/Statistics/StatRabbitMqController.cs b/PARR.API/Controllers/V1/Statistics/StatRabbitMqController.cs new file mode 100644 index 00000000..a8f9637a --- /dev/null +++ b/PARR.API/Controllers/V1/Statistics/StatRabbitMqController.cs @@ -0,0 +1,56 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using PARR.API.Contracts.V1; +using PARR.API.Contracts.V1.Responses.Base; +using PARR.API.Contracts.V1.Responses.Statistics; +using PARR.API.Controllers.V1.Base; +using PARR.API.Settings; +using PARR.BLL.Services.Interfaces; +using PARR.Constants; + +namespace PARR.API.Controllers.V1.Statistics +{ + /// + /// Статистика RabbitMQ + /// + [Authorize(Roles = ParrRoles.Administrator.Role)] + public class StatRabbitMqController : BaseApiController + { + private readonly IMqService mqService; + private readonly MqSettings mqSettings; + private readonly ILogger logger; + + public StatRabbitMqController(IMqService mqService, MqSettings mqSettings, ILogger logger) + { + this.mqService = mqService; + this.mqSettings = mqSettings; + this.logger = logger; + } + + /// + /// Статистика очередей в RabbitMQ + /// + /// + [HttpGet(ApiRoutes.StatRabbitMq.GetQueueStats)] + public IActionResult GetQueueStats() + { + var response = new List(); + + // список очередей + foreach (var queue in mqSettings.Statistics.QueueList) + { + var result = mqService.GetQueueCount(mqSettings.Statistics.StatMqAuth, queue); + + if (!result.IsSuccess) + { + logger.LogError(result.Exception, $"Ошибка при запросе статистики из RabbitMQ для очереди: ${queue}"); + return BadRequest(new Response(false, new List { new ErrorModel { Message = $"" } })); + } + + response.Add(new StatRabbitMqQueueResponse { Name = queue, Consumers = result.ConsumerCount, MessagesTotal = result.Count }); + } + + return Ok(new Response>(response.OrderBy(t => t.Name).ToList(), true)); + } + } +} diff --git a/PARR.API/Settings/MqSettings.cs b/PARR.API/Settings/MqSettings.cs index 4efd1fff..c89cdc93 100644 --- a/PARR.API/Settings/MqSettings.cs +++ b/PARR.API/Settings/MqSettings.cs @@ -5,6 +5,7 @@ namespace PARR.API.Settings public class MqSettings { public MqGenerateTemplates GenerateTemplates { get; set; } = new MqGenerateTemplates(); + public MqStatistics Statistics { get; set; } = new MqStatistics(); } public class MqGenerateTemplates : IMqSettings @@ -14,4 +15,18 @@ namespace PARR.API.Settings public string User { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; } + + public class MqStatistics + { + public List QueueList { get; set; } = new List(); + public StatMqAuth StatMqAuth { get; set; } = new StatMqAuth(); + } + + public class StatMqAuth : IMqSettings + { + public string HostName { get; set; } = string.Empty; + public string QueueName { get; set; } = string.Empty; + public string User { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; + } } diff --git a/PARR.API/appsettings.Development.json b/PARR.API/appsettings.Development.json index 9c4f419b..98dc9f58 100644 --- a/PARR.API/appsettings.Development.json +++ b/PARR.API/appsettings.Development.json @@ -23,6 +23,12 @@ "MqSettings": { "GenerateTemplates": { "HostName": "10.99.253.216" + }, + "Statistics": { + "StatMqAuth": { + "HostName": "10.99.253.216" + } + } } } diff --git a/PARR.API/appsettings.json b/PARR.API/appsettings.json index 4995f00b..86134484 100644 --- a/PARR.API/appsettings.json +++ b/PARR.API/appsettings.json @@ -44,6 +44,14 @@ "QueueName": "parr-generate-templates", "User": "generate_templates_api", "Password": "DHhjgdsf*&%95" + }, + "Statistics": { + "StatMqAuth": { + "HostName": "parr-rabbitmq", + "User": "rabbit_stats", + "Password": "KJHdgfjHFsdy^&$!ff331" + }, + "QueueList": [ "parr-aihit-data", "parr-espp-schedulers", "parr-espp-templates", "parr-generate-templates", "parr-orders" ] } }, "UserCacheSettings": { diff --git a/PARR.BLL/Domain/Mq/MqQueueCountResult.cs b/PARR.BLL/Domain/Mq/MqQueueCountResult.cs new file mode 100644 index 00000000..b725f76c --- /dev/null +++ b/PARR.BLL/Domain/Mq/MqQueueCountResult.cs @@ -0,0 +1,16 @@ +namespace PARR.BLL.Domain.Mq +{ + /// + /// Результат запроса кол-ва сообщений в очереди RabbitMq + /// + public class MqQueueCountResult + { + public bool IsSuccess { get;set; } + + public int Count { get; set; } + + public int ConsumerCount { get; set; } + + public Exception? Exception { get; set; } + } +} diff --git a/PARR.BLL/Services/Implementations/MqService.cs b/PARR.BLL/Services/Implementations/MqService.cs index 8c32021f..62f2b3b5 100644 --- a/PARR.BLL/Services/Implementations/MqService.cs +++ b/PARR.BLL/Services/Implementations/MqService.cs @@ -4,6 +4,7 @@ using PARR.BLL.Domain.Mq; using PARR.BLL.Services.Interfaces; using RabbitMQ.Client; using RabbitMQ.Client.Events; +using System.Runtime; using System.Text; namespace PARR.BLL.Services.Implementations @@ -154,6 +155,34 @@ namespace PARR.BLL.Services.Implementations } } + public MqQueueCountResult GetQueueCount(IMqSettings mqSettings, string queueName) + { + var factory = new ConnectionFactory + { + HostName = mqSettings.HostName, + UserName = mqSettings.User, + Password = mqSettings.Password, + }; + + try + { + using (var connection = factory.CreateConnection()) + using (var channel = connection.CreateModel()) + { + var messageCount = channel.MessageCount(queueName); + var consumerCount = channel.ConsumerCount(queueName); + + return new MqQueueCountResult { Count = (int)messageCount, ConsumerCount = (int)consumerCount, IsSuccess = true }; + } + } + catch (Exception ex) + { + logger.LogError(ex, $"Ошибка при запросе кол-ва сообщений в очереди {queueName}"); + + return new MqQueueCountResult { Count = 0, IsSuccess = false, Exception = ex }; + } + } + public void Dispose() { channel?.Close(); diff --git a/PARR.BLL/Services/Interfaces/IMqService.cs b/PARR.BLL/Services/Interfaces/IMqService.cs index d96bfb32..c54bf4a8 100644 --- a/PARR.BLL/Services/Interfaces/IMqService.cs +++ b/PARR.BLL/Services/Interfaces/IMqService.cs @@ -7,6 +7,7 @@ namespace PARR.BLL.Services.Interfaces public interface IMqService : IDisposable { + MqQueueCountResult GetQueueCount(IMqSettings mqSettings, string queueName); bool InitConsumer(IMqSettings mqSettings, MqMessageHandlerDelegate messageHandler); MqSendResult Send(IMqSettings mqSettings, string[] msgList); }