From e5215b7dc2b49ade376e7b1782ba1eaec4bca721 Mon Sep 17 00:00:00 2001 From: Mikhail Trubnikov Date: Tue, 28 May 2024 14:35:39 +1000 Subject: [PATCH] =?UTF-8?q?api(api,=20dal):=20IInfluxDbService.=20StatRobo?= =?UTF-8?q?tStateController=20=D0=BC=D0=BE=D0=BD=D0=B8=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D0=B3=20=D1=80=D0=BE=D0=B1=D0=BE=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PARR.API/Contracts/V1/ApiRoutes.cs | 6 ++ .../V1/Requests/RobotStateRequest.cs | 9 +++ .../V1/Statistics/StatRobotStateController.cs | 67 +++++++++++++++++++ .../Validators/RobotStateRequestValidator.cs | 17 +++++ PARR.API/appsettings.Development.json | 3 + PARR.API/appsettings.json | 12 ++++ PARR.Constants/RobotsAllEnum.cs | 28 ++++++++ PARR.DAL/InfluxDbServices/IInfluxDbService.cs | 10 +++ PARR.DAL/InfluxDbServices/InfluxDbService.cs | 59 ++++++++++++++++ PARR.DAL/PARR.DAL.csproj | 1 + PARR.DAL/ParrDalInstaller.cs | 16 +++++ PARR.DAL/Settings/InfluxDbSettings.cs | 32 +++++++++ 12 files changed, 260 insertions(+) create mode 100644 PARR.API/Contracts/V1/Requests/RobotStateRequest.cs create mode 100644 PARR.API/Controllers/V1/Statistics/StatRobotStateController.cs create mode 100644 PARR.API/Validators/RobotStateRequestValidator.cs create mode 100644 PARR.Constants/RobotsAllEnum.cs create mode 100644 PARR.DAL/InfluxDbServices/IInfluxDbService.cs create mode 100644 PARR.DAL/InfluxDbServices/InfluxDbService.cs create mode 100644 PARR.DAL/Settings/InfluxDbSettings.cs diff --git a/PARR.API/Contracts/V1/ApiRoutes.cs b/PARR.API/Contracts/V1/ApiRoutes.cs index fea903f7..daf87d89 100644 --- a/PARR.API/Contracts/V1/ApiRoutes.cs +++ b/PARR.API/Contracts/V1/ApiRoutes.cs @@ -218,6 +218,12 @@ public const string GetConnectionStats = BaseStat + "/rabbitmq-connections/"; } + public static class StatRobotState + { + public const string Get = BaseStat + "/robot-states/"; + public const string Send = BaseStat + "/robot-states/"; + } + #endregion #region Наряды diff --git a/PARR.API/Contracts/V1/Requests/RobotStateRequest.cs b/PARR.API/Contracts/V1/Requests/RobotStateRequest.cs new file mode 100644 index 00000000..b0978c73 --- /dev/null +++ b/PARR.API/Contracts/V1/Requests/RobotStateRequest.cs @@ -0,0 +1,9 @@ +using PARR.Constants; + +namespace PARR.API.Contracts.V1.Requests +{ + public class RobotStateRequest + { + public RobotsAllEnum Robot { get; set; } + } +} diff --git a/PARR.API/Controllers/V1/Statistics/StatRobotStateController.cs b/PARR.API/Controllers/V1/Statistics/StatRobotStateController.cs new file mode 100644 index 00000000..b6532576 --- /dev/null +++ b/PARR.API/Controllers/V1/Statistics/StatRobotStateController.cs @@ -0,0 +1,67 @@ +using FluentValidation; +using InfluxDB.Client.Api.Domain; +using InfluxDB.Client.Writes; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using PARR.API.Contracts.V1; +using PARR.API.Contracts.V1.Requests; +using PARR.API.Contracts.V1.Responses.Base; +using PARR.API.Controllers.V1.Base; +using PARR.Constants; +using PARR.DAL.InfluxDbServices; +using PARR.DAL.Settings; + +namespace PARR.API.Controllers.V1.Statistics +{ + /// + /// Статистика доступности роботов + /// + [Authorize(Roles = ParrRoles.EsppRobot.RoleOrAdmin)] + public class StatRobotStateController : BaseApiController + { + private readonly IInfluxDbService influxDbService; + private readonly IValidator validator; + private readonly InfluxDbSettings influxDbSettings; + + public StatRobotStateController( + IInfluxDbService influxDbService, + IValidator validator, + InfluxDbSettings influxDbSettings + ) + { + this.influxDbService = influxDbService; + this.validator = validator; + this.influxDbSettings = influxDbSettings; + } + + + /// + /// Статистика доступности роботов. Передать инф-у о доступности + /// + /// + /// + [HttpPost(ApiRoutes.StatRobotState.Send)] + public async Task Send([FromBody] RobotStateRequest request) + { + var resultValidate = await validator.ValidateAsync(request); + if (!resultValidate.IsValid) + return BadRequest(new Response(resultValidate.Errors)); + + var result = influxDbService.Write(write => + { + var point = PointData.Measurement("robots") + .Tag("robot", request.Robot.ToString()) + //.Field("robot", (int)request.Robot) + .Field("isUp", 1) + .Timestamp(DateTime.UtcNow, WritePrecision.Ns); + + write.WritePoint(point, bucket: influxDbSettings.Robots!.Bucket, org: influxDbSettings.Organization); + }, influxDbSettings.Robots!.Token); + + if (!result) + return BadRequest($"Ошибка при отправке данных"); + + return Ok(new Response("", true)); + } + } +} diff --git a/PARR.API/Validators/RobotStateRequestValidator.cs b/PARR.API/Validators/RobotStateRequestValidator.cs new file mode 100644 index 00000000..d17f979f --- /dev/null +++ b/PARR.API/Validators/RobotStateRequestValidator.cs @@ -0,0 +1,17 @@ +using FluentValidation; +using PARR.API.Contracts.V1.Requests; +using PARR.Constants; + +namespace PARR.API.Validators +{ + public class RobotStateRequestValidator : AbstractValidator + { + public RobotStateRequestValidator() + { + RuleFor(t => t.Robot).NotNull().IsInEnum().WithMessage($"Допустимые значения: {(int)RobotsAllEnum.TemplateOrder} ({RobotsAllEnum.TemplateOrder})," + + $"{(int)RobotsAllEnum.ScheduleOrder} ({RobotsAllEnum.ScheduleOrder})," + + $"{(int)RobotsAllEnum.TemplatesExport} ({RobotsAllEnum.TemplatesExport})," + + $"{(int)RobotsAllEnum.ScheduleExport} ({RobotsAllEnum.ScheduleExport})"); + } + } +} diff --git a/PARR.API/appsettings.Development.json b/PARR.API/appsettings.Development.json index 98dc9f58..56f9d92b 100644 --- a/PARR.API/appsettings.Development.json +++ b/PARR.API/appsettings.Development.json @@ -30,5 +30,8 @@ } } + }, + "InfluxDbSettings": { + "Url": "http://10.99.253.216:8086" } } diff --git a/PARR.API/appsettings.json b/PARR.API/appsettings.json index 89b3f95a..d20a9840 100644 --- a/PARR.API/appsettings.json +++ b/PARR.API/appsettings.json @@ -56,5 +56,17 @@ "UserCacheSettings": { "UserCacheTtl": "00:05:00", "UserBlockTtl": "00:03:00" + }, + "InfluxDbSettings": { + "Url": "http://parr-influxdb:8086", + "Organization": "parr", + "Robots": { + "Bucket": "robots", + "Token": "jgEigdAYLlX6_Ey8FsleCyjfGnh-sdieQDs6JtA_XNweINMUhjPKWD-ibALyo4MG6oDBFAUfFNNpwoiUR0HwQA==" + }, + "Logons": { + "Bucket": "logons", + "Token": "hjhOqZMAOm3UsAJURcROBvNqCRdR1Tp3jGYTdzduLXC4uSVrysjvEzLtM-n8jotdwuD7y0rxa2FzzOZKRGzKLg==" + } } } diff --git a/PARR.Constants/RobotsAllEnum.cs b/PARR.Constants/RobotsAllEnum.cs new file mode 100644 index 00000000..9846eecf --- /dev/null +++ b/PARR.Constants/RobotsAllEnum.cs @@ -0,0 +1,28 @@ +namespace PARR.Constants +{ + /// + /// Список всех роботов (в бд нет 3, 4) + /// + public enum RobotsAllEnum //: RobotsEnum + { + /// + /// Робот по созданию/изменению шаблона наряда ЕСПП + /// + TemplateOrder = 1, + + /// + /// Робот по созданию/изменению расписания шаблона наряда в ЕСПП + /// + ScheduleOrder = 2, + + /// + /// Робот экспорта шаблонов из ЕСПП в ПАРР + /// + TemplatesExport = 3, + + /// + /// Робот экспорта расписаний из ЕСПП в ПАРР + /// + ScheduleExport = 4 + } +} diff --git a/PARR.DAL/InfluxDbServices/IInfluxDbService.cs b/PARR.DAL/InfluxDbServices/IInfluxDbService.cs new file mode 100644 index 00000000..2a2611be --- /dev/null +++ b/PARR.DAL/InfluxDbServices/IInfluxDbService.cs @@ -0,0 +1,10 @@ +using InfluxDB.Client; + +namespace PARR.DAL.InfluxDbServices +{ + public interface IInfluxDbService + { + Task QueryAsync(Func> action, string token); + bool Write(Action action, string token); + } +} diff --git a/PARR.DAL/InfluxDbServices/InfluxDbService.cs b/PARR.DAL/InfluxDbServices/InfluxDbService.cs new file mode 100644 index 00000000..1235863e --- /dev/null +++ b/PARR.DAL/InfluxDbServices/InfluxDbService.cs @@ -0,0 +1,59 @@ +using InfluxDB.Client; +using Microsoft.Extensions.Logging; +using PARR.DAL.Settings; + +namespace PARR.DAL.InfluxDbServices +{ + internal class InfluxDbService : IInfluxDbService + { + private readonly InfluxDbSettings settings; + private readonly ILogger logger; + + public InfluxDbService(InfluxDbSettings settings, ILogger logger) + { + this.settings = settings; + this.logger = logger; + } + + public bool Write(Action action, string token) + { + try + { + //using var client = new InfluxDBClient(settings.Url, token); + //using var write = client.GetWriteApi(); + + using var client = new InfluxDBClient(settings.Url, token); + using (var write = client.GetWriteApi()) + { + action(write); + } + + return true; + } + catch (Exception ex) + { + logger.LogError(ex, "Ошибка при записи в БД, InfluxDb"); + return false; + } + } + + public async Task QueryAsync(Func> action, string token) + { + //TODO: + throw new NotImplementedException(); + //try + //{ + using var client = InfluxDBClientFactory.Create(settings.Url, token); + var query = client.GetQueryApi(); + + return await action(query); + //} + //catch (Exception ex) + //{ + // logger.LogError(ex, "Ошибка при запросе данных из БД, InfuxDb"); + // // return Task.FromResult(); + // return Task.CompletedTask; + //} + } + } +} diff --git a/PARR.DAL/PARR.DAL.csproj b/PARR.DAL/PARR.DAL.csproj index 024ea576..0d944d24 100644 --- a/PARR.DAL/PARR.DAL.csproj +++ b/PARR.DAL/PARR.DAL.csproj @@ -7,6 +7,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/PARR.DAL/ParrDalInstaller.cs b/PARR.DAL/ParrDalInstaller.cs index aeb35cb2..c625d27d 100644 --- a/PARR.DAL/ParrDalInstaller.cs +++ b/PARR.DAL/ParrDalInstaller.cs @@ -5,6 +5,7 @@ using PARR.DAL.CacheServices; using PARR.DAL.Configurations.DbSettings; using PARR.DAL.Context; using PARR.DAL.Contracts; +using PARR.DAL.InfluxDbServices; using PARR.DAL.Services.Implementation; using PARR.DAL.Services.Implementations; using PARR.DAL.Services.Interfaces; @@ -29,6 +30,8 @@ namespace PARR.DAL .UseNpgsql(configuration.GetConnectionString("DefaultConnection")) ); + #region Redis + services.AddStackExchangeRedisCache(opt => { opt.Configuration = configuration.GetConnectionString("RedisConnection"); @@ -36,6 +39,19 @@ namespace PARR.DAL services.AddTransient(); + #endregion + + #region InfluxDb + + var influxDbSettings = new InfluxDbSettings(); + configuration.GetSection(nameof(InfluxDbSettings)).Bind(influxDbSettings); + services.AddSingleton(influxDbSettings); + + services.AddTransient(); + + #endregion + + // Entity services services.AddTransient(); services.AddTransient(); diff --git a/PARR.DAL/Settings/InfluxDbSettings.cs b/PARR.DAL/Settings/InfluxDbSettings.cs new file mode 100644 index 00000000..fad300d6 --- /dev/null +++ b/PARR.DAL/Settings/InfluxDbSettings.cs @@ -0,0 +1,32 @@ +namespace PARR.DAL.Settings +{ + public class InfluxDbSettings + { + public string Url { get; set; } = string.Empty; + + public string Organization { get; set; } = string.Empty; + + public InfluxDbBucketRobotsSettings? Robots { get; set; } + + public InfluxDbBucketLogonsSettings? Logons { get; set; } + } + + public class InfluxDbBucketRobotsSettings : IInfluxDbBucketSettings + { + public string Bucket { get; set; } = string.Empty; + public string Token { get; set; } = string.Empty; + } + + public class InfluxDbBucketLogonsSettings : IInfluxDbBucketSettings + { + public string Bucket { get; set; } = string.Empty; + public string Token { get; set; } = string.Empty; + } + + public interface IInfluxDbBucketSettings + { + public string Bucket { get; set; } + + public string Token { get; set; } + } +}