[Git][NTPsec/ntpsec][master] 5 commits: Whoops, removed on % too many...
Gary E. Miller
gitlab at mg.gitlab.com
Tue Oct 4 03:17:22 UTC 2016
Gary E. Miller pushed to branch master at NTPsec / ntpsec
Commits:
eadcf5c1 by Gary E. Miller at 2016-10-03T20:16:55-07:00
Whoops, removed on % too many...
- - - - -
3bf53d54 by Gary E. Miller at 2016-10-03T20:16:55-07:00
Cleanup sitename handling. Make default non-boring.
Default is now FQDN, not 'ntpstats'.
- - - - -
e304cd50 by Gary E. Miller at 2016-10-03T20:16:55-07:00
24*60*60 is SecondsinDay, not SecondsinWeek
- - - - -
ca2b81b1 by Gary E. Miller at 2016-10-03T20:16:55-07:00
Missed one SecondseInWeek.
- - - - -
c977b990 by Gary E. Miller at 2016-10-03T20:16:55-07:00
ntpviz: Convert getopt() to argparse
A bit tedious, but now all the arguments are regularized in the code.
The defaults are now mostly in obvious places.
Auto generated -h/--help
Added long names for all args.
Arguments can be read from a command file.
All argumetns are in one args dictionary.
Better argument error messages.
Probably can use a bit more cleanup.
- - - - -
2 changed files:
- ntpstats/ntpviz
- pylib/statfiles.py
Changes:
=====================================
ntpstats/ntpviz
=====================================
--- a/ntpstats/ntpviz
+++ b/ntpstats/ntpviz
@@ -22,7 +22,8 @@ Python by ESR, concept and GNUPLOT code by Dan Drown.
#SPDX-License-Identifier: BSD-2-Clause
from __future__ import print_function, division
-import atexit, binascii, collections, getopt, os, socket, sys, time
+import argparse
+import atexit, binascii, collections, os, socket, sys, time
from ntp.statfiles import *
def print_profile():
@@ -210,8 +211,6 @@ set rmargin 12
sitename=None, period=None, starttime=None, endtime=None):
NTPStats.__init__(self, statsdir=statsdir, sitename=sitename,
period=period, starttime=starttime, endtime=endtime)
- if self.sitename is None:
- self.sitename = os.path.basename(statsdir)
def local_offset_gnuplot(self):
"Generate GNUPLOT code graphing local clock loop statistics"
@@ -314,7 +313,7 @@ component of frequency drift.</p>
gpslist.sort()
if not len( gpsmap) or not len( gpslist):
- if 1 <= debug_level:
+ if 1 <= args.debug_level:
sys.stderr.write("ntpviz: INFO: no gps data to graph\n")
return ''
@@ -542,7 +541,7 @@ plot \
useful to see how the measured offset is behaving.</p>
<p>Closer to 0s is better. An ideal system would be a horizontal line
-at 0s. Typical 90% ranges may be: local serial GPS 200 ms; local PPS
+at 0s. Typical 90%% ranges may be: local serial GPS 200 ms; local PPS
20µs</p>
<p>Clock Offset is field 5 in the peerstats log file.</p>
@@ -824,77 +823,147 @@ AADRxQAAxBEAAA==
"""
if __name__ == '__main__':
- try:
- (options, arguments) = getopt.getopt(sys.argv[1:], "d:e:ghn:o:p:s:D:", [
- "local-offset", "local-error", "local-jitter", "local-stability",
- "local-offset-histogram",
- "all-peer-offsets", "peer-offsets=",
- "all-peer-jitters", "peer-jitters=",
- "local-temps",
- "local-gps",
- "local-offset-multiplot",
- ])
- except getopt.GetoptError as err:
- sys.stderr.write(str(err) + "\n")
- raise SystemExit(2)
- sitename = None
- statsdirs = ["/var/log/ntpstats"]
- period = endtime = starttime = None
- generate = False
- show_local_offset = show_local_error = show_local_jitter = False
- show_local_stability = show_local_offset_histogram = show_temps = False
- show_local_offset_multiplot = show_gps = False
- show_peer_offsets = show_peer_jitters = None
- outdir = "ntpgraphs"
- debug_level = 0
- for (switch, val) in options:
- if switch == "-d":
- statsdirs = [os.path.expanduser(path) for path in val.split(",")]
- elif switch == "-e":
- endtime = iso_to_posix(val)
- elif switch == "-g":
- generate = True
- elif switch == "-h":
- sys.stdout.write(__doc__)
- raise SystemExit(0)
- elif switch == "-n":
- sitename = val
- elif switch == "-p":
- period = int( float(val) * NTPStats.SecondsInWeek)
- elif switch == "-s":
- starttime = iso_to_posix(val)
- elif switch == "-o":
- outdir = val
- elif switch == "-D":
- debug_level = int(val) # Debug level, 0 to 9, 9 most verbose
- elif switch == "--local-offset":
- show_local_offset = True
- elif switch == "--local-error":
- show_local_error = True
- elif switch == "--local-jitter":
- show_local_jitter = True
- elif switch == "--local-stability":
- show_local_stability = True
- elif switch == "--local-offset-histogram":
- show_local_offset_histogram = True
- elif switch == "--peer-offsets":
- show_peer_offsets = val.split(",")
- elif switch == "--all-peer-offsets":
- show_peer_offsets = []
- elif switch == "--peer-jitters":
- show_peer_jitters = val.split(",")
- elif switch == "--all-peer-jitters":
- show_peer_jitters = []
- elif switch == "--local-temps":
- show_temps = True
- elif switch == "--local-gps":
- show_gps = True
- elif switch == "--local-offset-multiplot":
- show_local_offset_multiplot = True
- if 0 < debug_level:
+
+ parser = argparse.ArgumentParser(description="ntpd stats visualizer",
+ fromfile_prefix_chars='@',
+ epilog = """
+See the manual page for details.
+
+Python by ESR, concept and GNUPLOT code by Dan Drown.
+""")
+ parser.add_argument('-g', '--generate',
+ default=False,
+ action="store_true",
+ dest='generate',
+ help="Run plot through gnuplot to make png")
+ parser.add_argument('-e', '--endtime',
+ default=None,
+ dest='endtime',
+ help="End time in POSIX (seconds) or ISO8601",
+ type=str)
+ parser.add_argument('-s', '--starttime',
+ default=None,
+ dest='starttime',
+ help="Start time in POSIX (seconds) or ISO8601",
+ type=str)
+ parser.add_argument('-n', '--name',
+ default=socket.getfqdn(),
+ dest='sitename',
+ help="sitename (title)",
+ type=str)
+ parser.add_argument('-o', '--outdir',
+ default = "ntpgraphs",
+ dest='outdir',
+ help="output directory",
+ type=str)
+ parser.add_argument('-d', '--datadir',
+ default = "/var/log/ntpstats",
+ dest='statsdirs',
+ help="one or more logfile directories to read",
+ type=str)
+ parser.add_argument('-p', '--period',
+ default = NTPStats.DefaultPeriod,
+ dest='period',
+ help="period in days to graph (float)",
+ type=float)
+ parser.add_argument( '--all-peer-jitters',
+ default = False,
+ action="store_true",
+ dest='show_peer_jitters',
+ help="Plot all peer jitters")
+ parser.add_argument( '--peer-jitters',
+ default = '',
+ dest='peer_jitters',
+ help="Plot peer jitters. Comma separated host list.",
+ type=str)
+ parser.add_argument( '--all-peer-offsets',
+ default = False,
+ action="store_true",
+ dest='show_peer_offsets',
+ help="Plot all peer offsets")
+ parser.add_argument( '--peer-offsets',
+ default = '',
+ dest='peer_offsets',
+ help="Plot peer offsets. Comma separated host list.",
+ type=str)
+ parser.add_argument( '--local-error',
+ default=False,
+ action="store_true",
+ dest='show_local_error',
+ help="Plot clock time and clock frequency offsets")
+ parser.add_argument( '--local-gps',
+ default = False,
+ action="store_true",
+ dest='show_gps',
+ help="Plot gpsd tdop and nSats")
+ parser.add_argument( '--local-jitter',
+ default=False,
+ action="store_true",
+ dest='show_local_jitter',
+ help="Plot clock time jitter")
+ parser.add_argument( '--local-offset',
+ default=False,
+ action="store_true",
+ dest='show_local_offset',
+ help="Plot Clock frequency offset")
+ parser.add_argument( '--local-offset-histogram',
+ default=False,
+ action="store_true",
+ dest='show_local_offset_histogram',
+ help="Plot histogram of loopstats time offsets")
+ parser.add_argument( '--local-offset-multiplot',
+ default = False,
+ action="store_true",
+ dest='show_local_offset_multiplot',
+ help="Plot comparative local offsets for multiple directories")
+ parser.add_argument( '--local-stability',
+ default=False,
+ action="store_true",
+ dest='show_local_stability',
+ help="Plot RMS frequency-jitter")
+ parser.add_argument( '--local-temps',
+ default = False,
+ action="store_true",
+ dest='show_temps',
+ help="Plot local temperature data")
+ parser.add_argument('-D', '--debug',
+ default=0,
+ dest='debug_level',
+ help="debug level, 0 (none) to 9 (most)",
+ type=int)
+ # FIXME, missing -V and --version
+
+ args = parser.parse_args()
+
+ args.period = int( float(args.period) * NTPStats.SecondsInDay)
+ if None != args.endtime:
+ args.endtime = iso_to_posix(args.endtime)
+ if None != args.starttime:
+ args.starttime = iso_to_posix(args.starttime)
+
+ args.statsdirs = [os.path.expanduser(path
+ for path in args.statsdirs.split(",")]
+
+ if True == args.show_peer_offsets:
+ args.show_peer_offsets = []
+ elif 0 < len(args.peer_offsets):
+ args.show_peer_offsets = args.peer_offsets.split(",")
+ else:
+ args.show_peer_offsets = None
+
+ if True == args.show_peer_jitters:
+ args.show_peer_jitters = []
+ elif 0 < len(args.peer_jitters):
+ args.show_peer_jitters = args.peer_jitters.split(",")
+ else:
+ args.show_peer_jitters = None
+
+ if 0 < args.debug_level:
sys.stderr.write("ntpviz: INFO: now running at debug: %s\n" % \
- debug_level)
- if 9 == debug_level:
+ args.debug_level)
+ sys.stderr.write("ntpviz: INFO: Parsed Options %s\n" % args)
+
+ if 9 == args.debug_level:
# crazy debug, also profile
import cProfile, pstats
pr = cProfile.Profile()
@@ -913,19 +982,20 @@ if __name__ == '__main__':
p.ionice(psutil.IOPRIO_CLASS_IDLE)
except ImportError:
- if 0 < debug_level:
+ if 0 < args.debug_level:
sys.stderr.write("ntpviz: INFO: psutils not found\n")
pass
# set nice()
nice = os.nice( nice )
- if 2 < debug_level:
+ if 2 < args.debug_level:
sys.stderr.write("ntpviz: INFO: now running at nice: %s\n" % \
nice)
- statlist = [NTPViz(statsdir=d, sitename=sitename,
- period=period, starttime=starttime, endtime=endtime)
- for d in statsdirs]
+ statlist = [NTPViz(statsdir=d, sitename=args.sitename,
+ period=args.period, starttime=args.starttime,
+ endtime=args.endtime)
+ for d in args.statsdirs]
for fontpath in ("/usr/share/fonts/liberation",
"/usr/share/fonts/liberation-fonts",
@@ -940,91 +1010,92 @@ if __name__ == '__main__':
if len(statlist) == 1:
stats = statlist[0]
- if show_local_offset or show_local_error or show_local_jitter or show_local_stability or show_local_offset_histogram:
+ if args.show_local_offset or \
+ args.show_local_error or \
+ args.show_local_jitter or \
+ args.show_local_stability or \
+ args.show_local_offset_histogram:
if not len( stats.loopstats ):
sys.stderr.write("ntpviz: ERROR: missing loopstats data\n")
raise SystemExit(1)
- if show_local_offset + show_local_error + show_local_jitter + show_local_stability + show_local_offset_histogram > 1:
- sys.stderr.write("ntpviz: ERROR: clash of mode options\n")
- raise SystemExit(1)
- if show_local_offset:
+ if args.show_local_offset:
plot = stats.local_offset_gnuplot()
- if show_local_error:
+ elif args.show_local_error:
plot = stats.local_error_gnuplot()
- if show_local_jitter:
+ elif args.show_local_jitter:
plot = stats.local_offset_jitter_gnuplot()
- if show_local_stability:
+ elif args.show_local_stability:
plot = stats.local_offset_stability_gnuplot()
- if show_local_offset_histogram:
+ elif args.show_local_offset_histogram:
plot = stats.local_offset_histogram_gnuplot()
- if generate:
+
+ if args.generate:
gnuplot(plot['plot'])
else:
sys.stdout.write(plot['plot'])
raise SystemExit(0)
- if show_peer_offsets is not None or show_peer_jitters is not None:
+ if None != args.show_peer_offsets or None != args.show_peer_jitters:
if not len( stats.peerstats ):
sys.stderr.write("ntpviz: ERROR: missing peerstats data\n")
raise SystemExit(1)
- if show_peer_offsets is not None:
- plot = stats.peer_offsets_gnuplot(show_peer_offsets)
- if show_peer_jitters is not None:
- plot = stats.peer_jitters_gnuplot(show_peer_jitters)
- if generate:
+ if None != args.show_peer_offsets:
+ plot = stats.peer_offsets_gnuplot(args.show_peer_offsets)
+ if None != show_peer_jitters:
+ plot = stats.peer_jitters_gnuplot(args.show_peer_jitters)
+ if args.generate:
gnuplot(plot['plot'])
else:
sys.stdout.write(plot['plot'])
raise SystemExit(0)
- if show_temps:
+ if args.show_temps:
if not len( stats.temps):
sys.stderr.write("ntpviz: ERROR: missing temps data\n")
raise SystemExit(1)
- if show_temps is not None:
- plot = stats.local_temps_gnuplot()
- if generate:
+ plot = stats.local_temps_gnuplot()
+ if args.generate:
gnuplot(plot['plot'])
else:
sys.stdout.write(plot['plot'])
raise SystemExit(0)
- if show_gps:
+ if args.show_gps:
if not len( stats.gpsd):
sys.stderr.write("ntpviz: ERROR: missing gps data\n")
raise SystemExit(1)
plot = stats.local_gps_gnuplot()
- if generate:
+ if args.generate:
gnuplot(plot['plot'])
else:
sys.stdout.write(plot['plot'])
raise SystemExit(0)
- if show_local_offset_multiplot:
+ if args.show_local_offset_multiplot:
plot = local_offset_multiplot(statlist)
- if generate:
+ if args.generate:
gnuplot(plot)
else:
sys.stdout.write(plot)
raise SystemExit(0)
# Fall through to HTML code generation
- if not os.path.isdir(outdir):
+ if not os.path.isdir(args.outdir):
try:
- os.mkdir(outdir)
+ os.mkdir(args.outdir)
except SystemError:
sys.stderr.write("ntpviz: ERROR: %s can't be created.\n" \
- % outdir)
+ % args.outdir)
raise SystemExit(1)
# if no ntpsec favicon.ico, write one.
- ico_filename = os.path.join(outdir, "favicon.ico")
+ ico_filename = os.path.join(args.outdir, "favicon.ico")
if not os.path.lexists( ico_filename ):
with open( ico_filename, "w" ) as wp:
wp.write(binascii.a2b_base64(ntpsec_ico))
# if no ntpsec logo, write one.
- logo_filename = os.path.join(outdir, "ntpsec-logo.png")
+ logo_filename = os.path.join(args.outdir, "ntpsec-logo.png")
if not os.path.lexists( logo_filename ):
with open( logo_filename, "w" ) as wp:
wp.write(binascii.a2b_base64(ntpsec_logo))
@@ -1033,7 +1104,7 @@ if __name__ == '__main__':
start_time_str = start_time.strftime("%c")
# if title file, get title from it
- title_f = os.path.join(outdir, "title")
+ title_f = os.path.join(args.outdir, "title")
title = 'ntpviz'
if os.path.isfile(title_f):
try:
@@ -1075,7 +1146,7 @@ Report generated: %(start_time_str)s UTC <br>
# Ugh. Not clear what to do in the multiplot case
if len(statlist) == 1:
index_header += 'Report Period: %1.1f days <br></div> ' \
- % (float(stats.period) / float(NTPStats.SecondsInWeek))
+ % (float(stats.period) / float(NTPStats.SecondsInDay))
index_header += '<div style="clear:both;"></div>'
index_trailer = '''\
@@ -1171,7 +1242,7 @@ ntpviz</a>, part of the <a href="https://www.ntpsec.org/">NTPsec project</a>
# during the run
index_buffer = index_header
# if header file, add it to index.html
- header = os.path.join(outdir, "header")
+ header = os.path.join(args.outdir, "header")
if os.path.isfile(header):
try:
header_file = open( header, 'r')
@@ -1223,11 +1294,11 @@ ntpviz</a>, part of the <a href="https://www.ntpsec.org/">NTPsec project</a>
else:
exp = imagename
index_buffer += "<br><br>\n"
- gnuplot(image['plot'], os.path.join(outdir, imagename + ".png"))
+ gnuplot(image['plot'], os.path.join(args.outdir, imagename + ".png"))
index_buffer += "</div>\n"
# if footer file, add it to index.html
- footer = os.path.join(outdir, "footer")
+ footer = os.path.join(args.outdir, "footer")
if os.path.isfile(footer):
try:
footer_file = open( footer, 'r')
@@ -1238,7 +1309,7 @@ ntpviz</a>, part of the <a href="https://www.ntpsec.org/">NTPsec project</a>
index_buffer += index_trailer
# and send the file buffer
- with open(os.path.join(outdir, "index.html"), "w") as ifile:
+ with open(os.path.join(args.outdir, "index.html"), "w") as ifile:
ifile.write(index_buffer)
ifile.close()
=====================================
pylib/statfiles.py
=====================================
--- a/pylib/statfiles.py
+++ b/pylib/statfiles.py
@@ -11,7 +11,7 @@ import calendar, datetime, glob, gzip, os, socket, subprocess, sys, time
class NTPStats:
"Gather statistics for a specified NTP site"
- SecondsInWeek = 24*60*60
+ SecondsInDay = 24*60*60
DefaultPeriod = 7*24*60*60
peermap = {} # cached result of peersplit()
@@ -57,6 +57,10 @@ class NTPStats:
self.endtime = endtime
self.sitename = sitename or os.path.basename(statsdir)
+ if 'ntpstats' == self.sitename:
+ # boring, use hostname
+ self.sitename = socket.getfqdn()
+
if not os.path.isdir(statsdir):
sys.stderr.write("ntpviz: ERROR: %s is not a directory\n" \
% statsdir)
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/da212799bdd54c02b11ec5957254b478893a265e...c977b990bd96b504e09fe4b5e12a7600332db8f7
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ntpsec.org/pipermail/vc/attachments/20161004/77b56ae4/attachment.html>
More information about the vc
mailing list