usage

package
v6.9.0-aug.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 27, 2026 License: MIT Imports: 17 Imported by: 0

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

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

func NeedsMigration(configFilePath string, configured string) (oldPath string, needed bool)

NeedsMigration checks if a legacy usage-statistics.json file exists.

func ResolveDataDir

func ResolveDataDir(configured string, configFilePath string) string

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

type ArchivedDetail struct {
	APIName   string
	ModelName string
	Detail    requestDetail
}

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

type EventFilters struct {
	Model  string
	Source string
	Search string
}

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 MergeResult struct {
	Added   int64 `json:"added"`
	Skipped int64 `json:"skipped"`
}

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) BaseDir

func (p *Persister) BaseDir() string

BaseDir returns the usage data directory.

func (*Persister) DetailStore

func (p *Persister) DetailStore() *DetailStore

DetailStore returns the historical detail store.

func (*Persister) HasPricing

func (p *Persister) HasPricing() bool

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

func (p *Persister) SetPriceFunc(fn PriceFunc)

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

func (p *Persister) Start(ctx context.Context)

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

type PriceFunc func(model string) (prompt, completion, cache float64, found bool)

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) Date

func (t *TodayStore) Date() string

Date returns the current date key.

func (*TodayStore) Details

func (t *TodayStore) Details() []FlatDetail

Details returns a copy of all details for today.

func (*TodayStore) Len

func (t *TodayStore) Len() int

Len returns the number of details stored.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL