@@ -19,6 +19,9 @@ type dashboardUsageRepoCapture struct {
1919 trendStream * bool
2020 modelRequestType * int16
2121 modelStream * bool
22+ rankingLimit int
23+ ranking []usagestats.UserSpendingRankingItem
24+ rankingTotal float64
2225}
2326
2427func (s * dashboardUsageRepoCapture ) GetUsageTrendWithFilters (
@@ -49,13 +52,26 @@ func (s *dashboardUsageRepoCapture) GetModelStatsWithFilters(
4952 return []usagestats.ModelStat {}, nil
5053}
5154
55+ func (s * dashboardUsageRepoCapture ) GetUserSpendingRanking (
56+ ctx context.Context ,
57+ startTime , endTime time.Time ,
58+ limit int ,
59+ ) (* usagestats.UserSpendingRankingResponse , error ) {
60+ s .rankingLimit = limit
61+ return & usagestats.UserSpendingRankingResponse {
62+ Ranking : s .ranking ,
63+ TotalActualCost : s .rankingTotal ,
64+ }, nil
65+ }
66+
5267func newDashboardRequestTypeTestRouter (repo * dashboardUsageRepoCapture ) * gin.Engine {
5368 gin .SetMode (gin .TestMode )
5469 dashboardSvc := service .NewDashboardService (repo , nil , nil , nil )
5570 handler := NewDashboardHandler (dashboardSvc , nil )
5671 router := gin .New ()
5772 router .GET ("/admin/dashboard/trend" , handler .GetUsageTrend )
5873 router .GET ("/admin/dashboard/models" , handler .GetModelStats )
74+ router .GET ("/admin/dashboard/users-ranking" , handler .GetUserSpendingRanking )
5975 return router
6076}
6177
@@ -130,3 +146,30 @@ func TestDashboardModelStatsInvalidStream(t *testing.T) {
130146
131147 require .Equal (t , http .StatusBadRequest , rec .Code )
132148}
149+
150+ func TestDashboardUsersRankingLimitAndCache (t * testing.T ) {
151+ dashboardUsersRankingCache = newSnapshotCache (5 * time .Minute )
152+ repo := & dashboardUsageRepoCapture {
153+ ranking : []usagestats.UserSpendingRankingItem {
154+ {UserID : 7 , Email : "rank@example.com" , ActualCost : 10.5 , Requests : 3 , Tokens : 300 },
155+ },
156+ rankingTotal : 88.8 ,
157+ }
158+ router := newDashboardRequestTypeTestRouter (repo )
159+
160+ req := httptest .NewRequest (http .MethodGet , "/admin/dashboard/users-ranking?limit=100&start_date=2025-01-01&end_date=2025-01-02" , nil )
161+ rec := httptest .NewRecorder ()
162+ router .ServeHTTP (rec , req )
163+
164+ require .Equal (t , http .StatusOK , rec .Code )
165+ require .Equal (t , 50 , repo .rankingLimit )
166+ require .Contains (t , rec .Body .String (), "\" total_actual_cost\" :88.8" )
167+ require .Equal (t , "miss" , rec .Header ().Get ("X-Snapshot-Cache" ))
168+
169+ req2 := httptest .NewRequest (http .MethodGet , "/admin/dashboard/users-ranking?limit=100&start_date=2025-01-01&end_date=2025-01-02" , nil )
170+ rec2 := httptest .NewRecorder ()
171+ router .ServeHTTP (rec2 , req2 )
172+
173+ require .Equal (t , http .StatusOK , rec2 .Code )
174+ require .Equal (t , "hit" , rec2 .Header ().Get ("X-Snapshot-Cache" ))
175+ }
0 commit comments