| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- package admin
- import (
- "context"
- "encoding/json"
- "fmt"
- "time"
- "github.com/Wei-Shaw/sub2api/internal/pkg/usagestats"
- )
- var (
- dashboardTrendCache = newSnapshotCache(30 * time.Second)
- dashboardModelStatsCache = newSnapshotCache(30 * time.Second)
- dashboardGroupStatsCache = newSnapshotCache(30 * time.Second)
- dashboardUsersTrendCache = newSnapshotCache(30 * time.Second)
- dashboardAPIKeysTrendCache = newSnapshotCache(30 * time.Second)
- )
- type dashboardTrendCacheKey struct {
- StartTime string `json:"start_time"`
- EndTime string `json:"end_time"`
- Granularity string `json:"granularity"`
- UserID int64 `json:"user_id"`
- APIKeyID int64 `json:"api_key_id"`
- AccountID int64 `json:"account_id"`
- GroupID int64 `json:"group_id"`
- Model string `json:"model"`
- RequestType *int16 `json:"request_type"`
- Stream *bool `json:"stream"`
- NativeCompactionV2 *bool `json:"native_compaction_v2"`
- BillingType *int8 `json:"billing_type"`
- UpstreamModelMismatch *bool `json:"upstream_model_mismatch"`
- }
- type dashboardModelGroupCacheKey struct {
- StartTime string `json:"start_time"`
- EndTime string `json:"end_time"`
- UserID int64 `json:"user_id"`
- APIKeyID int64 `json:"api_key_id"`
- AccountID int64 `json:"account_id"`
- GroupID int64 `json:"group_id"`
- ModelSource string `json:"model_source,omitempty"`
- RequestType *int16 `json:"request_type"`
- Stream *bool `json:"stream"`
- NativeCompactionV2 *bool `json:"native_compaction_v2"`
- BillingType *int8 `json:"billing_type"`
- UpstreamModelMismatch *bool `json:"upstream_model_mismatch"`
- }
- type dashboardEntityTrendCacheKey struct {
- StartTime string `json:"start_time"`
- EndTime string `json:"end_time"`
- Granularity string `json:"granularity"`
- Limit int `json:"limit"`
- }
- func cacheStatusValue(hit bool) string {
- if hit {
- return "hit"
- }
- return "miss"
- }
- func mustMarshalDashboardCacheKey(value any) string {
- raw, err := json.Marshal(value)
- if err != nil {
- return ""
- }
- return string(raw)
- }
- func snapshotPayloadAs[T any](payload any) (T, error) {
- typed, ok := payload.(T)
- if !ok {
- var zero T
- return zero, fmt.Errorf("unexpected cache payload type %T", payload)
- }
- return typed, nil
- }
- func (h *DashboardHandler) getUsageTrendCached(
- ctx context.Context,
- startTime, endTime time.Time,
- granularity string,
- userID, apiKeyID, accountID, groupID int64,
- model string,
- requestType *int16,
- stream *bool,
- nativeCompactionV2 *bool,
- billingType *int8,
- upstreamModelMismatch *bool,
- ) ([]usagestats.TrendDataPoint, bool, error) {
- key := mustMarshalDashboardCacheKey(dashboardTrendCacheKey{
- StartTime: startTime.UTC().Format(time.RFC3339),
- EndTime: endTime.UTC().Format(time.RFC3339),
- Granularity: granularity,
- UserID: userID,
- APIKeyID: apiKeyID,
- AccountID: accountID,
- GroupID: groupID,
- Model: model,
- RequestType: requestType,
- Stream: stream,
- NativeCompactionV2: nativeCompactionV2,
- BillingType: billingType,
- UpstreamModelMismatch: upstreamModelMismatch,
- })
- entry, hit, err := dashboardTrendCache.GetOrLoad(key, func() (any, error) {
- return h.dashboardService.GetUsageTrendWithUsageFilters(ctx, startTime, endTime, granularity, usagestats.UsageLogFilters{
- UserID: userID, APIKeyID: apiKeyID, AccountID: accountID, GroupID: groupID,
- Model: model, RequestType: requestType, Stream: stream, NativeCompactionV2: nativeCompactionV2, BillingType: billingType,
- UpstreamModelMismatch: upstreamModelMismatch,
- })
- })
- if err != nil {
- return nil, hit, err
- }
- trend, err := snapshotPayloadAs[[]usagestats.TrendDataPoint](entry.Payload)
- return trend, hit, err
- }
- func (h *DashboardHandler) getModelStatsCached(
- ctx context.Context,
- startTime, endTime time.Time,
- userID, apiKeyID, accountID, groupID int64,
- modelSource string,
- requestType *int16,
- stream *bool,
- nativeCompactionV2 *bool,
- billingType *int8,
- upstreamModelMismatch *bool,
- ) ([]usagestats.ModelStat, bool, error) {
- key := mustMarshalDashboardCacheKey(dashboardModelGroupCacheKey{
- StartTime: startTime.UTC().Format(time.RFC3339),
- EndTime: endTime.UTC().Format(time.RFC3339),
- UserID: userID,
- APIKeyID: apiKeyID,
- AccountID: accountID,
- GroupID: groupID,
- ModelSource: usagestats.NormalizeModelSource(modelSource),
- RequestType: requestType,
- Stream: stream,
- NativeCompactionV2: nativeCompactionV2,
- BillingType: billingType,
- UpstreamModelMismatch: upstreamModelMismatch,
- })
- entry, hit, err := dashboardModelStatsCache.GetOrLoad(key, func() (any, error) {
- return h.dashboardService.GetModelStatsWithUsageFiltersBySource(ctx, startTime, endTime, usagestats.UsageLogFilters{
- UserID: userID, APIKeyID: apiKeyID, AccountID: accountID, GroupID: groupID,
- RequestType: requestType, Stream: stream, NativeCompactionV2: nativeCompactionV2, BillingType: billingType,
- UpstreamModelMismatch: upstreamModelMismatch,
- }, modelSource)
- })
- if err != nil {
- return nil, hit, err
- }
- stats, err := snapshotPayloadAs[[]usagestats.ModelStat](entry.Payload)
- return stats, hit, err
- }
- func (h *DashboardHandler) getGroupStatsCached(
- ctx context.Context,
- startTime, endTime time.Time,
- userID, apiKeyID, accountID, groupID int64,
- requestType *int16,
- stream *bool,
- nativeCompactionV2 *bool,
- billingType *int8,
- upstreamModelMismatch *bool,
- ) ([]usagestats.GroupStat, bool, error) {
- key := mustMarshalDashboardCacheKey(dashboardModelGroupCacheKey{
- StartTime: startTime.UTC().Format(time.RFC3339),
- EndTime: endTime.UTC().Format(time.RFC3339),
- UserID: userID,
- APIKeyID: apiKeyID,
- AccountID: accountID,
- GroupID: groupID,
- RequestType: requestType,
- Stream: stream,
- NativeCompactionV2: nativeCompactionV2,
- BillingType: billingType,
- UpstreamModelMismatch: upstreamModelMismatch,
- })
- entry, hit, err := dashboardGroupStatsCache.GetOrLoad(key, func() (any, error) {
- return h.dashboardService.GetGroupStatsWithUsageFilters(ctx, startTime, endTime, usagestats.UsageLogFilters{
- UserID: userID, APIKeyID: apiKeyID, AccountID: accountID, GroupID: groupID,
- RequestType: requestType, Stream: stream, NativeCompactionV2: nativeCompactionV2, BillingType: billingType,
- UpstreamModelMismatch: upstreamModelMismatch,
- })
- })
- if err != nil {
- return nil, hit, err
- }
- stats, err := snapshotPayloadAs[[]usagestats.GroupStat](entry.Payload)
- return stats, hit, err
- }
- func (h *DashboardHandler) getAPIKeyUsageTrendCached(ctx context.Context, startTime, endTime time.Time, granularity string, limit int) ([]usagestats.APIKeyUsageTrendPoint, bool, error) {
- key := mustMarshalDashboardCacheKey(dashboardEntityTrendCacheKey{
- StartTime: startTime.UTC().Format(time.RFC3339),
- EndTime: endTime.UTC().Format(time.RFC3339),
- Granularity: granularity,
- Limit: limit,
- })
- entry, hit, err := dashboardAPIKeysTrendCache.GetOrLoad(key, func() (any, error) {
- return h.dashboardService.GetAPIKeyUsageTrend(ctx, startTime, endTime, granularity, limit)
- })
- if err != nil {
- return nil, hit, err
- }
- trend, err := snapshotPayloadAs[[]usagestats.APIKeyUsageTrendPoint](entry.Payload)
- return trend, hit, err
- }
- func (h *DashboardHandler) getUserUsageTrendCached(ctx context.Context, startTime, endTime time.Time, granularity string, limit int) ([]usagestats.UserUsageTrendPoint, bool, error) {
- key := mustMarshalDashboardCacheKey(dashboardEntityTrendCacheKey{
- StartTime: startTime.UTC().Format(time.RFC3339),
- EndTime: endTime.UTC().Format(time.RFC3339),
- Granularity: granularity,
- Limit: limit,
- })
- entry, hit, err := dashboardUsersTrendCache.GetOrLoad(key, func() (any, error) {
- return h.dashboardService.GetUserUsageTrend(ctx, startTime, endTime, granularity, limit)
- })
- if err != nil {
- return nil, hit, err
- }
- trend, err := snapshotPayloadAs[[]usagestats.UserUsageTrendPoint](entry.Payload)
- return trend, hit, err
- }
|