2

I ended up writing a quick little script for this in NodeJS, but I was wondering if there was a utility you could feed text into which would prepend each line with some text -- in my specific case, the time elapsed in milliseconds since the start of the programm. Ideally, the use would be something like:

longrunningprocess | prepend-timestamp

This could help do some fast debugging.

This question looks very similar to Is there a Unix utility to prepend timestamps to stdin?, but is not the same, I would like to prepend milliseconds since the start of the program, not the current timestamp.

Here is my version using NodeJS:

#!/bin/env node

var moment = require("moment");
process.stdin.resume()

var fullData = "";
var t = +new Date();

process.stdin.on('data', function(data) {
  fullData += data;
  splitted = fullData.split("\n");
  splitted.forEach(function (part) {
    if (part === "" ) {
      return process.stdout.write("\n");
    }
    process.stdout.write( (+new Date() - t) + " " + part +  "\n");
  })
  fullData = splitted[splitted.length-1];
});

process.stdout.on('error', function(err) {
  if (err.code === 'EPIPE') return process.exit()
    process.emit('error', err)
});

Bonus points if the ANSI escapes are kept (eg to see the colors of the initial command),

It would be even better if the precision (eg number of decimals) could be configurable.

edi9999
  • 19,701
  • 13
  • 88
  • 127

2 Answers2

1

If you are on Linux, the ts command fits the bill.

If you only need resolution to the second, you can just use bash:

start=$SECONDS
longrunningprocess | while IFS= read -r line; do
    echo "$((SECONDS - start)): $line"
done

The $SECONDS variable gives you the number of seconds since the shell started. It's very useful for this kind of duration calculation.


OK, I didn't fully understand all your requirements. Here's a version with Perl:

atime () { 
    local precision="${1:-5}"
    perl -MTime::HiRes=time -sne '
        BEGIN {$start = time} 
        printf "%.${prec}f %s", (time - $start), $_
    ' -- -prec="$precision"
}

longrunningprocess | atime 3

Demo:

$ { echo foo; sleep 1; echo bar; } | atime
0.00010 foo
0.98499 bar
$ { echo foo; sleep 1; echo bar; } | atime 3
0.000 foo
0.980 bar
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • `ts '%.s'` works quite well, but do you have an idea of how I could have the time relative to the start of the command rather than relative to the 1970-01-01 ? (Eg have the first line be 0, and consecutive lines 0.001, ...) – edi9999 Mar 09 '16 at 17:05
  • The command you posted doesn't give relative time (for ts), and not the milliseconds precision (for your bash solution) – edi9999 Mar 10 '16 at 08:45
  • Hmm, I just realized that `ts` is actually implemented as a perl script using Time::HiRes. I've just reinvented it. – glenn jackman Mar 10 '16 at 14:55
1

I ended up using both ts to print the current timestamp with milliseconds and awk to calculate the difference:

#!/bin/sh
# atime <precision>

precision=${1:-"5"}
ts '%.s' |
awk -v p="$precision" 'NR == 1 {st = $1} {diff = $1 - st; sub(/^[[:digit:].]+ /,""); printf "%."p"f %s\n", diff, $0}'

For example

{  echo "foo" ; sleep 1 ; echo "bar" ; } | atime

Prints :

0.00000 foo
0.97711 bar
edi9999
  • 19,701
  • 13
  • 88
  • 127