Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

lpchart

Chart InfluxDB line protocol in your terminal, without knowing what's in the file first.

lpchart browsing a line protocol file

Line protocol already tells you everything about itself: the measurements, the tag keys, the tag values, the field names, the types. So why does every charting tool make you head the file and pass the answers back in as flags?

lpchart reads that structure and hands it to you as something you can walk with the arrow keys. Point it at a file and a chart is already on screen.

lpchart metrics.lp

That's the whole invocation. No -m, no -f, no piping through jq first.

Why this exists

Line protocol looks like this:

cpu,host=web01,region=us-east usage_idle=69.023,usage_user=28.000 1755000000000000000

One line, two tags, two fields, one timestamp. In InfluxDB terms that line belongs to two different series, because usage_idle and usage_user each get their own, and the tag set is what separates web01 from web02.

Every terminal charting tool expects you to have flattened that into columns before you arrive. YouPlot, termgraph, asciigraph and incplot are all excellent, all CSV-shaped or JSON-shaped, and none of them know what a tag set is. So you end up writing a throwaway awk script to turn tags into columns before you can look at anything, which is a strange amount of work to answer "did the number go up".

lpchart speaks line protocol natively. Fields fan out into series on their own. Tag sets become the things you toggle. Timestamps become a real time axis instead of a column of 19-digit integers.

Install

go install github.com/didvc/lpchart/cmd/lpchart@latest

Requires Go 1.25 or newer. The binary lands in $(go env GOPATH)/bin, so add that to your PATH if it isn't there already.

Or build from a clone:

git clone https://github.com/didvc/lpchart
cd lpchart
go build -o lpchart ./cmd/lpchart

There are no runtime dependencies. It's one static binary, and it works over SSH and inside tmux.

Quick start

Browse a file:

lpchart metrics.lp

Browse whatever a collector just produced:

telegraf --once 2>/dev/null | lpchart

Watch data as it arrives:

tail -f /var/log/metrics.lp | lpchart -F

Pull from InfluxDB and look at it:

influx query 'from(bucket:"telegraf") |> range(start:-1h)' --raw | lpchart

Get a chart into a file or a pipe, with no TUI involved:

lpchart metrics.lp > chart.txt
lpchart metrics.lp | less -R

The three views

Press v to cycle between them. All three show the same selection over the same time window, so you can go from a shape, to the exact numbers, to the original bytes without losing your place.

Chart

The default view. Unicode line art, one colour per series, a real time axis, and gaps where data is genuinely missing. It will not interpolate across a hole and pretend a reading was there.

Table

the table view

The numbers behind the chart: one row per timestamp, one column per series, colour-matched to the chart lines.

Rows are the union of every selected series' timestamps rather than any one series' own. Series in the same measurement rarely share a clock, and stacking them by row index would quietly misalign them. Where a series had no sample at some instant you get · instead of a made-up number.

Raw

the raw view

The actual source lines, with their original line numbers, filtered to the measurement you're looking at.

This shows the real input text rather than a re-encoding of whatever the parser produced. When a chart looks wrong, this is the view that tells you whether the tool is misreading the file or the file is genuinely strange, and it can only do that job if it shows you the file instead of its own opinion of the file.

Keys

Key Does
tab / Move between panes (measurement, field, series, data)
or j k Move within the focused pane
pgup / pgdn Page, in the table and raw views
home / end Jump to first or last
space Toggle a series on or off
enter Show only this series
a / n Select all, or none
v / V Next or previous view
A Cycle aggregation
w Cycle the time window
u Toggle UTC and local time
? Help
q Quit

How series are worked out

A series is one combination of measurement, tag set and field. That's the same definition InfluxDB uses, and it's why a single line carrying three numeric fields becomes three lines on the chart.

The three panes follow that structure directly:

measurement          field                series
  cpu     6·3,600      usage_idle  1,800    ■ web01 us-east   600
  mem     6·3,600      usage_user  1,800    ■ web02 us-east   600
  net     6·3,600                           ■ db01  eu-west   600
  health  3·90

Counts read as series·points for measurements, and points for fields and series.

Labels shrink to what matters

If every series on screen shares region=us-east, the region stops being mentioned, because it isn't telling you anything. Labels are recomputed for whatever subset is visible at the time, so you get web01 and web02 rather than two 40-character keys that differ in one place. If nothing distinguishes two series, the full key comes back, because two identical legend entries would be worse than a long one.

It opens on something

The browser picks the measurement with the most data, then its busiest field, and switches on up to six of its series. It never opens to an empty chart. Moving to a different measurement or field picks again. Once you toggle something by hand, your selection is left alone.

Timestamps

Line protocol carries an integer and no indication of its unit. lpchart infers the unit from the magnitude, choosing between seconds, milliseconds, microseconds and nanoseconds, and shows you which one it settled on in the header as ts=ns. Override it when the guess is wrong:

lpchart -p ms metrics.lp

Times display in your local zone by default. Press u for UTC, or start with --utc. The axis and the caption always agree, so you'll never get a chart labelled in one zone and captioned in another.

Lines with no timestamp are stamped with their arrival time, which is what InfluxDB would do with them.

What can and can't be charted

