feat(api,core): Методы в API для получения метрик заданий роботам, StatRobotMetricsController.

This commit is contained in:
Mikhail Trubnikov
2026-07-16 10:12:56 +10:00
parent 4c80e247f5
commit 751b693e72
17 changed files with 540 additions and 2 deletions

View File

@@ -1,4 +1,6 @@
namespace PARR.API.Contracts.V1
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal;
namespace PARR.API.Contracts.V1
{
// https://tproger.ru/translations/luchshie-praktiki-razrabotki-rest-api-20-sovetov/
@@ -324,6 +326,16 @@
public const string GetWorkloadTemplateReport = BaseStat + "/workload/templates/{reportType}/{filter}/{state}/{date}";
}
public static class StatRobotMetrics
{
public const string GetRobotStatusMetrics = BaseStat + "/robot-metrics/robot-status/{robotCode}/{period}";
public const string GetTaskStatusMetrics = BaseStat + "/robot-metrics/task-status/{robotCode}/{period}";
public const string GetFilteredMetrics = BaseStat + "/robot-metrics/filtered";
}
#endregion
#region Наряды

View File

@@ -0,0 +1,22 @@
using PARR.Domain.Enums;
namespace PARR.API.Contracts.V1.Requests.Queries
{
public record RobotFilteredMetricsQuery
{
public RobotsEnum? RobotCode { get; init; }
public RobotStatusEnum? RobotStatusCode { get; init; }
public TaskStatusEnum? TaskStatusCode { get; init; }
public DateTimeOffset? DateFrom { get; init; }
public DateTimeOffset? DateTo { get; init; }
/// <summary>
/// Шаг группировки в минутах (например, 2, 30, 60, 1440)
/// </summary>
public int IntervalMinutes { get; set; } = 30;
}
}

View File

@@ -0,0 +1,8 @@
namespace PARR.API.Contracts.V1.Responses.Statistics
{
public record StatFilteredChartPoint
{
public DateTimeOffset Timestamp { get; init; }
public int Count { get; init; }
}
}

View File

@@ -0,0 +1,11 @@
namespace PARR.API.Contracts.V1.Responses.Statistics
{
public record StatRobotStatusChartPoint
{
public DateTimeOffset Timestamp { get; init; }
public int Wait { get; init; }
public int InProgress { get; init; }
public int Error { get; init; }
public int Complete { get; init; }
}
}

View File

@@ -0,0 +1,10 @@
namespace PARR.API.Contracts.V1.Responses.Statistics
{
public record StatTaskStatusChartPoint
{
public DateTimeOffset Timestamp { get; init; }
public int Creating { get; init; }
public int Updating { get; init; }
public int Ok { get; init; }
}
}

View File

@@ -0,0 +1,84 @@
using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PARR.API.Contracts.V1;
using PARR.API.Contracts.V1.Requests.Queries;
using PARR.API.Contracts.V1.Responses.Base;
using PARR.API.Contracts.V1.Responses.Statistics;
using PARR.API.Controllers.V1.Base;
using PARR.Core.Services.RobotMetrics;
using PARR.Domain.Common.Roles;
using PARR.Domain.DTOs.RobotMetrics;
using PARR.Domain.Enums;
namespace PARR.API.Controllers.V1.Statistics
{
/// <summary>
/// Метрики заданий роботам
/// </summary>
[Authorize(Roles = ParrRoles.Administrator.Role)]
public class StatRobotMetricsController : BaseApiController
{
private readonly IMapper _mapper;
private readonly IRobotMetricsService _robotMetricsService;
public StatRobotMetricsController(
IMapper mapper,
IRobotMetricsService robotMetricsService
)
{
_mapper = mapper;
_robotMetricsService = robotMetricsService;
}
/// <summary>
/// Статистика по Заданиям Роботу, график
/// </summary>
/// <returns></returns>
[HttpGet(ApiRoutes.StatRobotMetrics.GetRobotStatusMetrics)]
public async Task<IActionResult> GetRobotStatusMetrics([FromRoute] RobotsEnum robotCode, [FromRoute] ChartPeriod period, CancellationToken cancellationToken)
{
var data = await _robotMetricsService.GetRobotStatusMetricsAsync(robotCode, period, cancellationToken);
var response = _mapper.Map<List<StatRobotStatusChartPoint>>(data);
return Ok(new Response<List<StatRobotStatusChartPoint>>(response, true));
}
/// <summary>
/// Статистика по Статусам Заданий, график
/// </summary>
/// <returns></returns>
[HttpGet(ApiRoutes.StatRobotMetrics.GetTaskStatusMetrics)]
public async Task<IActionResult> GetTaskStatusMetrics([FromRoute] RobotsEnum robotCode, [FromRoute] ChartPeriod period, CancellationToken cancellationToken)
{
var data = await _robotMetricsService.GetTaskStatusMetricsAsync(robotCode, period, cancellationToken);
var response = _mapper.Map<List<StatTaskStatusChartPoint>>(data);
return Ok(new Response<List<StatTaskStatusChartPoint>>(response, true));
}
/// <summary>
/// Статистика по статусам заданий, гибкий фильтр
/// </summary>
/// <returns></returns>
[HttpGet(ApiRoutes.StatRobotMetrics.GetFilteredMetrics)]
public async Task<IActionResult> GetFilteredMetrics([FromQuery] RobotFilteredMetricsQuery request, CancellationToken cancellationToken)
{
// ------- Правильность расчетов этого метода доконца не проверена -------
var filter = _mapper.Map<MetricFilter>(request);
var data = await _robotMetricsService.GetFilteredMetricsAsync(filter, cancellationToken);
var response = _mapper.Map<List<StatFilteredChartPoint>>(data);
return Ok(new Response<List<StatFilteredChartPoint>>(response, true));
}
}
}

View File

@@ -5,6 +5,7 @@ using PARR.API.Contracts.V1.Responses.Statistics;
using PARR.API.MappingProfiles.Resolvers;
using PARR.Core.Repositories.Interfaces.Schedule;
using PARR.Domain.DTOs.Matching;
using PARR.Domain.DTOs.RobotMetrics;
using PARR.Domain.DTOs.RobotSnapshotDTO;
using PARR.Domain.DTOs.RobotTask;
using PARR.Domain.DTOs.Shortcode;
@@ -500,6 +501,14 @@ namespace PARR.API.MappingProfiles
#endregion
#region StatRobotMetrics
CreateMap<TaskStatusChartPoint, StatTaskStatusChartPoint>();
CreateMap<RobotStatusChartPoint, StatRobotStatusChartPoint>();
CreateMap<FilteredChartPoint, StatFilteredChartPoint>();
#endregion
}
}

View File

@@ -2,6 +2,7 @@
using PARR.API.Contracts.V1.Requests;
using PARR.API.Contracts.V1.Requests.Queries;
using PARR.Domain.Common.Pagination;
using PARR.Domain.DTOs.RobotMetrics;
using PARR.Domain.DTOs.RobotSnapshotDTO;
using PARR.Domain.Entities.JobEntities;
@@ -52,6 +53,9 @@ namespace PARR.API.MappingProfiles
#endregion
CreateMap<StatRobotSnapshotQuery, RobotSnapshotQuery>();
CreateMap<RobotFilteredMetricsQuery, MetricFilter>();
}
}
}