├── runX ├── notes ├── run-cron └── index.html.tmpl ├── titles.example ├── .gitignore ├── bin ├── loop ├── mul ├── copy-to-website.example ├── copy-logfiles.example ├── percentile ├── minmax ├── cumulative ├── linlogytics ├── skew-graph ├── diff-freq-graph ├── snr-hourly ├── foreach-stat ├── split ├── histogram ├── linscalelimit ├── graph-header ├── histogram-snr ├── timestamps ├── index ├── run ├── offset-graph ├── local-clock-graph └── plot ├── LICENSE └── README.md /runX/notes: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /titles.example: -------------------------------------------------------------------------------- 1 | statistics.SET_IP_HERE hostname 2 | -------------------------------------------------------------------------------- /runX/run-cron: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd `dirname ${0}` 4 | ../bin/run 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/copy-to-website 2 | bin/copy-logfiles 3 | titles 4 | run[0-9]* 5 | -------------------------------------------------------------------------------- /bin/loop: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while :; do 4 | ../bin/run 5 | sleep 3500 6 | done 7 | -------------------------------------------------------------------------------- /bin/mul: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | my $number = shift; 4 | 5 | print $number * <>; 6 | print "\n"; 7 | -------------------------------------------------------------------------------- /bin/copy-to-website.example: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rsync --delete -avP *.png *.html ~/my.www.dir/html/graphs/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This code is in the public domain, feel free to do whatever you like with it. 2 | 3 | Of course, this means it comes with no warranty or guarantees 4 | -------------------------------------------------------------------------------- /bin/copy-logfiles.example: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd log-chrony || exit 1 4 | rsync -avP --delete remoteserver.example.com:/var/log/chrony/ . 5 | 6 | # comment out the next two lines if you're not using the ntp app to log gps signals 7 | cd ../log || exit 1 8 | rsync -avP remoteserver.example.com:/var/log/ntp-app/ . 9 | -------------------------------------------------------------------------------- /bin/percentile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my $column = shift; 6 | my $percentile = shift; 7 | 8 | my(@data); 9 | while(<>) { 10 | my(@columns) = split(/ +/); 11 | push(@data, $columns[$column]); 12 | } 13 | 14 | @data = sort {$a <=> $b} @data; 15 | my $offset = int(scalar(@data) * ($percentile/100)); 16 | print $data[$offset],"\n"; 17 | -------------------------------------------------------------------------------- /bin/minmax: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my $column = shift; 6 | my $minmax = shift; 7 | 8 | my(@data); 9 | while(<>) { 10 | my(@columns) = split(/ +/); 11 | push(@data, $columns[$column]); 12 | } 13 | 14 | @data = sort {$a <=> $b} @data; 15 | my $offset = 0; 16 | if($minmax eq "max") { 17 | $offset = -1; 18 | } 19 | print $data[$offset],"\n"; 20 | -------------------------------------------------------------------------------- /bin/cumulative: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my($column) = shift; 6 | my($step) = shift; 7 | 8 | my(@data); 9 | while(<>) { 10 | my(@columns) = split(/ +/); 11 | push(@data, $columns[$column]); 12 | } 13 | 14 | @data = sort {$a <=> $b} @data; 15 | for(my $pct = 0; $pct < 100; $pct += $step) { 16 | my $offset = int(scalar(@data) * ($pct/100)); 17 | printf("%0.1f %s\n", $pct,$data[$offset]); 18 | } 19 | -------------------------------------------------------------------------------- /bin/linlogytics: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my $linscalelimit = shift; 6 | 7 | for (my $i = 1000000; $i >= 1; $i /= 10) 8 | { 9 | printf "%f, ", -($linscalelimit * $i); 10 | } 11 | 12 | printf "%f, ", -($linscalelimit * 0.5); 13 | printf "%f, ", 0; 14 | printf "%f, ", ($linscalelimit * 0.5); 15 | 16 | for (my $i = 1; $i <= 1000000; $i *= 10) 17 | { 18 | printf "%f, ", ($linscalelimit * $i); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /bin/skew-graph: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LINSCALELIMIT=1 4 | for stat in statistics.*; do 5 | LINSCALELIMIT=`../bin/linscalelimit $LINSCALELIMIT 5 $stat` 6 | echo $stat $LINSCALELIMIT 7 | done 8 | LINSCALELIMIT=`echo $LINSCALELIMIT | ../bin/mul 1000000` 9 | 10 | ( 11 | ../bin/graph-header all-skew.png $LINSCALELIMIT "%1.1f us/s" "all clocks (skew)" "set yrange [-10:10]" 12 | ../bin/foreach-stat "'__FILE__' using 1:(\$6*1000000) title '__TITLE__' with line \\" 13 | echo 14 | ) | gnuplot 15 | -------------------------------------------------------------------------------- /bin/diff-freq-graph: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LINSCALELIMIT=1 4 | for stat in statistics.*; do 5 | LINSCALELIMIT=`../bin/linscalelimit $LINSCALELIMIT 5 $stat` 6 | echo $stat $LINSCALELIMIT 7 | done 8 | LINSCALELIMIT=`echo $LINSCALELIMIT | ../bin/mul 1000000` 9 | 10 | # echo $LINSCALELIMIT 11 | 12 | ( 13 | ../bin/graph-header all-diff-freq.png $LINSCALELIMIT "%1.1f us/s" "all clocks (diff freq)" "set yrange [-3:3]" 14 | ../bin/foreach-stat "'__FILE__' using 1:(\$6*1000000) title '__TITLE__' with line \\" 15 | echo 16 | ) | gnuplot 17 | -------------------------------------------------------------------------------- /bin/snr-hourly: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | while(<>) { 6 | chomp($_); 7 | my($timestamp,$snr_data) = /^(\d+) (.*)/; 8 | my(@line) = split(/, /,$snr_data); 9 | my(%counts); 10 | for(my $i = 0; $i < @line; $i++) { 11 | if($line[$i] =~ /^(\d*):(\d+)$/) { 12 | my($snr,$count) = ($1,$2); 13 | if($snr > 0) { 14 | $counts{"+1"} += $count; 15 | } else { 16 | $counts{-1} += $count; 17 | } 18 | } else { 19 | print STDERR "$0 unknown part: $_\n"; 20 | } 21 | } 22 | print $timestamp," ",$counts{"-1"}," ",$counts{"+1"},"\n"; 23 | } 24 | -------------------------------------------------------------------------------- /bin/foreach-stat: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TEMPLATE=$1 4 | if [ -z "$TEMPLATE" ]; then 5 | echo need template 6 | exit 1 7 | fi 8 | 9 | i=0 10 | for stat in statistics.*; do 11 | date=`tail -1 $stat | cut -d" " -f1` 12 | echo $date $stat 13 | done | grep -v NMEA | sort -n | while read date file; do 14 | title=`grep "^$file " ../titles 2> /dev/null | cut -d" " -f2` 15 | if [ -z "$title" ]; then 16 | title=${file#statistics.} 17 | fi 18 | if [ $i != 0 ]; then 19 | echo -n , 20 | else 21 | i=1 22 | fi 23 | echo $TEMPLATE | sed -e "s/__FILE__/$file/g" -e "s/__TITLE__/$title/g" 24 | done 25 | -------------------------------------------------------------------------------- /bin/split: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my $filename = shift; 6 | if(not defined $filename) { 7 | die("I need an output filename"); 8 | } 9 | my $alias_file = shift; 10 | my(%aliases); 11 | if(-f $alias_file) { 12 | open(ALIAS,"<",$alias_file); 13 | while() { 14 | if(/(\S+) (\S+)/) { 15 | $aliases{$1} = $2; 16 | } 17 | } 18 | close(ALIAS); 19 | } 20 | 21 | while(<>) { 22 | if(/^(\d+) (\S+)/) { 23 | my($host) = $2; 24 | if(defined($aliases{$host})) { 25 | $host = $aliases{$host}; 26 | } 27 | open(OUT,">>$filename.$host"); 28 | print OUT $_; 29 | close(OUT); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /bin/histogram: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my($column) = shift; 6 | my($multiply) = shift; 7 | 8 | my(%counts); 9 | while(<>) { 10 | chomp($_); 11 | my(@line) = split(/ +/); 12 | my $data = $line[$column]; 13 | if(length($multiply)) { 14 | $data = int($data * $multiply); 15 | } 16 | $counts{$data}++; 17 | } 18 | 19 | my($last_count); 20 | foreach my $count (sort { $a <=> $b } keys %counts) { 21 | if(defined($last_count) and $last_count+1 != $count) { 22 | print(($last_count+1)." 0\n"); 23 | if(defined($last_count) and $last_count+2 != $count) { 24 | print(($count-1)." 0\n"); 25 | } 26 | } 27 | $last_count = $count; 28 | print $count," ",$counts{$count},"\n"; 29 | } 30 | -------------------------------------------------------------------------------- /bin/linscalelimit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my $prevlimit = shift; 6 | my $column = shift; 7 | 8 | my(@data); 9 | while(<>) { 10 | my(@columns) = split(/ +/); 11 | push(@data, abs($columns[$column])); 12 | } 13 | 14 | my $percentile = 50; 15 | 16 | @data = sort {$a <=> $b} @data; 17 | my $offset = int(scalar(@data) * ($percentile/100)); 18 | my $limit = $data[$offset]; 19 | if ($limit == 0) { $limit = 1; printf STDERR "FORCE LIMIT 1 (avoid log(0))\n"; } 20 | # This takes us to the next power of 10: 21 | my $linscalelimit = 10**int(log($limit)/log(10)+1); 22 | # But scale down to 5 or 2 23 | if ($linscalelimit / 2 > $limit) { 24 | $linscalelimit /= 2; 25 | } 26 | if ($linscalelimit / 2.5 > $limit) { 27 | $linscalelimit /= 2.5; 28 | } 29 | 30 | if ($linscalelimit > $prevlimit) { 31 | $linscalelimit = $prevlimit; 32 | } 33 | 34 | print $linscalelimit,"\n"; 35 | -------------------------------------------------------------------------------- /bin/graph-header: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FILENAME=$1 4 | LINSCALELIMIT=$2 5 | FORMAT=$3 6 | TITLE=$4 7 | CUSTOM=$5 8 | 9 | YTICS=`../bin/linlogytics $LINSCALELIMIT` 10 | 11 | #echo $LINSCALELIMIT 1>&2 12 | #echo $YTICS 1>&2 13 | 14 | cat < \$cdf) 8 | or die("Error in command line arguments\n"); 9 | 10 | 11 | my(%counts); 12 | while(<>) { 13 | chomp($_); 14 | s/^\d+ //; 15 | my(@line) = split(/, /); 16 | for(my $i = 0; $i < @line; $i++) { 17 | if($line[$i] =~ /^(\d*):(\d+)$/) { 18 | my($snr,$count) = ($1,$2); 19 | if($snr ne "") { 20 | $counts{$snr} += $count; 21 | } else { 22 | $counts{-1} += $count; 23 | } 24 | } else { 25 | print STDERR "$0 unknown part: $_\n"; 26 | } 27 | } 28 | } 29 | 30 | if($cdf) { 31 | my($sum) = 0; 32 | my(%bins); 33 | foreach my $count (sort { $a <=> $b } keys %counts) { 34 | $sum += $counts{$count}; 35 | $bins{$count} = $sum; 36 | } 37 | foreach my $count (sort { $a <=> $b } keys %bins) { 38 | print "$count ",($bins{$count}/$sum*100),"\n"; 39 | } 40 | } else { 41 | foreach my $count (sort { $a <=> $b } keys %counts) { 42 | print $count," ",$counts{$count},"\n"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /runX/index.html.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | NTP Run __RUN__ - __THISHOST__ 4 | 5 | 6 | 7 | 8 |

