TinyStore

Command line / metrics

metrics

tinystore metrics reads and writes a store's metrics from a shell, with no SDK. names, read and aggregate read beside the program or server that holds the directory. ingest writes the Prometheus text that an exporter serves, or that a script prints, and delete removes a series; both write through the server that holds the directory, or start one.

sh
tinystore metrics ./data names
tinystore metrics ./data read ping_rtt_ms --where target=poland --since 1h
tinystore metrics ./data aggregate ping_rtt_ms --since 1h --every 10m --op max --by target
curl -s localhost:9100/metrics | tinystore metrics ./data ingest --label instance=web-1
tinystore metrics ./data delete ping_rtt_ms target=poland

See what a store holds

sh
tinystore metrics ./data names
tinystore metrics ./data names http_      # names that start with http_
ping_lost_total  counter      6 series  keep 30d    newest 2s ago
ping_rtt_ms      gauge        6 series  keep 30d    newest 2s ago

--json gives one object per name, with its unit, help and times in UTC. A store with many names prints the first 1000; the last line says which name --after starts the next page at.

Read samples

sh
tinystore metrics ./data read ping_rtt_ms --where target=poland --from 14:32 --to 14:33 --gaps 5s
ping_rtt_ms{target="poland"}   26 Oct 14:32–14:33 Europe/Moscow · 46 samples
  14:32:00   23.1
  14:32:01   22.9
  14:32:02   23.4
             · 15s without samples
  14:32:17   24.0
  • The first line of each series names it and the range that was read, in this machine's time zone. Without --since, --from or --to, read reads the last hour.
  • --from and --to take 14:30 for today, 2026-10-25T03:00 for a date, both in this machine's zone, or a time with its offset, such as 2026-10-25T00:00:00Z.
  • --where target=poland keeps the series whose label matches. Use status=500,502 for either value, env!=dev for neither, and host=api-* for a prefix. Give --where again for more labels.
  • --gaps 5s marks every place where a series had no sample for longer than five seconds. Without it, read guesses nothing about a series' step.
  • read prints 1000 samples at most, and says on stderr how many more there were. Narrow the range, or raise --limit.

--json prints one object per sample, its time in UTC:

json
{"labels":{"target":"poland"},"name":"ping_rtt_ms","time":"2026-10-26T11:32:00Z","value":23.1}

A value that JSON can't hold, NaN or an infinity, comes as text: "NaN", "+Inf", "-Inf". When --limit cut the output, the last line says how many samples it left out: {"more":2591000}.

Aggregate

sh
tinystore metrics ./data aggregate ping_rtt_ms --since 1h --every 10m --op max --by target
ping_rtt_ms max every 10m   26 Oct 13:40–14:40 Europe/Moscow
             finland   poland   sweden
  13:40:00      31.2     24.0     40.1
  13:50:00      30.8   1012.5     39.7
  • --op is count, sum, avg, min, max, increase, rate, delta, first, last, or p and a rank, such as p95.
  • --every 10m makes a bucket every ten minutes. Without it, the range is one bucket.
  • --by target makes a group, a column, per value of the label.
  • A terminal gets a table. When the columns don't fit, each bucket gets a line of its own. --json gives one object per bucket.

Write a scrape or a file

sh
curl -s localhost:9100/metrics | tinystore metrics ./data ingest --label instance=web-1
tinystore metrics ./data ingest --keep 30d < scrape.txt
wrote 1834 samples to ./data
  • ingest reads stdin to its end and writes every series of the text, or none. A line it cannot read fails the whole text, and the error names the line.
  • A sample that the text gives no time gets the time the text was read.
  • A name's kind comes from the text's # TYPE line. A name with no # TYPE is a gauge.
  • --label instance=web-1 adds a label to every series. Give it again for more labels.
  • --keep 30d sets how long each name of the text keeps its samples, as the SDKs' keep does.

A script can print the text itself. Each line is a name, its labels, a value and, if you have one, a time in milliseconds:

sh
printf 'ping_rtt_ms{target="poland"} 23.1 1793014320000\n' | tinystore metrics ./data ingest

Delete a series

sh
tinystore metrics ./data delete ping_rtt_ms target=poland
deleted ping_rtt_ms{target="poland"}

delete removes the one series whose labels are exactly the ones given, as the SDKs' delete does. A name alone names its series without labels, so delete ping_rtt_ms removes nothing from a metric whose series all have a target.

Who writes

Who holds ./dataWhat a write does
tinystore serve or an SDK's sidecarwrites through it
nothingstarts a sidecar, which stops 30 seconds after its last client, and says so
a program that opened it embeddedrefuses and exits 1
tinystore metrics ingest: started a server for ./data; it stops 30 s after the last client

Several commands can write at once: the first one starts the sidecar, and the others write through it. A program that opened the store embedded keeps it inside its own process, so no other process can write to it:

tinystore metrics ingest: a program holds ./data inside its own process, so no other process can write to it
  open it in that program with a sidecar, or let `tinystore serve ./data` hold it

A directory without a store is refused, and nothing is created in it. Run the program or tinystore serve there once to make the store.

Limits and defaults

WhatValue
a name's keep, when none given30 days
the largest text2 MiB, the largest message the server takes
a sidecar's idle time30 seconds after its last client
the wait for a server15 seconds to start, 10 for an answer

See also

  • Ingesting: the same writes from a program, and what the engine keeps.
  • status and logs: see which server holds a directory.

Edit this page on GitHub Updated 26 October 2026

esc
↑↓ navigate ↵ open ⇥ filter 0 results