using Admin.NET.Core;
using Admin.NET.Plugin.AiDOP.Dto.SmartOps;
using Admin.NET.Plugin.AiDOP.Entity;
using SqlSugar;
namespace Admin.NET.Plugin.AiDOP.SmartOps;
///
/// KPI 计算运行日志查询(只读、分页、脱敏)。租户由 MetricCode 解析,不信任前端;
/// 输出仅可展示字段,不返回 SQL 明文 / 参数快照 / 连接串;错误摘要截断。
///
public sealed class AdoSmartOpsKpiRunLogQueryService : ITransient
{
private const int DefaultPageSize = 20;
private const int MaxPageSize = 100;
private const int ErrorMessageMaxLen = 300;
private readonly ISqlSugarClient _db;
public AdoSmartOpsKpiRunLogQueryService(ISqlSugarClient db)
{
_db = db;
}
public async Task QueryAsync(KpiRunLogQueryDto dto)
{
if (string.IsNullOrWhiteSpace(dto.MetricCode))
throw Oops.Bah("metricCode 必填");
var moduleCode = AdoSmartOpsKpiBusinessInputService.ResolveModuleCode(dto.MetricCode);
var tenantId = AdoSmartOpsKpiCalcConfigService.ResolveKpiTenantId(moduleCode);
var page = dto.Page <= 0 ? 1 : dto.Page;
var pageSize = dto.PageSize <= 0 ? DefaultPageSize : Math.Min(dto.PageSize, MaxPageSize);
var status = string.IsNullOrWhiteSpace(dto.Status) ? null : dto.Status.Trim().ToUpperInvariant();
RefAsync total = 0;
var rows = await _db.Queryable().ClearFilter()
.Where(x => x.MetricCode == dto.MetricCode && x.TenantId == tenantId)
.WhereIF(status != null, x => x.Status == status)
.WhereIF(dto.StartTime != null, x => x.StartedAt >= dto.StartTime!.Value)
.WhereIF(dto.EndTime != null, x => x.StartedAt <= dto.EndTime!.Value)
.OrderBy(x => x.StartedAt, OrderByType.Desc)
.ToPageListAsync(page, pageSize, total);
return new KpiRunLogPageDto
{
Total = total.Value,
Page = page,
PageSize = pageSize,
List = rows.Select(ToItem).ToList(),
};
}
private static KpiRunLogItemDto ToItem(AdoSmartOpsKpiCalcRunLog e) => new()
{
Id = e.Id,
BatchId = e.BatchId,
MetricCode = e.MetricCode,
EngineType = e.EngineType,
VersionNo = e.VersionNo,
DataSourceCode = e.DataSourceCode,
BizDate = e.BizDate.ToString("yyyy-MM-dd"),
StartedAt = e.StartedAt.ToString("yyyy-MM-dd HH:mm:ss"),
DurationMs = e.DurationMs,
Status = e.Status,
RowCount = e.RowCount,
MetricValue = e.MetricValue,
ErrorCode = e.ErrorCode,
ErrorMessage = Truncate(e.ErrorMessage, ErrorMessageMaxLen),
TriggerType = e.TriggerType,
};
private static string? Truncate(string? s, int max) =>
string.IsNullOrEmpty(s) ? s : (s.Length <= max ? s : s.Substring(0, max) + "…");
}