[ntpsec commit] Implement and document JSON reporting in ntpfrob.

Eric S. Raymond esr at ntpsec.org
Wed Oct 14 13:33:26 UTC 2015


Module:    ntpsec
Branch:    master
Commit:    57172eea4b6c834ac597410a234a88008d117635
Changeset: http://git.ntpsec.org/ntpsec/commit/?id=57172eea4b6c834ac597410a234a88008d117635

Author:    Eric S. Raymond <esr at thyrsus.com>
Date:      Wed Oct 14 09:05:52 2015 -0400

Implement and document JSON reporting in ntpfrob.

---

 docs/includes/ntpfrob-body.txt | 28 +++++++++++++++++++++++++---
 ntpfrob/jitter.c               | 39 +++++++++++++++++++++++++++++++--------
 ntpfrob/main.c                 | 27 ++++++++++++++++++++-------
 ntpfrob/precision.c            | 31 +++++++++++++++++++------------
 ntpfrob/tickadj.c              | 14 +++++++++++---
 5 files changed, 106 insertions(+), 33 deletions(-)

diff --git a/docs/includes/ntpfrob-body.txt b/docs/includes/ntpfrob-body.txt
index 8daa2bd..971917a 100644
--- a/docs/includes/ntpfrob-body.txt
+++ b/docs/includes/ntpfrob-body.txt
@@ -27,16 +27,34 @@ Portions of it formerly traveled as `tickadj` and `ntptime`.
   Measure clock precision.
 `-s`::
   Check for stepback bug.
+`-j`::
+  Report in self-describing JSON.
 
 == Modes of operation ==
 
-Documentation for some of these functions is scanty. If you suspect
-you may need to use them, reading the source code may be wise.
+Documentation for some of these functions is scanty; this is a problem
+inherited from ancient days along with their code. If you suspect
+you may need to use them, reading the source code may be wise. If
+you believe you understand the code in more detail than any of
+these descriptions, please explain it to the {project-shortname}
+maintainers.
+
+Normally this tool reports in an eyeball-friendly unstructured text
+format. With the -j option (where applicable) it reports JSON records.
+Note that the -j option should be given before any mode option. 
+
+The reporting formats of this tool should be considered unstable;
+they may change as diagnostics are added or improved.  JSON
+reports will be kept forward-compatible through changes.
 
 === Clock tick adjustment ===
 
 The -A function reads your clock's tick rate in microseconds.  The -a
-function sets it. Both rely on the adjtimex(2) system call.
+function sets it. Both rely on the adjtimex(2) system call.  This
+mode finishes by tereporting the tick value and (if available) the
+tick adjustment value.
+
+The -j option is applicable to this mode.
 
 Tweaking your tick rate is almost never necessary on hardware new
 enough to have a fully POSIX.1-2001-conformant Unix.
@@ -50,6 +68,8 @@ hardware interrupt, usually in the range 10 us-1 ms. For those systems
 with microsecond counters the jitter is dominated only by the
 operating system.
 
+The -j option is applicable to this mode.
+
 === Pulse-per-second check ==
 
 The -p option shows whether the  PPS-API (RFC 2783 kernel
@@ -60,6 +80,8 @@ PPS interface) finds PPS on a specified device.
 The -e option measure the resolution of the system clock, watching how
 the current time changes as we read it repeatedly.
 
+The -j option is applicable to this mode.
+
 === Stepback bug check ===
 
 The -s option checks for a bug originally seen on IBM RS/6000 AIX
diff --git a/ntpfrob/jitter.c b/ntpfrob/jitter.c
index ba1e8b4..4ec5730 100644
--- a/ntpfrob/jitter.c
+++ b/ntpfrob/jitter.c
@@ -15,10 +15,13 @@
 #include <stdio.h>
 #include <sys/time.h>
 #include <stdlib.h>
+#include <stdbool.h>
+
 #include "ntp_fp.h"
 
 #define NBUF	800002
 #define JAN_1970 2208988800UL		/* Unix base epoch */
+#define NSAMPLES 10
 
 char progname[10];
 double sys_residual;
@@ -58,7 +61,7 @@ get_clocktime(
 	now->l_uf = (uint32_t)dtemp;
 }
 
