feat: 新增近24小时每小时与今日模型使用量统计接口及实现

This commit is contained in:
chenchun
2026-01-23 14:50:46 +08:00
parent 0983837ff7
commit b8c79ac61c
5 changed files with 176 additions and 1 deletions

View File

@@ -0,0 +1,22 @@
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
/// <summary>
/// 每小时Token使用量统计DTO柱状图
/// </summary>
public class HourlyTokenUsageDto
{
/// <summary>
/// 小时时间点
/// </summary>
public DateTime Hour { get; set; }
/// <summary>
/// 该小时总Token消耗量
/// </summary>
public long TotalTokens { get; set; }
/// <summary>
/// 各模型Token消耗明细
/// </summary>
public List<ModelTokenBreakdownDto> ModelBreakdown { get; set; } = new();
}

View File

@@ -0,0 +1,22 @@
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
/// <summary>
/// 模型今日使用量统计DTO卡片列表
/// </summary>
public class ModelTodayUsageDto
{
/// <summary>
/// 模型ID
/// </summary>
public string ModelId { get; set; }
/// <summary>
/// 今日使用次数
/// </summary>
public int UsageCount { get; set; }
/// <summary>
/// 今日消耗总Token数
/// </summary>
public long TotalTokens { get; set; }
}

View File

@@ -0,0 +1,17 @@
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
/// <summary>
/// 模型Token堆叠数据DTO用于柱状图
/// </summary>
public class ModelTokenBreakdownDto
{
/// <summary>
/// 模型ID
/// </summary>
public string ModelId { get; set; }
/// <summary>
/// Token消耗量
/// </summary>
public long Tokens { get; set; }
}

View File

@@ -24,4 +24,16 @@ public interface IUsageStatisticsService
/// </summary> /// </summary>
/// <returns>尊享服务Token用量统计</returns> /// <returns>尊享服务Token用量统计</returns>
Task<PremiumTokenUsageDto> GetPremiumTokenUsageAsync(); Task<PremiumTokenUsageDto> GetPremiumTokenUsageAsync();
/// <summary>
/// 获取当前用户近24小时每小时Token消耗统计柱状图
/// </summary>
/// <returns>每小时Token使用量列表包含各模型堆叠数据</returns>
Task<List<HourlyTokenUsageDto>> GetLast24HoursTokenUsageAsync(UsageStatisticsGetInput input);
/// <summary>
/// 获取当前用户今日各模型使用量统计(卡片列表)
/// </summary>
/// <returns>模型今日使用量列表包含使用次数和总Token</returns>
Task<List<ModelTodayUsageDto>> GetTodayModelUsageAsync(UsageStatisticsGetInput input);
} }

View File

@@ -57,7 +57,7 @@ public class UsageStatisticsService : ApplicationService, IUsageStatisticsServic
// 从Message表统计近7天的token消耗 // 从Message表统计近7天的token消耗
var dailyUsage = await _messageRepository._DbQueryable var dailyUsage = await _messageRepository._DbQueryable
.Where(x => x.UserId == userId) .Where(x => x.UserId == userId)
.Where(x => x.Role == "assistant" || x.Role == "system") .Where(x => x.Role == "system")
.Where(x => x.CreationTime >= startDate && x.CreationTime < endDate.AddDays(1)) .Where(x => x.CreationTime >= startDate && x.CreationTime < endDate.AddDays(1))
.WhereIF(input.TokenId.HasValue,x => x.TokenId == input.TokenId) .WhereIF(input.TokenId.HasValue,x => x.TokenId == input.TokenId)
.GroupBy(x => x.CreationTime.Date) .GroupBy(x => x.CreationTime.Date)
@@ -228,4 +228,106 @@ public class UsageStatisticsService : ApplicationService, IUsageStatisticsServic
return result; return result;
} }
/// <summary>
/// 获取当前用户近24小时每小时Token消耗统计柱状图
/// </summary>
/// <returns>每小时Token使用量列表包含各模型堆叠数据</returns>
public async Task<List<HourlyTokenUsageDto>> GetLast24HoursTokenUsageAsync([FromQuery]UsageStatisticsGetInput input)
{
var userId = CurrentUser.GetId();
var now = DateTime.Now;
var startTime = now.AddHours(-23); // 滚动24小时从23小时前到现在
var startHour = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0);
// 从Message表查询近24小时的数据只选择需要的字段
var messages = await _messageRepository._DbQueryable
.Where(x => x.UserId == userId)
.Where(x => x.Role == "system")
.Where(x => x.CreationTime >= startHour)
.WhereIF(input.TokenId.HasValue, x => x.TokenId == input.TokenId)
.Select(x => new
{
x.CreationTime,
x.ModelId,
x.TokenUsage.TotalTokenCount
})
.ToListAsync();
// 在内存中按小时和模型分组统计
var hourlyGrouped = messages
.GroupBy(x => new
{
Hour = new DateTime(x.CreationTime.Year, x.CreationTime.Month, x.CreationTime.Day, x.CreationTime.Hour, 0, 0),
x.ModelId
})
.Select(g => new
{
g.Key.Hour,
g.Key.ModelId,
Tokens = g.Sum(x => x.TotalTokenCount)
})
.ToList();
// 生成完整的24小时数据
var result = new List<HourlyTokenUsageDto>();
for (int i = 0; i < 24; i++)
{
var hour = startHour.AddHours(i);
var hourData = hourlyGrouped.Where(x => x.Hour == hour).ToList();
var modelBreakdown = hourData.Select(x => new ModelTokenBreakdownDto
{
ModelId = x.ModelId,
Tokens = x.Tokens
}).ToList();
result.Add(new HourlyTokenUsageDto
{
Hour = hour,
TotalTokens = modelBreakdown.Sum(x => x.Tokens),
ModelBreakdown = modelBreakdown
});
}
return result;
}
/// <summary>
/// 获取当前用户今日各模型使用量统计(卡片列表)
/// </summary>
/// <returns>模型今日使用量列表包含使用次数和总Token</returns>
public async Task<List<ModelTodayUsageDto>> GetTodayModelUsageAsync([FromQuery]UsageStatisticsGetInput input)
{
var userId = CurrentUser.GetId();
var todayStart = DateTime.Today; // 今天凌晨0点
var tomorrowStart = todayStart.AddDays(1);
// 从Message表查询今天的数据只选择需要的字段
var messages = await _messageRepository._DbQueryable
.Where(x => x.UserId == userId)
.Where(x => x.Role == "system")
.Where(x => x.CreationTime >= todayStart && x.CreationTime < tomorrowStart)
.WhereIF(input.TokenId.HasValue, x => x.TokenId == input.TokenId)
.Select(x => new
{
x.ModelId,
x.TokenUsage.TotalTokenCount
})
.ToListAsync();
// 在内存中按模型分组统计
var modelStats = messages
.GroupBy(x => x.ModelId)
.Select(g => new ModelTodayUsageDto
{
ModelId = g.Key,
UsageCount = g.Count(),
TotalTokens = g.Sum(x => x.TotalTokenCount)
})
.OrderByDescending(x => x.TotalTokens)
.ToList();
return modelStats;
}
} }