Documentation
¶
Index ¶
- Constants
- Variables
- type BudgetOpts
- type CostAlert
- type CostBreakdown
- type CostBudget
- type CostMetric
- type CostRate
- type OrgCostSummary
- type Scope
- type SessionCostSummary
- type Tracker
- func (t *Tracker) AccrueUsage(ctx context.Context, now time.Time) (int, error)
- func (t *Tracker) CreateAlert(ctx context.Context, alert *CostAlert) error
- func (t *Tracker) GetAlerts(ctx context.Context, resolved bool, scope Scope) ([]CostAlert, error)
- func (t *Tracker) GetBudget(ctx context.Context, orgID uuid.UUID, month string) (*CostBudget, error)
- func (t *Tracker) GetCostBreakdown(ctx context.Context, period string, scope Scope) (*CostBreakdown, error)
- func (t *Tracker) GetOrgSummary(ctx context.Context, orgID uuid.UUID, month string) (*OrgCostSummary, error)
- func (t *Tracker) GetSessionCosts(ctx context.Context, sessionID uuid.UUID) ([]CostMetric, error)
- func (t *Tracker) GetSessionSummary(ctx context.Context, sessionID uuid.UUID) (*SessionCostSummary, error)
- func (t *Tracker) RecordMetric(ctx context.Context, metric *CostMetric) error
- func (t *Tracker) ResolveAlert(ctx context.Context, alertID uuid.UUID, resolvedBy string, scope Scope) error
- func (t *Tracker) SetBudget(ctx context.Context, orgID uuid.UUID, opts BudgetOpts) error
- func (t *Tracker) StartAccrual(ctx context.Context, interval time.Duration)
- func (t *Tracker) VerifyMetric(m *CostMetric) bool
Constants ¶
const ( AlertTypeIdleSession = "idle_session" AlertTypeBudgetWarning = "budget_warning" AlertTypeBudgetExceeded = "budget_exceeded" AlertTypeOptimization = "optimization" AlertTypeStorageGrowth = "storage_growth" )
Alert types
const ( SeverityInfo = "info" SeverityWarning = "warning" SeverityCritical = "critical" )
Severity levels
const MaxMonthlyLimit = 99_999_999.99
MaxMonthlyLimit is the largest budget the schema can store: monthly_limit is DECIMAL(10,2), so a larger value would fail the insert with a numeric overflow rather than a useful validation error.
const MinAccrualSpan = 5 * time.Minute
MinAccrualSpan is how much running time must have built up before a still running session is billed. Cost metrics are immutable rows, so billing every sweep would write one row per session per minute and cost values would round to zero at the column's four decimals. A session that has stopped is always billed for its remainder, whatever its length.
Variables ¶
var ErrAlertNotFound = errors.New("cost alert not found")
ErrAlertNotFound is returned when an alert does not exist, or exists but is not visible to the caller. The two cases are deliberately indistinguishable.
var ErrInvalidBudget = errors.New("invalid budget")
ErrInvalidBudget is returned when budget input fails validation.
Functions ¶
This section is empty.
Types ¶
type BudgetOpts ¶ added in v0.3.2
BudgetOpts describes a monthly spending limit for an org.
type CostAlert ¶
type CostAlert struct {
ID uuid.UUID `db:"id" json:"id"`
AlertType string `db:"alert_type" json:"alert_type"`
Severity string `db:"severity" json:"severity"`
SessionID *uuid.UUID `db:"session_id" json:"session_id,omitempty"`
OrgID *uuid.UUID `db:"org_id" json:"org_id,omitempty"`
Title string `db:"title" json:"title"`
Description string `db:"description" json:"description"`
PotentialSavings *float64 `db:"potential_savings" json:"potential_savings,omitempty"`
Resolved bool `db:"resolved" json:"resolved"`
ResolvedAt *time.Time `db:"resolved_at" json:"resolved_at,omitempty"`
ResolvedBy *string `db:"resolved_by" json:"resolved_by,omitempty"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
CostAlert notifies about cost issues (idle sessions, budget warnings, etc.)
type CostBreakdown ¶
type CostBreakdown struct {
Period string `db:"-" json:"period"` // YYYY-MM or YYYY-MM-DD
ComputeCost float64 `db:"compute_cost" json:"compute_cost"`
StorageCost float64 `db:"storage_cost" json:"storage_cost"`
NetworkCost float64 `db:"network_cost" json:"network_cost"`
TotalCost float64 `db:"total_cost" json:"total_cost"`
TopSessions []SessionCostSummary `db:"-" json:"top_sessions"`
AlertCount int `db:"-" json:"alert_count"`
}
CostBreakdown provides detailed cost analysis.
The cost fields carry db tags because the totals are scanned straight into this struct; without them sqlx maps `compute_cost` to no field and the whole query fails with "missing destination name". Period, TopSessions and AlertCount are filled in separately and are explicitly ignored by the mapper.
type CostBudget ¶
type CostBudget struct {
ID uuid.UUID `db:"id" json:"id"`
OrgID uuid.UUID `db:"org_id" json:"org_id"`
MonthlyLimit float64 `db:"monthly_limit" json:"monthly_limit"`
AlertThreshold float64 `db:"alert_threshold" json:"alert_threshold"`
CurrentMonth string `db:"current_month" json:"current_month"`
CurrentSpend float64 `db:"current_spend" json:"current_spend"`
AlertSent bool `db:"alert_sent" json:"alert_sent"`
ExceededAt *time.Time `db:"exceeded_at" json:"exceeded_at,omitempty"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
CostBudget defines spending limits for an organization
type CostMetric ¶
type CostMetric struct {
ID uuid.UUID `db:"id" json:"id"`
SessionID uuid.UUID `db:"session_id" json:"session_id"`
PeriodStart time.Time `db:"period_start" json:"period_start"`
PeriodEnd time.Time `db:"period_end" json:"period_end"`
CPUCoreHours float64 `db:"cpu_core_hours" json:"cpu_core_hours"`
MemoryGBHours float64 `db:"memory_gb_hours" json:"memory_gb_hours"`
GPUHours float64 `db:"gpu_hours" json:"gpu_hours"`
WorkspaceGBDays float64 `db:"workspace_gb_days" json:"workspace_gb_days"`
SnapshotGBDays float64 `db:"snapshot_gb_days" json:"snapshot_gb_days"`
ArtifactGBDays float64 `db:"artifact_gb_days" json:"artifact_gb_days"`
EgressGB float64 `db:"egress_gb" json:"egress_gb"`
IngressGB float64 `db:"ingress_gb" json:"ingress_gb"`
ComputeCost float64 `db:"compute_cost" json:"compute_cost"`
StorageCost float64 `db:"storage_cost" json:"storage_cost"`
NetworkCost float64 `db:"network_cost" json:"network_cost"`
TotalCost float64 `db:"total_cost" json:"total_cost"`
RateID *uuid.UUID `db:"rate_id" json:"rate_id,omitempty"`
Checksum string `db:"checksum" json:"checksum"`
Signature string `db:"signature" json:"signature"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
CostMetric records resource usage and costs for a session over a time period
type CostRate ¶
type CostRate struct {
ID uuid.UUID `db:"id" json:"id"`
Name string `db:"name" json:"name"`
CPUCoreHourRate float64 `db:"cpu_core_hour_rate" json:"cpu_core_hour_rate"`
MemoryGBHourRate float64 `db:"memory_gb_hour_rate" json:"memory_gb_hour_rate"`
GPUHourRate float64 `db:"gpu_hour_rate" json:"gpu_hour_rate"`
StorageGBMonthRate float64 `db:"storage_gb_month_rate" json:"storage_gb_month_rate"`
SnapshotGBMonthRate float64 `db:"snapshot_gb_month_rate" json:"snapshot_gb_month_rate"`
ArtifactGBMonthRate float64 `db:"artifact_gb_month_rate" json:"artifact_gb_month_rate"`
EgressGBRate float64 `db:"egress_gb_rate" json:"egress_gb_rate"`
Active bool `db:"active" json:"active"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
CostRate defines pricing for compute, storage, and network resources
type OrgCostSummary ¶
type OrgCostSummary struct {
OrgID uuid.UUID `db:"org_id" json:"org_id"`
OrgName string `db:"org_name" json:"org_name"`
ComputeCost float64 `db:"compute_cost" json:"compute_cost"`
StorageCost float64 `db:"storage_cost" json:"storage_cost"`
NetworkCost float64 `db:"network_cost" json:"network_cost"`
TotalCost float64 `db:"total_cost" json:"total_cost"`
SessionCount int `db:"session_count" json:"session_count"`
}
OrgCostSummary aggregates all costs for an organization
type Scope ¶ added in v0.3.2
type Scope struct {
// Master grants the deployment-wide view.
Master bool
// Actor is the API key principal whose sessions and orgs are visible.
Actor string
}
Scope restricts a cost query to the data one caller is allowed to see.
Spend figures are business-sensitive: a deployment-wide total, and the names of the ten sessions that spent the most, tell any tenant how busy every other tenant is. Every aggregate query therefore takes a Scope, and only the master key gets the unrestricted view.
func ActorScope ¶ added in v0.3.2
ActorScope returns the scope visible to one API key principal.
func DeploymentScope ¶ added in v0.3.2
func DeploymentScope() Scope
DeploymentScope returns the unrestricted scope used by the master key and by internal callers such as the cost sweeper.
type SessionCostSummary ¶
type SessionCostSummary struct {
SessionID uuid.UUID `db:"session_id" json:"session_id"`
SessionName string `db:"session_name" json:"session_name"`
ComputeCost float64 `db:"compute_cost" json:"compute_cost"`
StorageCost float64 `db:"storage_cost" json:"storage_cost"`
NetworkCost float64 `db:"network_cost" json:"network_cost"`
TotalCost float64 `db:"total_cost" json:"total_cost"`
// StoppedAt is set when the session has ended (deleted, or stopped when idle).
StoppedAt *time.Time `db:"stopped_at" json:"stopped_at,omitempty"`
FirstMetric *time.Time `db:"first_metric" json:"first_metric,omitempty"`
LastMetric *time.Time `db:"last_metric" json:"last_metric,omitempty"`
}
SessionCostSummary aggregates all costs for a session FirstMetric and LastMetric are pointers because the query left-joins cost_metrics: a session that has not been billed yet has no metrics, and MIN/MAX over zero rows returns NULL.
type Tracker ¶
type Tracker struct {
// contains filtered or unexported fields
}
Tracker collects and calculates cost metrics for sessions
func (*Tracker) AccrueUsage ¶ added in v0.4.4
AccrueUsage bills every session for the time that has passed since it was last billed, and returns how many metrics were recorded. It is safe to call repeatedly and from several API instances: a period that was already billed is skipped.
func (*Tracker) CreateAlert ¶
CreateAlert creates a cost alert
func (*Tracker) GetBudget ¶ added in v0.3.2
func (t *Tracker) GetBudget(ctx context.Context, orgID uuid.UUID, month string) (*CostBudget, error)
GetBudget returns the budget for an org and month, or nil when none is set.
func (*Tracker) GetCostBreakdown ¶
func (t *Tracker) GetCostBreakdown(ctx context.Context, period string, scope Scope) (*CostBreakdown, error)
GetCostBreakdown returns cost breakdown for a period, restricted to the sessions and alerts the scope may see.
func (*Tracker) GetOrgSummary ¶
func (t *Tracker) GetOrgSummary(ctx context.Context, orgID uuid.UUID, month string) (*OrgCostSummary, error)
GetOrgSummary returns aggregated cost summary for an organization
func (*Tracker) GetSessionCosts ¶
GetSessionCosts returns all cost metrics for a session
func (*Tracker) GetSessionSummary ¶
func (t *Tracker) GetSessionSummary(ctx context.Context, sessionID uuid.UUID) (*SessionCostSummary, error)
GetSessionSummary returns aggregated cost summary for a session
func (*Tracker) RecordMetric ¶
func (t *Tracker) RecordMetric(ctx context.Context, metric *CostMetric) error
RecordMetric records a cost metric for a session
func (*Tracker) ResolveAlert ¶
func (t *Tracker) ResolveAlert(ctx context.Context, alertID uuid.UUID, resolvedBy string, scope Scope) error
ResolveAlert marks an alert as resolved.
The scope is part of the WHERE clause rather than a separate lookup: a caller must not be able to resolve — and so hide — an alert raised against another tenant's session. Returns ErrAlertNotFound when no visible alert matches, which also covers a wholly unknown ID.
func (*Tracker) SetBudget ¶ added in v0.3.2
SetBudget creates or replaces the budget for an org and month.
func (*Tracker) StartAccrual ¶ added in v0.4.4
StartAccrual bills sessions every interval until ctx is cancelled.
func (*Tracker) VerifyMetric ¶ added in v0.3.1
func (t *Tracker) VerifyMetric(m *CostMetric) bool
VerifyMetric reports whether a metric's stored checksum and signature match its contents. Returns false when signing is not configured so that an unkeyed deployment cannot treat every metric as authentic.