usage

package
v1.9.0 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package usage defines API key usage records and aggregation types.

Index

Constants

View Source
const (
	PeriodHourly  = "hourly"
	PeriodDaily   = "daily"
	PeriodMonthly = "monthly"
)

Aggregation periods accepted by Store.Aggregate. Buckets are UTC.

Variables

View Source
var ErrInvalidPeriod = errors.New("keysmith: usage period must be hourly, daily or monthly")

ErrInvalidPeriod is returned when an aggregation period is not one of the Period constants.

Functions

func Truncate

func Truncate(t time.Time, period string) (time.Time, error)

Truncate returns the UTC start of the bucket t falls in.

Types

type Aggregation

type Aggregation struct {
	KeyID            id.KeyID  `json:"key_id"`
	TenantID         string    `json:"tenant_id"`
	Period           string    `json:"period"`
	PeriodStart      time.Time `json:"period_start"`
	RequestCount     int64     `json:"request_count"`
	ErrorCount       int64     `json:"error_count"`        // status >= 400
	ServerErrorCount int64     `json:"server_error_count"` // status >= 500
	TotalLatency     int64     `json:"total_latency_ms"`
	// P50Latency and P99Latency are never set. The four backends cannot
	// compute the same percentile, so none of them try. The fields stay so
	// the JSON shape does not break.
	P50Latency *int64 `json:"p50_latency_ms,omitempty"`
	P99Latency *int64 `json:"p99_latency_ms,omitempty"`
}

Aggregation represents aggregated usage statistics for one bucket. It is computed from the raw usage rows on every call. KeyID is the zero value when the filter did not name a key and the bucket sums across keys.

type QueryFilter

type QueryFilter struct {
	KeyID    *id.KeyID  `json:"key_id,omitempty"`
	TenantID string     `json:"tenant_id,omitempty"`
	After    *time.Time `json:"after,omitempty"`
	Before   *time.Time `json:"before,omitempty"`
	Period   string     `json:"period,omitempty"`
	Limit    int        `json:"limit,omitempty"`
	Offset   int        `json:"offset,omitempty"`
}

QueryFilter contains filters for querying usage.

type Record

type Record struct {
	ID         id.UsageID     `json:"id" db:"id"`
	KeyID      id.KeyID       `json:"key_id" db:"key_id"`
	TenantID   string         `json:"tenant_id" db:"tenant_id"`
	Endpoint   string         `json:"endpoint" db:"endpoint"`
	Method     string         `json:"method" db:"method"`
	StatusCode int            `json:"status_code" db:"status_code"`
	IPAddress  string         `json:"ip_address" db:"ip_address"`
	UserAgent  string         `json:"user_agent,omitempty" db:"user_agent"`
	Latency    time.Duration  `json:"latency" db:"latency_ms"`
	Metadata   map[string]any `json:"metadata,omitempty" db:"metadata"`
	CreatedAt  time.Time      `json:"created_at" db:"created_at"`
}

Record is a single usage event for a key.

type Store

type Store interface {
	Record(ctx context.Context, rec *Record) error
	RecordBatch(ctx context.Context, recs []*Record) error
	Query(ctx context.Context, filter *QueryFilter) ([]*Record, error)
	// Aggregate buckets recorded usage by filter.Period. It ignores
	// filter.Limit and filter.Offset, so bound the range with filter.After
	// and filter.Before.
	Aggregate(ctx context.Context, filter *QueryFilter) ([]*Aggregation, error)
	Count(ctx context.Context, filter *QueryFilter) (int64, error)
	Purge(ctx context.Context, before time.Time) (int64, error)
	DailyCount(ctx context.Context, keyID id.KeyID, date time.Time) (int64, error)
	MonthlyCount(ctx context.Context, keyID id.KeyID, month time.Time) (int64, error)
}

Store is the persistence interface for key usage tracking.

Jump to

Keyboard shortcuts

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