Documentation
¶
Overview ¶
Package world defines the estate the console opens onto: the teams that spend, the desks that watch them, the analysts hired to each desk, and the events planted in the cost series.
The planted events are the part worth explaining. The original generated plausible noise and then detected whatever the detector happened to find, which means nothing could say whether the detector was right: a missed anomaly and an estate with no anomalies look identical from the outside.
Here every irregularity is placed on purpose and carries the answer with it, including the ones that must NOT be reported. A generator that only plants true positives cannot catch a detector that flags everything.
Index ¶
- Constants
- Variables
- func DayBefore(day string, n int) string
- func LastFullMonth() string
- func ResourceKind(service string) string
- type AIUnit
- type Agent
- type AgentState
- type Commitment
- type Desk
- type Driver
- type Event
- type Licence
- type Row
- type Series
- type Shape
- type Shared
- type Team
- type Utilisation
Constants ¶
const ( FirstDay = "2025-06-01" LastDay = "2026-08-15" )
The estate spans fourteen and a half months, which is what makes a year-on-year comparison possible and a twelve-month commitment expire inside the window.
const Waterline = 80.0
Waterline is the eighty percent line: below it, the discount is costing more than it saves.
Variables ¶
var Catalogue = buildCatalogue()
Catalogue is the whole estate, written out rather than generated, so that what the console shows can be read here and argued with.
The shape of it matters as much as the size: a few large series and a long tail of small ones, because that is what a real account looks like and it is what makes a money floor necessary rather than fussy.
var Commitments = buildCommitments()
Commitments is what each desk has bought in advance, as a share of the spend a commitment can actually cover.
Committable spend is compute, database and accelerator: storage and egress are not covered by a savings plan, and a commitment sized against the whole bill would look prudent while covering things it cannot.
var Crew = buildCrew()
Crew is thirty-six analysts. The variety is the point: a console that only ever shows healthy agents never gets its unhappy paths looked at, and the unhappy paths are where a governance product earns its place.
var Desks = []Desk{
{"aws", "cloud", "USD"},
{"gcp", "cloud", "USD"},
{"azure", "cloud", "USD"},
{"onprem", "on-premises", "USD"},
{"ai", "ai", "USD"},
{"saas", "saas", "USD"},
}
var Licences = buildLicences()
Licences is the seat estate, read off the SaaS invoices.
Issued seats are what the invoice actually pays for, at the vendor's list price. That is the whole point: "we pay for 60 seats" is a claim somebody can check against a line in the ledger, and a claim nobody can check is what this table used to be.
var Planted = []Event{ { ID: "E01", Source: "aws", Team: "ml-platform", Service: "Amazon EC2", Day: "2026-07-14", Shape: Spike, Factor: 5.4, Excess: money.Cents(184_000), Detect: true, Why: "A training run left forty instances up over a weekend. Nothing in the registry explains it.", }, { ID: "E02", Source: "gcp", Team: "research", Service: "GKE", Day: "2026-06-22", Shape: Spike, Factor: 4.1, Excess: money.Cents(96_500), Detect: true, Driver: "Quarterly model refresh, planned", Why: "Real and large, and the registry explains it. It is reported and annotated, never hidden.", }, { ID: "E03", Source: "azure", Team: "security", Service: "Microsoft Sentinel", Day: "2026-08-03", Shape: Drop, Factor: 0.08, Excess: money.Cents(-71_200), Detect: true, Why: "The log feed stopped delivering. A fall this steep is a data-quality incident, not a saving.", }, { ID: "E04", Source: "onprem", Team: "data-eng", Service: "Batch cluster", Day: "2026-07-02", Shape: Drop, Factor: 0.35, Excess: money.Cents(-42_800), Detect: true, Driver: "Batch cluster decommission, tranche 1", Why: "A deliberate switch-off. Reported so somebody confirms the saving was intended and stuck.", }, { ID: "E05", Source: "ai", Team: "product-web", Service: "Anthropic API", Day: "2026-07-28", Shape: Step, Factor: 2.6, Excess: money.Cents(238_400), Detect: true, CausedBy: "deep-analysis", Why: "An agent was moved to the strong model and left there. A step, not a spike: it does not come back down.", }, { ID: "E06", Source: "ai", Team: "ml-platform", Service: "OpenRouter", Day: "2026-08-11", Shape: Spike, Factor: 6.8, Excess: money.Cents(151_900), Detect: true, CausedBy: "unit-econ-ai", Why: "A retry loop. The clearest case for a runtime kill-switch in the whole fixture.", }, { ID: "E07", Source: "aws", Team: "product-mobile", Service: "Amazon S3", Day: "2026-06-09", Shape: Step, Factor: 1.9, Excess: money.Cents(88_300), Detect: true, Why: "Lifecycle rules were removed, so nothing ages out any more. Steps are the ones people miss.", }, { ID: "E08", Source: "gcp", Team: "growth", Service: "BigQuery", Day: "2026-08-05", Shape: Spike, Factor: 3.7, Excess: money.Cents(64_100), Detect: true, Why: "One unpartitioned query scanned the whole table, repeatedly.", }, { ID: "E09", Source: "saas", Team: "support-tools", Service: "Zendesk", Day: "2026-07-01", Shape: Step, Factor: 1.45, Excess: money.Cents(10_800), Detect: true, Why: "Seats bought for a hiring plan that slipped. Money in unused licences.", }, { ID: "N01", Source: "aws", Team: "sre-platform", Service: "Amazon EC2", Day: "2026-07-19", Shape: Natural, Factor: 1, Detect: false, Why: "A Sunday, with nothing done to it. This desk runs at 64 percent of a " + "weekday at the weekend, and a detector without a same-day-type baseline " + "reports that rhythm as an incident every single week.", }, { ID: "N02", Source: "gcp", Team: "product-web", Service: "Cloud Run", Day: "2026-06-01", Shape: Ramp, Factor: 1.8, Detect: false, Why: "Eighty percent growth spread over three months. Real, worth a forecast, " + "and not an incident on any single day.", }, { ID: "N03", Source: "azure", Team: "finance-systems", Service: "Azure Functions", Day: "2026-08-07", Shape: Spike, Factor: 4.2, Excess: money.Cents(310), Detect: false, Why: "Four times a baseline of eighty cents. Statistically loud, worth three dollars. " + "Below the money floor, and a queue full of these teaches people to ignore the queue.", }, { ID: "N04", Source: "onprem", Team: "sre-platform", Service: "Storage array", Day: "2026-06-30", Shape: Natural, Factor: 1, Detect: false, Driver: "Month-end batch on the storage array", Why: "The month-end batch runs every month and the generator puts it in the " + "series itself. A 28-day window holds only one month-end, so the median " + "never learns it: the registry is what makes a monthly rhythm expected.", }, { ID: "N05", Source: "ai", Team: "research", Service: "GPU training cluster", Day: "2026-07-08", Shape: Spike, Factor: 3.1, Excess: money.Cents(58_000), Detect: false, Driver: "Scheduled weekly training window", Why: "Large, and it happens every Wednesday on a published schedule. The registry " + "covers it as recurring, so it is expected rather than merely explained.", }, }
Planted is the fixture's ground truth. Fourteen events: nine that a correct detector must find and five it must leave alone.
{"aws", "Savings Plan", "Purchase", money.Cents(420_000), 1}, {"aws", "Reserved Instances", "Purchase", money.Cents(180_000), 1}, {"aws", "Tax", "Tax", money.Cents(96_000), 28}, {"aws", "Enterprise Discount", "Credit", money.Cents(-140_000), 28}, {"gcp", "Committed Use Discount", "Purchase", money.Cents(260_000), 1}, {"gcp", "Tax", "Tax", money.Cents(52_000), 28}, {"azure", "Reservations", "Purchase", money.Cents(150_000), 1}, {"azure", "Tax", "Tax", money.Cents(38_000), 28}, {"onprem", "Depreciation", "Purchase", money.Cents(310_000), 1}, {"saas", "Annual platform fee", "Purchase", money.Cents(88_000), 15}, }
var Teams = []Team{
{"ml-platform", "engineering", "weekly"},
{"data-eng", "engineering", "weekly"},
{"product-web", "product", "weekly"},
{"product-mobile", "product", "fortnightly"},
{"sre-platform", "engineering", "weekly"},
{"security", "risk", "monthly"},
{"growth", "commercial", "fortnightly"},
{"finance-systems", "corporate", "monthly"},
{"research", "engineering", "monthly"},
{"support-tools", "corporate", "monthly"},
}
var UtilisationRows = buildUtilisation()
UtilisationRows names the resources inside a line, and they SUM to the line.
That is the property the page is worth having: the resources listed under aws / Amazon EC2 / ml-platform add up, to the cent, to what that line cost last month. A rightsizing table whose rows do not add up to anything is a list of assertions, and the saving column on it cannot be trusted either.
Functions ¶
func DayBefore ¶
DayBefore is n days before a "2006-01-02" date, as the same string.
It exists so a fixture can stagger dates without every caller re-deriving the parse and the format, and so an unparseable input comes back unchanged rather than as the zero time, which would render as year one.
func LastFullMonth ¶
func LastFullMonth() string
lastFullMonth is the month before the estate's last day.
The planes are monthly figures, and the open month is a part-month: a seat count derived from eleven days of an invoice would say the organisation had halved its licences overnight. LastFullMonth is exported so a reconciliation can measure the same month these planes were derived from. Measuring them against a different month is the one way to make a correct derivation look broken.
func ResourceKind ¶
resourceKind classifies a service so the page can say what it is looking at. Anything that is not compute, storage-adjacent or an accelerator is not something a rightsizing page has anything useful to say about. ResourceKind is exported so a reconciliation can classify a service the same way the derivation did.
Types ¶
type AIUnit ¶
type AIUnit struct {
Month string
Team string
Model string
Tokens int64
Cost money.Cents
Actions int
Deflected int
}
AIUnit is the AI desk's economics: price separated from volume.
A bill that doubled because the price went up and a bill that doubled because twice as much was done are different facts with different answers, and a console that reports only dollars cannot tell them apart.
func AIUnits ¶
func AIUnits() []AIUnit
AIUnits is derived from the same generated series the charges come from, so the two agree by construction rather than by a reconciliation nobody runs.
func (AIUnit) PerMillion ¶
type AgentState ¶
type AgentState string
AgentState is what an analyst is doing right now, and every value here exists because some screen has to render it honestly.
const ( Active AgentState = "active" // on the rota Suspended AgentState = "suspended" // off it, with a reason, work untouched Onboarding AgentState = "onboarding" // hired, nothing finished yet Restricted AgentState = "restricted" // may propose, may not act OverGuard AgentState = "over-guard" // this month's spend passed its ceiling Probation AgentState = "probation" // first-pass rate under the bar )
type Commitment ¶
type Commitment struct {
Source string
Name string
Kind string // savings-plan, reserved, cud
Hourly money.Cents
Used float64 // percentage of what was committed
Expires string
Term string
Note string
}
Commitment is a discount bought in advance: cheaper per hour, and only if you use it.
func ExpiringWithin ¶
func ExpiringWithin(days int, from string) []Commitment
ExpiringWithin is the calendar question: what has to be decided soon.
func (Commitment) BelowWaterline ¶
func (c Commitment) BelowWaterline() bool
func (Commitment) Wasted ¶
func (c Commitment) Wasted() money.Cents
Wasted is what is being paid for and not used, per month.
type Driver ¶
type Driver struct {
Start, End, Scope, Label, Kind, Source string
}
RecurringDrivers are the registry entries that cover the events which are expected rather than merely explained.
type Event ¶
type Event struct {
ID string
Source string
Team string
Service string
Day string // ISO date; for Step and Ramp, the day it starts
Shape Shape
Factor float64 // multiple of baseline at the peak, or the step's new level
Excess money.Cents // roughly what it adds or removes, for ranking
Detect bool // must the detector report this?
Driver string // registry label that explains it, if any
CausedBy string // an agent, when the spend is an agent's own
Why string // why it is or is not an anomaly, in a person's words
}
Event is one planted irregularity and the answer that goes with it.
Detect is the ground truth. A false entry is as valuable as a true one: weekends, slow growth and amounts below the money floor are exactly what a naive detector reports, and without them in the fixture nothing measures that.
func MustDetect ¶
func MustDetect() []Event
MustDetect is the ground truth a detector is scored against.
func MustIgnore ¶
func MustIgnore() []Event
MustIgnore is the other half, and the half that catches a detector which simply flags everything loud.
type Licence ¶
type Row ¶
type Row struct {
Source string
Day string
Service string
Team string
Category string
Billed money.Cents
Quantity float64
Unit string
Meter string
Model string
}
Row is one charge as the store holds it.
type Series ¶
type Series struct {
Source string
Team string
Service string
Base money.Cents // typical weekday spend
Weekend float64 // weekend level as a fraction of a weekday
Growth float64 // annual growth, 0.20 being twenty percent a year
Noise float64 // day-to-day variation as a fraction of the base
Meter string // AI desks carry consumption alongside cost
Unit string
Model string
}
Series is one daily cost line: a team's use of one service on one desk.
type Shape ¶
type Shape string
Shape is how an irregularity looks in the series.
const ( Spike Shape = "spike" // one day well above the baseline Drop Shape = "drop" // one day well below it Step Shape = "step" // a sustained change in level Ramp Shape = "ramp" // a gradual climb, which is NOT an anomaly // Natural changes nothing at all. The control is the series behaving // normally on a day a careless detector reports anyway: a Sunday, a // month-end batch. Planting a synthetic dip and then calling it normal // would test the opposite of what it claims. Natural Shape = "natural" )
type Shared ¶
type Shared struct {
}
Shared is a cost with no team of its own: a commitment bought for a desk, tax on the whole bill, a credit applied to the account.
The estate needs these or allocation is a page with nothing to do. They are also the honest part of a real bill: on most accounts somewhere between a tenth and a quarter of the money arrives with nobody's name on it, and what a FinOps team is actually asked to do is give it one.
type Team ¶
type Team struct {
Name string
Unit string // the business unit chargeback rolls up to
Cadence string // how often they want to hear from FinOps
}
Team is a spending team. Ten of them, because a FinOps console with three teams never shows the thing that makes allocation hard, which is a shared cost nobody owns and two teams that both think they are the small one.
type Utilisation ¶
type Utilisation struct {
Source string
Service string
Team string
Resource string
Kind string // compute, database, accelerator
P95CPU float64
P95Mem float64
Days int
Monthly money.Cents // what it costs now
Advice string // the smaller size, when there is one
Saving money.Cents // what the smaller size would cost less
Why string
}
Utilisation is what a machine actually did, as opposed to what it cost.
Cost alone cannot tell you whether something is the wrong size. A box at four percent CPU and a box at eighty percent bill identically, and only one of them is a finding. This is the evidence half of a rightsizing case, and without it a recommendation is a guess with a dollar sign on it.