-void jitter(void)
+void jitter(const bool json)
 {
 	l_fp tr;
 	int i, j;
@@ -101,13 +104,33 @@ void jitter(void)
 		}
 	}
 	average = average / (NBUF - 2);
-	fprintf(stderr, "Average %13.9f\n", average);
-	fprintf(stderr, "First rank\n");
-	for (i = 0; i < 10; i++)
-		fprintf(stderr, "%2d %13.9f\n", i, gtod[i]);
-	fprintf(stderr, "Last rank\n");
-	for (i = NBUF - 12; i < NBUF - 2; i++)
-		fprintf(stderr, "%2d %13.9f\n", i, gtod[i]);
+	if (json) {
+		fprintf(stdout, "{\"Average\":%13.9f,", average);
+		fprintf(stdout, "\"First rank\":[");
+		for (i = 0; i < NSAMPLES; i++) {
+		    fprintf(stdout, "%13.9f", gtod[i]);
+		    if (i < NSAMPLES - 1)
+			fputc(',', stdout);
+		    fputs("],", stdout);
+		}
+		fprintf(stdout, "\"Last rank\":");
+		for (i = NBUF - 12; i < NBUF - 2; i++) {
+		    fprintf(stdout, "%13.9f\n", gtod[i]);
+		    if (i < NSAMPLES - 1)
+			fputc(',', stdout);
+		    fputs("]}\n", stdout);
+		}
+	}
+	else
+	{
+		fprintf(stdout, "Average %13.9f\n", average);
+		fprintf(stdout, "First rank\n");
+		for (i = 0; i < NSAMPLES; i++)
+		    fprintf(stdout, "%2d %13.9f\n", i, gtod[i]);
+		fprintf(stdout, "Last rank\n");
+		for (i = NBUF - 12; i < NBUF - 2; i++)
+		    fprintf(stdout, "%2d %13.9f\n", i, gtod[i]);
+	}
 }
 
 /* end */
diff --git a/ntpfrob/main.c b/ntpfrob/main.c
index 3073b9a..5785553 100644
--- a/ntpfrob/main.c
+++ b/ntpfrob/main.c
@@ -5,6 +5,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 
 #include "config.h"
 
@@ -12,20 +13,21 @@
  * Our methods, one per linked module
  */
 extern void ppscheck(char *device);
-extern void tickadj(const int tick);
-extern void jitter(void);
+extern void tickadj(const bool json, const int tick);
+extern void jitter(const bool json);
 extern void stepback(void);
