stats: API usage and cost

mito stats [OPTIONS]

stats tells you what mito has been doing to your AWS bill.

Every command records the S3 calls it makes. stats prints the running totals and estimates what they cost.

Options

FlagMeaning
--jsonMachine-readable output
--resetClear the counters and start again
-h, --helpHelp

The counts add up over time

The counters are cumulative and live on disk. So mito stats answers "what has this tool cost me so far", not "what did the last command cost".

If you want to measure one specific job, reset first:

mito stats --reset
mito diff ./data/ s3://my-bucket/data/
mito stats

For each kind of operation it tracks calls, successes, failures, retries, bytes up, bytes down, bytes moved server-side, and latency (average and worst).

Why the operation types look oddly specific

The types are split more finely than the S3 API names are, because the billing is split more finely:

TypeWhy it is separate
HeadObject, GetObjectGET-class pricing
PutObject, ListObjectsV2, ListBucketsPUT-class pricing, roughly 12x the GET price
DeleteObject, DeleteObjectsFree on AWS S3
UploadPartCopy, CopyObjectCopy inside one bucket. No data transfer charge
UploadPartCopyRemote, CopyObjectRemoteCopy between buckets. May cross regions, may cost transfer
CreateMultipartUpload, UploadPart, CompleteMultipartUpload, AbortMultipartUploadMultipart lifecycle
ListParts, ListMultipartUploads, GetBucketLocationMetadata calls

The same-bucket versus cross-bucket split is decided by comparing the source bucket named in the copy header against the destination bucket. It matters because a same-bucket copy is priced as a request, while a cross-region one also moves data.

Where the prices come from

Built-in per-region defaults, compiled into the binary. Nothing is fetched.

   built-in per-region defaults  ──► cached on disk ──► estimate

Fetching live rates from the AWS Pricing API is not implemented (#106). There is a cache file with a 24-hour lifetime, but what it caches is the same built-in table, so it changes nothing today.

The practical consequence: the rates are a snapshot someone typed in, not what AWS is charging you this month. They will drift.

mito stats --json
{
  "total": {
    "calls": 0,
    "success": 0,
    "failures": 0,
    "retries": 0,
    "bytes_uploaded": 0,
    "bytes_downloaded": 0,
    "avg_latency_ms": 0.00
  },
  "operations": {},
  "cost_breakdown": {
    "requests_usd": 0.000000,
    "data_transfer_out_usd": 0.000000,
    "total_usd": 0.000000
  },
  "region": "us-east-1"
}

Treat the number as an estimate, not a bill

It only covers requests mito itself made. It knows nothing about:

  • storage costs
  • your negotiated pricing
  • free-tier allowances
  • traffic from anything else on the account

Its real value is comparative. Run a workload two ways and see which one made an order of magnitude fewer PUT-class calls. That comparison is reliable even when the dollar figure is not.

If you point mito at a non-AWS service, the call counts stay accurate and the dollars become meaningless, because everything is priced at AWS rates. See S3-compatible storage.

Where the state lives

See Files on disk.

--reset does not delete the metrics file. It clears the counters and writes an empty file over the top. If that write fails, the command says so and exits 1, rather than claiming a reset that did not happen. It leaves the pricing cache alone.