Documentation
¶
Overview ¶
Package usage provides usage tracking and logging functionality for the CLI Proxy API server. It includes plugins for monitoring API usage, token consumption, and other metrics to help with observability and billing purposes.
Index ¶
- func MigrateV1ToV2(oldFilePath, baseDir string, ...) error
- func NeedsMigration(configFilePath string, configured string) (oldPath string, needed bool)
- func ResolveDataDir(configured string, configFilePath string) string
- func SetGlobalPersister(p *Persister)
- func SetStatisticsEnabled(enabled bool)
- type ArchivedDetail
- type DetailStore
- type EventFilters
- type FlatDetail
- type MergeResult
- type Persister
- func (p *Persister) BaseDir() string
- func (p *Persister) DetailStore() *DetailStore
- func (p *Persister) HasPricing() bool
- func (p *Persister) ListArchives() []archiveInfo
- func (p *Persister) Record(detail FlatDetail)
- func (p *Persister) Retention() config.UsageRetention
- func (p *Persister) SetPriceFunc(fn PriceFunc)
- func (p *Persister) SetRetention(r config.UsageRetention)
- func (p *Persister) Snapshot() StatisticsSnapshot
- func (p *Persister) Start(ctx context.Context)
- func (p *Persister) Stop()
- func (p *Persister) Summary() *SummaryData
- func (p *Persister) TodayDetails() []FlatDetail
- func (p *Persister) TodayStore() *TodayStore
- func (p *Persister) Trim()
- func (p *Persister) TrimPreview() TrimPreviewResult
- type PriceFunc
- type QueryResult
- type RequestStatistics
- type StatisticsSnapshot
- type SummaryData
- type TodayStore
- func (t *TodayStore) Append(detail FlatDetail)
- func (t *TodayStore) Date() string
- func (t *TodayStore) Details() []FlatDetail
- func (t *TodayStore) Len() int
- func (t *TodayStore) Query(from, to time.Time, page, pageSize int, filters EventFilters, sortField string, ...) ([]FlatDetail, int)
- func (t *TodayStore) Save() error
- type TrimPreviewResult
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MigrateV1ToV2 ¶
func MigrateV1ToV2( oldFilePath, baseDir string, pricesFn func(model string) (prompt, completion, cache float64, ok bool), ) error
MigrateV1ToV2 detects and migrates legacy usage-statistics.json (v1 format) to the new directory-based v2 format (summary.json + today.json + per-day archives).
It also processes any legacy usage-archive-YYYY-MM.json files.
After successful migration, the old file is renamed to .bak.
Parameters:
- oldFilePath: path to the legacy usage-statistics.json
- baseDir: the new usage-data/ directory
- pricesFn: optional function to look up model prices for cost calculation
func NeedsMigration ¶
NeedsMigration checks if a legacy usage-statistics.json file exists.
func ResolveDataDir ¶
ResolveDataDir determines the base directory for usage data storage. Priority: configured > WRITABLE_PATH/usage-data > config dir/usage-data
func SetGlobalPersister ¶
func SetGlobalPersister(p *Persister)
SetGlobalPersister registers the active Persister for the LoggerPlugin to use.
func SetStatisticsEnabled ¶
func SetStatisticsEnabled(enabled bool)
SetStatisticsEnabled toggles whether in-memory statistics are recorded.
Types ¶
type ArchivedDetail ¶
ArchivedDetail pairs a trimmed requestDetail with its API and model names for archival.
type DetailStore ¶
type DetailStore struct {
// contains filtered or unexported fields
}
DetailStore manages historical per-day detail files on disk. Details are never loaded into memory permanently — they are read on demand for event queries.
func (*DetailStore) Archive ¶
func (d *DetailStore) Archive(date string, details []FlatDetail) error
Archive writes a day's details to the appropriate monthly directory. The file path is: baseDir/YYYY-MM/YYYY-MM-DD.json
func (*DetailStore) QueryRange ¶
func (d *DetailStore) QueryRange( from, to time.Time, page, pageSize int, filters EventFilters, sortField string, sortDesc bool, limitHint ...int, ) ([]FlatDetail, int, error)
QueryRange loads and filters details across multiple days for the given time range. Returns paginated results and total count.
When filters are empty and sortField is "timestamp", an optional limitHint enables early-exit: loading stops once enough items are collected. When filters are non-empty, all matching days are always loaded to ensure correct total counts for pagination.
type EventFilters ¶
EventFilters specifies optional filters for querying event details.
type FlatDetail ¶
type FlatDetail struct {
Timestamp time.Time `json:"timestamp"`
Model string `json:"model"`
Source string `json:"source"`
AuthIndex string `json:"auth_index"`
Tokens tokenStats `json:"tokens"`
Failed bool `json:"failed"`
}
FlatDetail is a denormalized request detail record. Unlike the old nested API→Model→Detail structure, each record carries its own model name.
func MergeSorted ¶
func MergeSorted(a, b []FlatDetail, sortField string, desc bool) []FlatDetail
MergeSorted merges two pre-sorted FlatDetail slices into a single sorted slice. Both inputs must already be sorted by the same field and direction.
type MergeResult ¶
type Persister ¶
type Persister struct {
// contains filtered or unexported fields
}
Persister handles recording, periodic persistence, trimming, and archival of usage statistics. It manages three data stores:
- SummaryData: all-time aggregated metrics (small, always in memory)
- TodayStore: current day's request details (in memory, persisted periodically)
- DetailStore: historical per-day detail files (on disk, loaded on demand)
func NewPersister ¶
func NewPersister(baseDir string, retention config.UsageRetention) *Persister
NewPersister constructs a new Persister for the given base directory. Zero retention values apply defaults; negative values disable the corresponding feature.
func (*Persister) DetailStore ¶
func (p *Persister) DetailStore() *DetailStore
DetailStore returns the historical detail store.
func (*Persister) HasPricing ¶
HasPricing reports whether a price lookup function has been configured.
func (*Persister) ListArchives ¶
func (p *Persister) ListArchives() []archiveInfo
ListArchives returns info about archived day files.
func (*Persister) Record ¶
func (p *Persister) Record(detail FlatDetail)
Record ingests a new request detail, updates summary, and appends to today's store.
func (*Persister) Retention ¶
func (p *Persister) Retention() config.UsageRetention
Retention returns the current retention configuration.
func (*Persister) SetPriceFunc ¶
SetPriceFunc sets the function used to look up model prices for cost calculation.
func (*Persister) SetRetention ¶
func (p *Persister) SetRetention(r config.UsageRetention)
SetRetention updates the retention configuration.
func (*Persister) Snapshot ¶
func (p *Persister) Snapshot() StatisticsSnapshot
Snapshot builds a legacy StatisticsSnapshot from the current state for export compatibility.
func (*Persister) Start ¶
Start loads existing data from disk and begins periodic saving and trimming.
func (*Persister) Stop ¶
func (p *Persister) Stop()
Stop saves a final snapshot and stops the periodic saver.
func (*Persister) Summary ¶
func (p *Persister) Summary() *SummaryData
Summary returns the in-memory SummaryData.
func (*Persister) TodayDetails ¶
func (p *Persister) TodayDetails() []FlatDetail
TodayDetails returns a copy of today's details.
func (*Persister) TodayStore ¶
func (p *Persister) TodayStore() *TodayStore
TodayStore returns the today store for direct queries.
func (*Persister) Trim ¶
func (p *Persister) Trim()
Trim performs an immediate trim of old details and saves the result.
func (*Persister) TrimPreview ¶
func (p *Persister) TrimPreview() TrimPreviewResult
TrimPreview returns info about what Trim would clean, without actually cleaning.
type PriceFunc ¶
PriceFunc returns the pricing for a model. Returns (prompt, completion, cache, found).
type QueryResult ¶
type QueryResult struct {
Totals summaryTotals
ByModel map[string]*summaryModelStats
ByCredential map[string]*summaryCredentialStats
TimeSeries []timePoint
TimeSeriesByModel map[string][]timePoint
}
QueryResult holds the result of a time-range query on SummaryData.
type RequestStatistics ¶
type RequestStatistics struct {
// contains filtered or unexported fields
}
RequestStatistics maintains aggregated request metrics in memory. This is the legacy storage used when no Persister is configured.
func GetRequestStatistics ¶
func GetRequestStatistics() *RequestStatistics
GetRequestStatistics returns the shared statistics store.
func (*RequestStatistics) MergeSnapshot ¶
func (s *RequestStatistics) MergeSnapshot(snapshot StatisticsSnapshot) MergeResult
MergeSnapshot merges an exported statistics snapshot into the current store. Existing data is preserved and duplicate request details are skipped.
func (*RequestStatistics) Record ¶
func (s *RequestStatistics) Record(ctx context.Context, record coreusage.Record)
Record ingests a new usage record and updates the aggregates (legacy path).
func (*RequestStatistics) Snapshot ¶
func (s *RequestStatistics) Snapshot() StatisticsSnapshot
Snapshot returns a copy of the aggregated metrics for external consumption.
func (*RequestStatistics) TrimDetails ¶
func (s *RequestStatistics) TrimDetails(cutoff time.Time) []ArchivedDetail
TrimDetails removes all details older than the cutoff time from memory. Aggregate counters are preserved. Trimmed records are returned for archival.
type StatisticsSnapshot ¶
type StatisticsSnapshot struct {
TotalRequests int64 `json:"total_requests"`
SuccessCount int64 `json:"success_count"`
FailureCount int64 `json:"failure_count"`
TotalTokens int64 `json:"total_tokens"`
APIs map[string]aPISnapshot `json:"apis"`
RequestsByDay map[string]int64 `json:"requests_by_day"`
RequestsByHour map[string]int64 `json:"requests_by_hour"`
TokensByDay map[string]int64 `json:"tokens_by_day"`
TokensByHour map[string]int64 `json:"tokens_by_hour"`
}
StatisticsSnapshot represents an immutable view of the aggregated metrics.
type SummaryData ¶
type SummaryData struct {
Version int `json:"version"`
UpdatedAt time.Time `json:"updated_at"`
Totals summaryTotals `json:"totals"`
ByModel map[string]*summaryModelStats `json:"by_model"`
ByCredential map[string]*summaryCredentialStats `json:"by_credential"`
Daily map[string]*daySummary `json:"daily"`
// contains filtered or unexported fields
}
SummaryData holds all-time aggregated usage metrics, updated incrementally on each request. It is designed to be small (~100KB/year) and kept entirely in memory.
func (*SummaryData) Query ¶
func (s *SummaryData) Query(from, to time.Time) QueryResult
Query returns aggregated results for the given time range. It filters Daily entries by [from, to] and builds time series.
func (*SummaryData) QueryHourly ¶
func (s *SummaryData) QueryHourly(from, to time.Time) QueryResult
QueryHourly returns hourly-granularity time series for the given time range.
func (*SummaryData) Record ¶
func (s *SummaryData) Record(detail FlatDetail, cost float64)
Record incrementally updates all dimensions with a single request detail.
type TodayStore ¶
type TodayStore struct {
// contains filtered or unexported fields
}
TodayStore manages the current day's request details in memory.
func (*TodayStore) Append ¶
func (t *TodayStore) Append(detail FlatDetail)
Append adds a detail record to today's store.
func (*TodayStore) Details ¶
func (t *TodayStore) Details() []FlatDetail
Details returns a copy of all details for today.
func (*TodayStore) Query ¶
func (t *TodayStore) Query( from, to time.Time, page, pageSize int, filters EventFilters, sortField string, sortDesc bool, ) ([]FlatDetail, int)
Query returns a filtered, sorted, paginated slice of today's details. page is 1-indexed. Returns the matching slice and total count (before pagination).
func (*TodayStore) Save ¶
func (t *TodayStore) Save() error
Save writes today's details to disk atomically.
type TrimPreviewResult ¶
type TrimPreviewResult struct {
FilesCount int `json:"files_count"`
TotalSizeBytes int64 `json:"total_size_bytes"`
DateRange *trimDateRange `json:"date_range,omitempty"`
Details []cleanPreviewFile `json:"details"`
}
TrimPreviewResult returns a preview of what would be cleaned by Trim.