-extern void precision(void);
+extern void precision(const bool json);
 
 int
 main(int argc, char **argv)
 {
 	int ch;
-	while ((ch = getopt(argc, argv, "aA:cp:")) != EOF) {
+	bool json = false;
+	while ((ch = getopt(argc, argv, "a:Acejp:")) != EOF) {
 		switch (ch) {
 		case 'A':
 #ifdef HAVE_ADJTIMEX
-		    tickadj(0);
+		    tickadj(json, 0);
 #else
 		    fputs("ntpfrob: no adjtimex(2) call.\n", stderr);
 		    exit(0);
@@ -33,16 +35,23 @@ main(int argc, char **argv)
 		    break;
 		case 'a':
 #ifdef HAVE_ADJTIMEX
-		    tickadj(atoi(optarg));
+		    tickadj(json, atoi(optarg));
 #else
 		    fputs("ntpfrob: no adjtimex(2) call.\n", stderr);
 		    exit(0);
 #endif
 		    break;
 		case 'c':
-		    jitter();
+		    jitter(json);
 		    exit(0);
 		    break;
+		case 'e':
+		    precision(json);
+		    exit(0);
+		    break;
+		case 'j':
+		    json = true;
+		    break;
 		case 'p':
 #ifdef HAVE_SYS_TIMEPPS_H
 		    ppscheck(optarg);
@@ -51,6 +60,10 @@ main(int argc, char **argv)
 		    exit(0);
 #endif
 		    break;
+		default:
+		    fputs("ntpfrob: no mode option specified.\n", stderr);
+		    exit(1);
+		    break;
 		}
 	}
 
diff --git a/ntpfrob/precision.c b/ntpfrob/precision.c
index 470cb4e..29d01f2 100644
--- a/ntpfrob/precision.c
+++ b/ntpfrob/precision.c
@@ -6,17 +6,23 @@
 #include "ntp_unixtime.h"
 
 #include <stdio.h>
+#include <stdbool.h>
 
 #define	DEFAULT_SYS_PRECISION	-99
 
-int default_get_resolution();
-int default_get_precision();
+int default_get_resolution(void);
+int default_get_precision(void);
 
-void precision(void)
+void precision(const bool json)
 {
-	printf("log2(resolution) = %d, log2(precision) = %d\n",
-	       default_get_resolution(),
-	       default_get_precision());
+	if (json)
+		printf("{\"log2 of resolution\":%d, \"log2 of precision\":%d}\n",
+		       default_get_resolution(),
+		       default_get_precision());
+	else
+		printf("log2(resolution) = %d, log2(precision) = %d\n",
+			default_get_resolution(),
+			default_get_precision());
 }
 
 /* Find the resolution of the system clock by watching how the current time
@@ -80,23 +86,24 @@ default_get_resolution(void)
 		last = tp.tv_usec;
 	}
 
-	printf("resolution = %ld usec after %d loop%s\n",
+	fprintf(stderr, "resolution = %ld usec after %d loop%s\n",
 	       diff, i, (i==1) ? "" : "s");
 
 	diff = (diff *3)/2;
 	if (i >= MAXLOOPS) {
-		printf(
+		fprintf(stderr,
 			"     (Boy this machine is fast ! %d loops without a step)\n",
 			MAXLOOPS);
 		diff = 1; /* No STEP, so FAST machine */
 	}
 	if (i == 0) {
-		printf(
+		fprintf(stderr,
 			"     (The resolution is less than the time to read the clock -- Assume 1us)\n");
 		diff = 1; /* time to read clock >= resolution */
 	}
 	for (i=0, val=HUSECS; val>0; i--, val >>= 1) if (diff >= val) return i;
-	printf("     (Oh dear -- that wasn't expected ! I'll guess !)\n");
+	fprintf(stderr,
+		"     (Oh dear -- that wasn't expected ! I'll guess !)\n");
 	return DEFAULT_SYS_PRECISION /* Something's BUST, so lie ! */;
 }
 
@@ -157,10 +164,10 @@ default_get_precision(void)
 			    val = diff;
 		}
 	}
-	printf("precision  = %ld usec after %d loop%s\n",
+	fprintf(stderr, "precision  = %ld usec after %d loop%s\n",
 	       val, i, (i == 1) ? "" : "s");
 	if (usec >= HUSECS) {
-		printf("     (Boy this machine is fast ! usec was %ld)\n",
+	    fprintf(stderr, "     (Boy this machine is fast ! usec was %ld)\n",
 		       usec);
 		val = MINSTEP;	/* val <= MINSTEP; fast machine */
 	}
diff --git a/ntpfrob/tickadj.c b/ntpfrob/tickadj.c
index 11f6f57..c61f06b 100644
--- a/ntpfrob/tickadj.c
+++ b/ntpfrob/tickadj.c
@@ -25,7 +25,7 @@
 
 static struct timex txc;
 
-void tickadj(const int newtick)
+void tickadj(const bool json, const int newtick)
 {
 	if (newtick != 0)
 	{
@@ -68,9 +68,17 @@ void tickadj(const int newtick)
 	else
 	{
 #ifdef STRUCT_TIMEX_HAS_TIME_TICK
-		printf("tick     = %ld\ntick_adj = %ld\n", txc.time_tick, txc.tickadj);
+		if (json)
+			printf("{\"tick\":%ld,\"tick_adj\":%ld}\n",
+			       txc.time_tick, txc.tickadj);
+		else
+			printf("tick = %ld\ntick_adj = %ld\n",
+			       txc.time_tick, txc.tickadj);
 #else
-		printf("tick = %ld\n", txc.tick);
+		if (json)
+			printf("{\"tick\":%ld}\n", txc.tick);
+		else
+			printf("tick = %ld\n", txc.tick);
 #endif
 	}
 



More information about the vc mailing list