plox β Time Plots from Logs
π What It Does
You give it logs. It gives you a graph.
Turn timestamped logs into clean plots. Extract numeric values from log files and plot them over time. Fully CLI-driven. Regex-based. Configurable.
For some examples refer to sample gallery.
β¨ Features
- Regex-based field extraction with optional fast line filtering,
- Flexible timestamp parsing and unit-aware number handling,
- Compose multi-panel layouts to separate and group related metrics,
- Multiple input logs with per-file layouts and panel duplication support,
- Supports:
- Numeric value plotting,
- Fixed-value markers on event (pattern) match,
- Cumulative event counting,
- Time deltas between events,
- Reusable graph layouts via TOML config files
- Outputs PNGs (via gnuplot) and per-line CSV caches for fast redraws
π§ͺ Example
plox graph \
--input tests/examples/some.log \
--output tests/.output/panels.png \
--timestamp-format "[%s]" \
--plot om_module x \
--panel \
--plot x_module x01 \
--plot x_module x02 \
--plot x_module x03 \
--panel \
--event-count foo_module SOME_EVENT \
--event foo_module SOME_EVENT 1.0 --yaxis y2 --style points
For more examples refer to sample gallery.
π¦ Install
or
# use ./target/release/plox
gnuplot is required for rendering PNGs β install it via your system package manager.
π Case Study
This section walks through a real-world example of using plox to build a graph configuration progressively via the CLI β starting with a single metric, layering in more complexity, and finally extracting it into a reusable config.
Some log
|
) a=1 i=6 views=[(37, 15000, 0)] event=NewBestBlock { }
) a=2 i=4 views=[(37, 60712, 0), (39, 55211, 0)] event=NewBestBlock { }
) a=2 i=4 views=[(37, 61031, 0), (40, 53840, 0)] event=NewBestBlock { }
) a=2 i=5 views=[(37, 73804, 0), (41, 64216, 0)] event=NewBestBlock { }
) a=2 i=5 views=[(37, 73804, 0), (42, 61819, 0)] event=NewBestBlock { }
) a=1 i=5 views=[(43, 64088, 0)] event=NewBestBlock { }
π₯οΈ CLI Workflow
A sequence of plox graph commands that evolve from a simple one-liner to a complete multi-panel, multi-metric graph.
# basic plot: extract one value from logs
# add another value: prune duration
# split into separate panels for clarity
# switch to points with marker size
# write a graph config file (too complex for cli - file editing becomes more convenient)
# try to extract first number from 'txs=(.., ..)' in 'maintain...' lines:
# edit/iterate the config, extract more data
# compare to another run
# apply same config to multiple files with per-file layout
π Graph Config
Once the command-line version becomes too complex to maintain comfortably, the configuration can be saved to a TOML file using -w <graph-config-file>. This creates a declarative layout thatβs easy to version, inspect, and edit.
Below is a sample graph configuration representing where we eventually land in the case study. Itβs functionally identical to the CLI commands above but significantly easier to maintain as the graph grows.
[[]]
[[]]
= "prune:"
= "validated_counter"
= "points"
= 3.0
= "dot"
= "red"
= "validation count in prune"
[[]]
= "prune"
= 'took:([\d\.]+)(\w+)?'
= "points"
= 3.0
= "cross"
= "blue"
= "prune duration [y2][ms]"
= "y2"
[[]]
= "txs"
= true
[[]]
= "maintain"
= 'txs=\((\d+),\s+\d+\)'
= "steps"
= "red"
="watched txs"
[[]]
= "maintain"
= 'txs=\(\d+,\s+(\d+)\)'
= "steps"
= "blue"
=2
="unwatched txs"
π Working with Multiple Log Files
Multiple input logs can be passed via --input:
By default, each line (plot, event, etc.) is applied to all input files β unless it is bound to a specific file.
π Binding a Line to a Specific File
To target a specific log file:
- Use
--file-id <N>to refer to the Nth file in--input - Or use
--file-name <path>to bind directly to a filename
# apply this line only to c.log:
# apply this line to global-errors.log which is not used in --input:
β Without Binding, Lines Apply to All Inputs
If --file-id or --file-name is not set, the line is applied to every file in --input.
This is useful if comparing logs from the same system.
π Panel Duplication
Use --per-file-panels to separate outputs per input log, which may improve readability of the graph.
This flag automatically duplicates each panel once per input file, if that panel includes any unbound lines. Then, it resolves each unbound line to exactly one input.
How it works
- Unbound lines (no
file-idorfile-name) β assigned to exactly one file per duplicated panel - Bound lines β copied into all panels unchanged
- Each final panel = one log file + one consistent layout
Why it matters
This makes it easy to apply a single graph layout across multiple logs, with clean isolation:
Results in:
| Panel | Line | File |
|---|---|---|
| 0 | duration |
a.log |
| 0 | ERROR (explicit file-name) |
e.log |
| 1 | duration |
b.log |
| 1 | ERROR (explicit file-name) |
e.log |
This lets applying the same layout to multiple inputs while keeping shared reference lines intact.
π Time Ranges and Alignment
Each panel computes its own time range by merging the time spans of all its lines. This behavior is controlled by --time-range-mode, which determines whether the panel uses the full union or only the overlapping portion of its lines.
The X-axis range across panels can then be left independent or aligned globally. This is configured using --panel-alignment-mode.
If --time-range is provided, it overrides all automatic range calculation and applies a fixed global time window to all panels. Useful for "zooming" some interesting area.
π§ Full CLI Reference
See plox --help for a complete list of options.
π Output Files
Running plox graph generates:
pngβ rendered plot in given location (default:graph.png, or via--output)gnuplotβ generated script (same location and name as PNG)- CSV cache per log file (default:
.plox/next to the log file), can be controlled by--cache-dir,
Regenration of CSV cache can be forced with --force-csv-regen flag.
Additionally the output PNG can be saved next to the input log file (if one log), or to in a common parent directory (if multiple input files are given) if --inline-output <FILE> is used.
π§ Status
Actively under development β feedback welcome!
π License
Licensed under either of:
- MIT License
- Apache License 2.0
at your option.