feat: pricing stat.

This commit is contained in:
2026-04-30 16:33:30 +08:00
parent bbe6dea436
commit e43a034e28
5 changed files with 88 additions and 6 deletions
+25 -5
View File
@@ -123,6 +123,9 @@ type regionStatisticsItem struct {
AvgDurationMs float64 `json:"avgDurationMs"`
TotalOriginalFileSize int64 `json:"totalOriginalFileSize"`
TotalCompressedSize int64 `json:"totalCompressedSize"`
TotalCost float64 `json:"totalCost"`
TotalInputCost float64 `json:"totalInputCost"`
TotalOutputCost float64 `json:"totalOutputCost"`
AnalysisTypeCounts map[string]int64 `json:"analysisTypeCounts"`
SourceTypeCounts map[string]int64 `json:"sourceTypeCounts"`
FirstUsedAt *time.Time `json:"firstUsedAt"`
@@ -161,6 +164,9 @@ func (sc *StatisticsController) StatisticsByRegion(c *gin.Context) {
TotalDurationMs int64
TotalOriginalFileSize int64
TotalCompressedSize int64
TotalCost float64
TotalInputCost float64
TotalOutputCost float64
FirstUsedAt *int64
LastUsedAt *int64
}
@@ -176,6 +182,9 @@ func (sc *StatisticsController) StatisticsByRegion(c *gin.Context) {
COALESCE(SUM(duration_ms), 0) as total_duration_ms,
COALESCE(SUM(original_file_size), 0) as total_original_file_size,
COALESCE(SUM(compressed_content_size), 0) as total_compressed_size,
COALESCE(SUM(total_cost), 0) as total_cost,
COALESCE(SUM((cost_json::jsonb->>'inputCost')::float8), 0) as total_input_cost,
COALESCE(SUM((cost_json::jsonb->>'outputCost')::float8), 0) as total_output_cost,
MIN(upload_time) as first_used_at,
MAX(upload_time) as last_used_at
`).Group("region_id").Scan(&rawResults).Error
@@ -290,6 +299,9 @@ func (sc *StatisticsController) StatisticsByRegion(c *gin.Context) {
AvgDurationMs: avgDuration,
TotalOriginalFileSize: r.TotalOriginalFileSize,
TotalCompressedSize: r.TotalCompressedSize,
TotalCost: r.TotalCost,
TotalInputCost: r.TotalInputCost,
TotalOutputCost: r.TotalOutputCost,
AnalysisTypeCounts: analysisTypeMap[regionID],
SourceTypeCounts: sourceTypeMap[regionID],
FirstUsedAt: firstUsedAt,
@@ -306,6 +318,9 @@ func (sc *StatisticsController) StatisticsByRegion(c *gin.Context) {
overall.TotalDurationMs += r.TotalDurationMs
overall.TotalOriginalFileSize += r.TotalOriginalFileSize
overall.TotalCompressedSize += r.TotalCompressedSize
overall.TotalCost += r.TotalCost
overall.TotalInputCost += r.TotalInputCost
overall.TotalOutputCost += r.TotalOutputCost
if firstUsedAt != nil {
if overall.FirstUsedAt == nil || firstUsedAt.Before(*overall.FirstUsedAt) {
@@ -359,10 +374,11 @@ func (sc *StatisticsController) TimelineStatistics(c *gin.Context) {
}
type timelineItem struct {
Date string `json:"date"`
Count int64 `json:"count"`
InputTokens int64 `json:"inputTokens"`
OutputTokens int64 `json:"outputTokens"`
Date string `json:"date"`
Count int64 `json:"count"`
InputTokens int64 `json:"inputTokens"`
OutputTokens int64 `json:"outputTokens"`
TotalCost float64 `json:"totalCost"`
}
type rawRegionTimeline struct {
@@ -371,6 +387,7 @@ func (sc *StatisticsController) TimelineStatistics(c *gin.Context) {
Count int64
InputTokens int64
OutputTokens int64
TotalCost float64
}
var rawResults []rawRegionTimeline
@@ -379,7 +396,8 @@ func (sc *StatisticsController) TimelineStatistics(c *gin.Context) {
DATE(TO_TIMESTAMP(upload_time / 1000.0)) as date,
COUNT(*) as count,
COALESCE(SUM(input_tokens), 0) as input_tokens,
COALESCE(SUM(output_tokens), 0) as output_tokens
COALESCE(SUM(output_tokens), 0) as output_tokens,
COALESCE(SUM(total_cost), 0) as total_cost
`).Group("region_id, DATE(TO_TIMESTAMP(upload_time / 1000.0))").Order("region_id, date ASC").Scan(&rawResults).Error
if err != nil {
@@ -399,6 +417,7 @@ func (sc *StatisticsController) TimelineStatistics(c *gin.Context) {
overallMap[r.Date].Count += r.Count
overallMap[r.Date].InputTokens += r.InputTokens
overallMap[r.Date].OutputTokens += r.OutputTokens
overallMap[r.Date].TotalCost += r.TotalCost
regionID := uint32(0)
if r.RegionID != nil {
@@ -410,6 +429,7 @@ func (sc *StatisticsController) TimelineStatistics(c *gin.Context) {
Count: r.Count,
InputTokens: r.InputTokens,
OutputTokens: r.OutputTokens,
TotalCost: r.TotalCost,
})
if _, ok := regionIDSet[regionID]; !ok && regionID > 0 {
regionIDSet[regionID] = struct{}{}