Help us shape the future of Go! Take the 2026 Go Developer Survey

ledger

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 8, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package ledger records what every API call cost, as an append-only JSONL file.

The point is to answer "what did I spend today, and how much did the context cache save me" without a dashboard. Token counts are stored alongside the estimated cost so old rows can be repriced when DeepSeek changes the rate card — the cost field is a convenience, the counts are the record.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseSince

func ParseSince(s string) (time.Time, error)

ParseSince turns a human window ("today", "7d", "24h", "all", or a YYYY-MM-DD date) into a cutoff time.

func Path

func Path() string

Path is the ledger file.

Types

type Entry

type Entry struct {
	Time  time.Time `json:"ts"`
	API   string    `json:"api"`   // chat | fim | responses | anthropic
	Model string    `json:"model"` // as resolved to a priced model
	// Requested is the model name the user asked for, kept only when it
	// differs from Model — the Anthropic endpoint remaps Claude names.
	Requested       string  `json:"requested,omitempty"`
	InputTokens     int     `json:"in"`
	CacheHitTokens  int     `json:"cache_hit"`
	CacheMissTokens int     `json:"cache_miss"`
	OutputTokens    int     `json:"out"`
	ReasoningTokens int     `json:"reasoning,omitempty"`
	CostUSD         float64 `json:"cost_usd"`
	SavedUSD        float64 `json:"saved_usd"`
	DurationMS      int64   `json:"ms"`
	Stream          bool    `json:"stream,omitempty"`
	Session         string  `json:"session,omitempty"`
}

Entry is one API call.

func Load

func Load(since time.Time) ([]Entry, error)

Load reads entries at or after since. A missing ledger is not an error; it means nothing has been spent yet.

func Record

func Record(api, requested string, u deepseek.Usage, dur time.Duration, stream bool, session string) (Entry, error)

Record appends one call. Ledger failures never fail the command that produced them: the user asked for a completion, not for bookkeeping. The error is returned so the caller can mention it under --verbose.

type Report

type Report struct {
	Since   time.Time          `json:"since,omitempty"`
	Total   Summary            `json:"total"`
	ByModel map[string]Summary `json:"by_model"`
	ByAPI   map[string]Summary `json:"by_api"`
}

Report is a grouped view of the ledger.

func Summarize

func Summarize(entries []Entry, since time.Time) *Report

Summarize groups entries by model and by API.

func (*Report) APIs

func (r *Report) APIs() []string

APIs returns the wire formats present, in descending cost order.

func (*Report) Models

func (r *Report) Models() []string

Models returns the model names present, in descending cost order, so the biggest spender is always the first line printed.

type Summary

type Summary struct {
	Calls           int     `json:"calls"`
	InputTokens     int     `json:"input_tokens"`
	CacheHitTokens  int     `json:"cache_hit_tokens"`
	CacheMissTokens int     `json:"cache_miss_tokens"`
	OutputTokens    int     `json:"output_tokens"`
	ReasoningTokens int     `json:"reasoning_tokens"`
	CostUSD         float64 `json:"cost_usd"`
	SavedUSD        float64 `json:"saved_usd"`
}

Summary aggregates a set of entries.

func (Summary) CacheHitRate

func (s Summary) CacheHitRate() float64

CacheHitRate is the share of prompt tokens served from cache.

Jump to

Keyboard shortcuts

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