9 | Last update - __TIME__ GMT 10 |

11 | Local Clock: Frequency + Offset
12 | Local Clock: Frequency detail
13 | Local Clock: Offset detail
14 | Local Clock: Offset histogram
15 | Local Clock: Skew
16 | Local Clock: stddev
17 | Remote Clocks: Frequency Difference
18 | Remote Clocks: Offsets
19 | Remote Clocks: Skew
20 | __ALL_REMOTES__ 21 |
22 | __RUN__ notes:
23 | __NOTES__
24 | 
25 |

26 | Git repository for chrony-graph: 27 | https://github.com/ddrown/chrony-graph 28 |

29 | 30 | -------------------------------------------------------------------------------- /bin/timestamps: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | { 6 | package DateToEpoch; 7 | 8 | use strict; 9 | use DateTime; 10 | 11 | sub new { 12 | bless({}, $_[0]); 13 | } 14 | 15 | sub date_to_epoch { 16 | my($self,%date) = @_; 17 | 18 | if(not defined $self->{dt}) { 19 | $self->{dt} = DateTime->new(%date, time_zone => "UTC"); 20 | $self->{epoch} = $self->{dt}->epoch(); 21 | $self->{last_time} = \%date; 22 | return $self->{epoch}; 23 | } 24 | 25 | my(%set); 26 | foreach my $key (qw(year month day)) { 27 | if($date{$key} != $self->{last_time}{$key}) { 28 | $set{$key} = $date{$key}; 29 | $self->{last_time}{$key} = $date{$key}; 30 | } 31 | } 32 | if(%set) { 33 | $self->{dt}->set(%set); 34 | $self->{epoch} = $self->{dt}->epoch(); 35 | } 36 | 37 | my $offset = ($date{hour} - $self->{last_time}{hour}) * 60*60 + 38 | ($date{minute} - $self->{last_time}{minute}) * 60 + 39 | ($date{second} - $self->{last_time}{second}); 40 | return $self->{epoch} + $offset; 41 | } 42 | } 43 | 44 | my($dte) = new DateToEpoch(); 45 | my(@order) = qw(year month day hour minute second); 46 | while(<>) { 47 | if(/^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}) (.*)/) { 48 | my $text = $7; 49 | my(%this_time); 50 | @this_time{@order} = ($1,$2,$3,$4,$5,$6); 51 | my $epoch = $dte->date_to_epoch(%this_time); 52 | $text =~ s/([0-9.]+e[+-][0-9]+)/sprintf("%0.9f",$1)/eg; 53 | if($epoch > time()+300) { # nothing in the future 54 | $epoch = 0; 55 | } 56 | print "$epoch $text\n"; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /bin/index: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Cwd; 5 | use File::Basename; 6 | use Sys::Hostname; 7 | 8 | sub read_hash { 9 | my $fn = shift; 10 | my $hash = shift; 11 | open(my $fh, '<', $fn) or return; 12 | while (my $line=<$fh>) { 13 | chomp($line); 14 | my ($key, $value) = split / /, $line, 2; 15 | $hash->{$key} = $value; 16 | } 17 | close($fh); 18 | } 19 | 20 | my %titles = (); 21 | read_hash('../titles.common', \%titles); 22 | read_hash('../titles', \%titles); 23 | 24 | my $RUN=cwd(); 25 | $RUN = basename($RUN); 26 | 27 | open(NOTES,"<","notes"); 28 | my $NOTES=join("",); 29 | close(NOTES); 30 | $NOTES =~ s//>/g; 32 | $NOTES =~ s/&/&/g; 33 | 34 | my $time = scalar(gmtime()); 35 | 36 | my $THISHOST = $ENV{THISHOST} // hostname(); 37 | my $FREQ = $ENV{FREQ}; 38 | 39 | my @remotes = glob("remote-statistics.*.{svg,png}"); 40 | my $ALL_REMOTES = ""; 41 | my $ALL_REMOTES_WITH_LINK = ""; 42 | foreach my $r (@remotes) { 43 | my $remote = $r; 44 | $remote =~ s/^remote-statistics\.//; 45 | $remote =~ s/\.(svg|png)$//; 46 | my $key = $remote; 47 | $key =~ s/_/:/g; 48 | my $desc = $titles{"statistics.$key"} || $key; 49 | my $img = "\"Remote"; 50 | $ALL_REMOTES .= "$img
\n"; 51 | $ALL_REMOTES_WITH_LINK .= "$img
\n"; 52 | } 53 | 54 | open(TMPL,"<","index.html.tmpl"); 55 | while() { 56 | s/__RUN__/$RUN/g; 57 | s/__NOTES__/$NOTES/g; 58 | s/__TIME__/$time/g; 59 | s/__THISHOST__/$THISHOST/g; 60 | s/__FREQ__/$FREQ/g; 61 | s,__ALL_REMOTES__,$ALL_REMOTES,g; 62 | s,__ALL_REMOTES_WITH_LINK__,$ALL_REMOTES_WITH_LINK,g; 63 | print; 64 | } 65 | -------------------------------------------------------------------------------- /bin/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -x startime ]; then 4 | STARTIME=`./startime` 5 | else 6 | NOW=`date +%s` 7 | # 604800 seconds = 7 days 8 | STARTIME=`expr $NOW - 604800` 9 | fi 10 | 11 | LOGDAYS=7 12 | if [ -n "$CHRONY_LOGDIR" ]; then 13 | LOGDIR=$CHRONY_LOGDIR 14 | else 15 | LOGDIR=/var/log/chrony 16 | fi 17 | 18 | if [ -x ../bin/copy-logfiles ]; then 19 | test -d log-chrony || mkdir log-chrony 20 | test -d log || mkdir log 21 | ../bin/copy-logfiles 22 | LOGDIR=log-chrony 23 | fi 24 | 25 | function limit_time { 26 | awk '{if($1 > '$STARTIME') { print }}' 27 | } 28 | 29 | function cat_logfiles { 30 | file_pattern="$1" 31 | 32 | find $LOGDIR -name "$file_pattern" \! -name \*.gz -mtime -$LOGDAYS | xargs -r cat 33 | # un-comment this next line if you compress your logs 34 | # find $LOGDIR -name "$file_pattern".gz -mtime -$LOGDAYS | xargs -r zcat 35 | } 36 | 37 | rm -f statistics* 38 | echo statistics.log `date` 39 | # split the statistics logs based on the source IP 40 | cat_logfiles statistics.log\* | ../bin/timestamps | limit_time | sort -n | ../bin/split statistics ../aliases 41 | 42 | rm -f measurements.* 43 | echo measurements.log `date` 44 | # measurements logs - also split based on source IP 45 | cat_logfiles measurements.log\* | ../bin/timestamps | limit_time | sort -n | ../bin/split measurements ../aliases 46 | 47 | echo tracking.log `date` 48 | # local clock info goes in one logfile 49 | cat_logfiles tracking.log\* | ../bin/timestamps | limit_time | sort -n >tracking.log 50 | 51 | echo done `date` 52 | 53 | # optional GPS log processing 54 | if [ -f log/gps-lock ]; then 55 | sed 's/ \([0-9]\+:[0-9]\+\) / \1:00 /' gps-lock 56 | fi 57 | if [ -f log/snr-history ]; then 58 | sed 's/ \([0-9]\+:[0-9]\+\) / \1:00 /' snr-history 59 | fi 60 | 61 | if [ -f log/gps-lock2 ]; then 62 | sed 's/ \([0-9]\+:[0-9]\+\) / \1:00 /' gps-lock2 63 | fi 64 | if [ -f log/snr-history2 ]; then 65 | sed 's/ \([0-9]\+:[0-9]\+\) / \1:00 /' snr-history2 66 | fi 67 | 68 | rm -f remote-statistics.* 69 | ../bin/plot 70 | ../bin/index >index.html 71 | ../bin/copy-to-website 72 | -------------------------------------------------------------------------------- /bin/offset-graph: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LINSCALELIMIT=1 4 | for stat in statistics.*; do 5 | LINSCALELIMIT=`../bin/linscalelimit $LINSCALELIMIT 3 $stat` 6 | echo $stat $LINSCALELIMIT 7 | done 8 | LINSCALELIMIT=`echo $LINSCALELIMIT | ../bin/mul 1000000` 9 | 10 | ( 11 | ../bin/graph-header all-offset.png $LINSCALELIMIT "%1.0f us" "all clocks (offset)" "" 12 | ../bin/foreach-stat "'__FILE__' using 1:(\$4*1000000) title '__TITLE__' with line \\" 13 | echo 14 | ) | gnuplot 15 | 16 | if [ -f ../titles ]; then 17 | titles=$(cat ../titles) 18 | else 19 | titles=$( 20 | for stat in statistics.*; do 21 | echo $stat ${stat#statistics.} 22 | done 23 | ) 24 | fi 25 | 26 | #( 27 | # ../bin/graph-header remote-strat1.png 1 "%1.0f us" "offset of remote strat1s" "" 28 | # i=0 29 | # echo "$titles" | while read file title; do 30 | # if [ $i != 0 ]; then 31 | # echo -n , 32 | # else 33 | # i=1 34 | # fi 35 | # echo "'$file' using 1:(\$4*1000000) title '$title' with line \\" 36 | # done 37 | #) | gnuplot 38 | # 39 | #( 40 | # ../bin/graph-header remote-strat1-downstream.png 1 "%1.0f us" "offset-rtt/2 of remote strat1s" "" 41 | # i=0 42 | # echo "$titles" | while read file title; do 43 | # measurements_file=`echo $file | sed 's/^statistics/measurements/'` 44 | # if [ -f $measurements_file ]; then 45 | # if [ $i != 0 ]; then 46 | # echo -n , 47 | # else 48 | # i=1 49 | # fi 50 | # echo "'$measurements_file' using 1:((\$11-\$12/2)*1000000) title '$title' with line \\" 51 | # fi 52 | # done 53 | # echo 54 | #) | gnuplot 55 | 56 | echo "$titles" | while read file title; do 57 | imagename=`echo $file | sed 's/:/_/g'` 58 | measurements_file=`echo $file | sed 's/^statistics/measurements/'` 59 | # Run only (1) for existing files and (2) once, so `titles.*` can be a sub-/superset 60 | if [ -f "$file" -a ! -f "remote-${imagename}.png" -a ! -f "remote-${imagename}.svg" ]; then 61 | ( 62 | if [ -f $measurements_file ]; then 63 | FIFTY=`../bin/percentile 10 50 $measurements_file | ../bin/mul 1000000` 64 | CUSTOM="set label 1 gprintf('50%% = $FIFTY us',50) at graph 0.01,0.05 left front" 65 | LINSCALELIMIT=`../bin/linscalelimit 1 10 $measurements_file | ../bin/mul 1000000` 66 | ../bin/graph-header remote-${imagename}.png $LINSCALELIMIT "%1.0f us" "offset of $title" "$CUSTOM" 67 | echo "'$measurements_file' using 1:(\$11*1000000) title 'offset' with line, \\" 68 | echo "'$measurements_file' using 1:((\$11+\$12/2)*1000000) title 'offset+rtt/2' with line, \\" 69 | echo "'$measurements_file' using 1:((\$11-\$12/2)*1000000) title 'offset-rtt/2' with line, \\" 70 | echo "$FIFTY title '50th percentile'" 71 | else 72 | FIFTY=`../bin/percentile 3 50 $file | ../bin/mul 1000000` 73 | CUSTOM="set label 1 gprintf('50%% = $FIFTY us',50) at graph 0.01,0.05 left front" 74 | LINSCALELIMIT=`../bin/linscalelimit 1 3 $file | ../bin/mul 1000000` 75 | ../bin/graph-header remote-${imagename}.png $LINSCALELIMIT "%1.0f us" "offset of $title" "$CUSTOM" 76 | echo "'$file' using 1:(\$4*1000000) title 'offset' with line, \\" 77 | echo "$FIFTY title '50th percentile'" 78 | fi 79 | ) | gnuplot 80 | fi 81 | done 82 | -------------------------------------------------------------------------------- /bin/local-clock-graph: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LINSCALELIMIT=`../bin/linscalelimit 1 5 tracking.log | ../bin/mul 1000000` 4 | 5 | # echo $LINSCALELIMIT 6 | 7 | YTICS=`../bin/linlogytics $LINSCALELIMIT` 8 | 9 | gnuplot <tracking.log.history 88 | ../bin/histogram 5 1000000 tracking.log.history 89 | SEVENTYFIVE=`../bin/percentile 5 75 tracking.log | ../bin/mul 1000000` 90 | TWENTYFIVE=`../bin/percentile 5 25 tracking.log | ../bin/mul 1000000` 91 | 92 | gnuplot <snr-history.history 137 | #gnuplot <snr-history.hourly 150 | #gnuplot <