rating

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package rating turns the usage drafts of a billing period into amounts: one per draft and dimension of the pricing entry its resource type carries. Rate is a pure function. It reads nothing and writes nothing, so a period is rated from the drafts a caller already holds and the model version that caller resolved.

The arithmetic follows roadmap/00-conventions.md section 6. Values are decimals throughout, the one division is money.Div, and the one rounding is money.Round2, applied per dimension per record. Every aggregate a later pass builds is a sum of those rounded amounts, so a total equals the sum of the line items shown beside it.

A resource type the model does not price is not billed as free. The resource is skipped and its type is counted in Result.Unpriced, which reaches an operator as a warning in the run's stats. A usage field that holds a value nothing can be read as a number is counted in Result.Unreadable the same way: it is billed as zero, and a line item short by a whole metric has to be visible rather than pass for a resource that consumed nothing.

The normative specification is roadmap/03-phase-3-metering-rating.md, WP 3.6.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func QuantityOf

func QuantityOf(usage map[string]any, metric string) (decimal.Decimal, bool)

QuantityOf reads one quantity out of a draft's usage map. The map holds what metering put there, which is the quantities the engine derived beside the size fields the payload envelope decoded, so a JSON number arrives as a float64. A float never reaches decimal.NewFromFloat: it goes through the shortest text that round-trips it, which is the text encoding/json writes the same value back out as.

A string holding digits is a quantity too. It is the spelling a collector reaches for when a size outgrows the range a float64 holds exactly, and a size schema that says nothing about the field, which is what the shipped ones do, lets it through. A price is accepted in both spellings for the same reason, so a quantity spelled that way is read rather than billed at zero.

A metric the map does not hold, a metric it holds a null under, and a nil map are zero and readable: nothing was reported, and the dimension is rated at 0.00. A value nothing reads a number from, a flavor name or a boolean, is zero and unreadable, which is what tells a resource that consumed nothing from one whose quantity arrived in a form nothing bills from.

The export reads a stored usage object back through this function, so the quantity a CSV shows is the quantity its amount was rated from.

Types

type DimensionAmount

type DimensionAmount struct {
	Metric string
	Amount decimal.Decimal
	// Quantity is what the amount was rated from: the value the record carried
	// under Metric rounded to four places, and zero where it carried none, a
	// null, or one no quantity reads from. It is not the amount over the price.
	// Hours and both modifiers stand between the two on a time_gauge dimension.
	Quantity decimal.Decimal
}

DimensionAmount is what one dimension of one record costs, rounded with money.Round2. A dimension whose metric the record carries no quantity for is billed as zero and still emitted, so a record shows every dimension it was held against.

type RecordRating

type RecordRating struct {
	Amounts []DimensionAmount
	// StateModifier is what the draft's state was billed at, and one where the
	// entry names no modifier for it, rounded to the four places a quantity is
	// rendered at. It is held per record however few dimensions it reached: only
	// a time_gauge dimension is multiplied by it, while a statement shows the
	// modifier of the period it rated.
	StateModifier decimal.Decimal
}

RecordRating is one usage draft rated: one amount per dimension of the resource type's pricing entry, in the order the entry lists them.

type ResourceRating

type ResourceRating struct {
	Resource source.Resource
	Records  []RecordRating
}

ResourceRating is one resource and what its drafts are billed as. Records is index-aligned with the drafts it was rated from: Records[i] rates Drafts[i].

type Result

type Result struct {
	// Currency is the currency of the model the amounts were rated with. A
	// model version carries one currency, so every amount here is in it.
	Currency string
	// Resources holds one entry per priced resource, in the order the resources
	// came in. A resource whose type is not priced is not among them.
	Resources []ResourceRating
	// Unpriced counts the skipped resources per platform and resource type,
	// sorted by platform and then by resource type.
	Unpriced []UnpricedResourceType
	// Unreadable counts the drafts whose usage held an unreadable value, per
	// platform, resource type, and field, sorted the same way.
	Unreadable []UnreadableQuantity
}

Result is what one rating pass produced: the amounts of every priced resource, the resource types no price was found for, and the usage fields that held a value no quantity could be read from.

func Rate

func Rate(model pricing.Model, resources []metering.ResourceUsage) Result

Rate rates every resource against the model. It returns no error: a resource type the model does not price is reported in Result.Unpriced, a value no quantity reads from in Result.Unreadable, and a quantity a draft does not carry at all is billed as zero, which are the three things that can still be missing once a model has been imported.

State and type modifiers apply to time_gauge dimensions only. A counter dimension is the measured quantity times the price of a unit, whatever state the record was in: a gigabyte of egress costs what it costs, however the resource it left was running.

type UnpricedResourceType

type UnpricedResourceType struct {
	Platform     string `json:"platform"`
	ResourceType string `json:"resource_type"`
	Count        int    `json:"count"`
}

UnpricedResourceType is a resource type the model does not price, and how many resources of it were skipped. Count counts resources, not their drafts. The run writes the slice into runs.stats.unpriced, which is what the JSON tags name the fields for.

type UnreadableQuantity

type UnreadableQuantity struct {
	Platform     string `json:"platform"`
	ResourceType string `json:"resource_type"`
	Field        string `json:"field"`
	Count        int    `json:"count"`
}

UnreadableQuantity is a usage field a draft held a value under that no quantity could be read from: a size a collector sent as a flavor name, say, which the size schema of its resource type lets through. The field is billed the way an absent one is, at zero, so the run names it rather than leave an invoice short by a whole line with nothing to say so. Count counts drafts, not the dimensions the field was read for. The run writes the slice into runs.stats.unreadable, which is what the JSON tags name the fields for.

Jump to

Keyboard shortcuts

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