hur.st's bl.aagh

BSD, Ruby, Rust, Rambling

rtss

Relative Timestamps for Stuff

[rust]

rtss annotates its output with relative durations between consecutive lines and since program start.

Inspired by Kevin Burke's Golang tss, I thought it would be a fun exercise and a nice bit of Rust practice to implement something similar.

I'm fairly pleased with the result - it's considerably faster, running at hundreds of MB per second in my tests - and somewhat more featureful, including pty support, allowing it to work similarly to expect's unbuffer command.

rtss on its own build

-% cargo build --release 2>&1 | rtss
 274.1ms  274.1ms |    Compiling libc v0.2.40
   1.50s    1.22s |    Compiling memchr v2.0.1
   2.28s  780.8ms |    Compiling rtss v0.5.0 (file:///home/freaky/code/rtss)
   5.18s    2.90s |     Finished release [optimized] target(s) in 5.17 secs
   5.18s    exit code: 0

Sortable output mode

-% rtss --sortable sh -c "echo foo; echo bar; sleep 1; echo moo >&2; sleep 1; echo baz; exit 64"
00:00:00.001652 00:00:00.001652 | foo
00:00:00.001652 00:00:00.000000 | bar
00:00:01.007287 00:00:01.007287 # moo
00:00:02.071962 00:00:02.070309 | baz
00:00:02.072185    exit code: 64

PTY mode

-% rtss zpool status 5
  10.01s   10.01s |   pool: rpool
  10.01s          |  state: ONLINE
  10.01s          |   scan: scrub repaired 0 in 1h7m with 0 errors on Wed May  2 04:00:38 2018

-% rtss --pty zpool status 5
   4.2ms    4.2ms |   pool: rpool
   4.2ms          |  state: ONLINE
   4.5ms    0.3ms |   scan: scrub repaired 0 in 1h7m with 0 errors on Wed May  2 04:00:38 2018

API

There's also a small library which provides a wrapper for any Write type. The command-line tool simply wraps this using io::copy().

use std::io::{self, Write};
use std::time::{Duration, Instant};

extern crate rtss;
use rtss::{RtssWriter, DurationExt};

fn main() -> io::Result<()> {
    let mut writer = RtssWriter::new(io::stdout(), Duration::human_string, '|', &Instant::now());
    writer.write(b"Hello!\n")?;
    writer.write(b"World!\n")?;
    Ok(())
}
   0.2μs    0.2μs | Hello!
  84.7μs   84.6μs | World!

Future

The most obvious direction to take rtss is making the output formatting more configurable—ideally with a custom template. I'd quite like to do this while maintaining the high performance if possible, which somewhat complicates matters.

tj is an example of the sort of thing I want to do—and an illustration of the performance cost of a naive approach. rtss runs at several hundred MB per second, tj barely breaks 5.