Field type Result
float, integer, unsigned Plotted
boolean Plotted as 0 and 1, so status flags line up with gauges
string Skipped, since there's no y position for "degraded"

Skipped strings are counted and reported in the header rather than silently dropped, so "why is this measurement empty" has an answer on screen:

! 90 string fields are not chartable

Aggregation

When more samples land in one column than the terminal has room for, they have to be combined somehow. Which way is right depends on the metric, so A cycles through the options.

mean is the default and suits rates and utilisation. last is usually right for a gauge. max and min suit latency, or finding the spike you came to look at. sum and count suit counters and event rates.

If a spike matters and mean is smoothing it away, press A until you reach max.

Command line

Everything below is optional. The flags pre-seed the browser, or drive lpchart from a script. None of them are required to look at a file.

Usage:
  lpchart [flags] [file ...]
  ... | lpchart [flags]

Choosing data

Flag Does
-m, --measurement Only these measurements (repeatable)
-f, --field Only these fields (repeatable)
-t, --tag key=value Only points with this tag (repeatable, all must match)
--by key,key Build series from these tag keys only, merging the rest
--max-series Cap on series drawn in one-shot mode, default 12

Time

Flag Does
--last 5m Keep only the last stretch of data
--since, --until Bound the window (RFC3339, or 2006-01-02 15:04)
-p, --time-precision auto, ns, us, ms, s
--utc Show UTC instead of local time

Output

Flag Does
-W, --width, -H, --height Chart size, defaulting to your terminal
-a, --agg mean, last, min, max, sum, count
--color auto, always, never
--decimals Decimal places on the y axis

Modes

Flag Does
-F, --follow Keep reading and redraw as lines arrive
-l, --list List the series found, then exit
-s, --stats Per-series summary table of min, mean, max and last
--plot Force a one-shot chart
--tui Force the browser even when output is redirected
--skip-errors Keep going past malformed lines

It behaves like a normal unix filter

When output isn't a terminal, whether that's redirected to a file, piped into less, or run from a script, lpchart prints one chart and exits instead of opening the browser. You don't have to remember a flag for it.

lpchart metrics.lp > chart.txt
lpchart --stats metrics.lp | column -t
lpchart --list metrics.lp

Recipes

What is in this file?

lpchart --list metrics.lp

Compare one field across hosts, ignoring every other tag:

lpchart -m cpu -f usage_idle --by host metrics.lp

Only the last five minutes, in the browser:

lpchart --last 5m metrics.lp

Watch a live agent:

while :; do telegraf --once 2>/dev/null; sleep 10; done | lpchart -F

Chart a single number over time from anything. Any tool that can emit name value=<n> per line works, with no tags and no timestamps needed:

while :; do
  echo "ping value=$(ping -c1 1.1.1.1 | grep -oP 'time=\K[\d.]+')"
  sleep 1
done | lpchart -F

Drop a chart into a commit message or an issue:

lpchart --color never -W 72 -H 12 metrics.lp

Limits worth knowing

-F truly streams only from stdin. Given a file it reads to the end and stops, rather than tailing the file for you. Pipe tail -f in instead.

The raw view keeps the most recent 20,000 lines. Files smaller than that show completely. Past it you get the newest lines, and the header tells you how many scrolled off, which is the end you want when following something live.

The browser loads up to 5,000 series as a memory guard. Filter with -m, -f or -t if your tag cardinality runs above that.

--by applies to one-shot mode only. Inside the browser, series identity is always the full tag set.

--since, --until and --max-series likewise apply to one-shot mode. The browser uses w for its time window.

Troubleshooting

"no input" means nothing arrived on stdin and no file was named.

"found N fields, all of them strings" means the measurement you selected has nothing numeric in it. Try another one, and the raw view will show you why.

Errors like "line 4: ..." point at a malformed line. Add --skip-errors to carry on and count them instead of stopping. The message names the line number so you can go and find it.

If the chart is a row of dots instead of a line, that's a bug. Grid resolution is supposed to follow the number of distinct timestamps in your data. Please open an issue with a sample.

If times look wrong by a few hours, you're probably reading local time and expecting UTC. Press u.

If colours look wrong or absent, --color always forces them on for pipes and --color never turns them off. NO_COLOR is respected.

Built on

lpchart is a thin layer over some very good libraries, and deliberately so:

Contributing

Issues and pull requests are welcome. If you're reporting a rendering problem, a few lines of sample line protocol help enormously, and the raw view exists partly so you can copy them straight out.

go test ./...
go test -race ./...
go vet ./...

Follow mode is concurrent, so the race detector matters when touching it.

Licence

BSD 3-Clause. See LICENSE.


Related projects

  • nimo — nano-inspired terminal text editor written in pure Nim.
  • crypto-charts — Terminal crypto price charts: top coins and price history from the free CoinGecko API (Go, Bubble Tea)
  • algebra-visual — Live terminal function grapher: plot y = f(x) as you type (Go, Bubble Tea, ntcharts)
  • dir-cpu — Real-time CLI that shows CPU usage aggregated by filesystem directory

About

Chart InfluxDB line protocol in your terminal. Browse measurements, fields and tag sets interactively without knowing what is in the file first.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages