570 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			570 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
| package ntpq
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/influxdata/telegraf"
 | |
| 	"github.com/influxdata/telegraf/testutil"
 | |
| 	"github.com/stretchr/testify/assert"
 | |
| 	"github.com/stretchr/testify/require"
 | |
| )
 | |
| 
 | |
| func TestSingleNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(singleNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.NoError(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"when":   int64(101),
 | |
| 		"poll":   int64(256),
 | |
| 		"reach":  int64(37),
 | |
| 		"delay":  float64(51.016),
 | |
| 		"offset": float64(233.010),
 | |
| 		"jitter": float64(17.462),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "uschi5-ntp-002.",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        "10.177.80.46",
 | |
| 		"stratum":      "2",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestBadIntNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(badIntParseNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.Error(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"when":   int64(101),
 | |
| 		"reach":  int64(37),
 | |
| 		"delay":  float64(51.016),
 | |
| 		"offset": float64(233.010),
 | |
| 		"jitter": float64(17.462),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "uschi5-ntp-002.",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        "10.177.80.46",
 | |
| 		"stratum":      "2",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestBadFloatNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(badFloatParseNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.Error(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"when":   int64(2),
 | |
| 		"poll":   int64(256),
 | |
| 		"reach":  int64(37),
 | |
| 		"delay":  float64(51.016),
 | |
| 		"jitter": float64(17.462),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "uschi5-ntp-002.",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        "10.177.80.46",
 | |
| 		"stratum":      "2",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestDaysNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(whenDaysNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.NoError(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"when":   int64(172800),
 | |
| 		"poll":   int64(256),
 | |
| 		"reach":  int64(37),
 | |
| 		"delay":  float64(51.016),
 | |
| 		"offset": float64(233.010),
 | |
| 		"jitter": float64(17.462),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "uschi5-ntp-002.",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        "10.177.80.46",
 | |
| 		"stratum":      "2",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestHoursNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(whenHoursNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.NoError(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"when":   int64(7200),
 | |
| 		"poll":   int64(256),
 | |
| 		"reach":  int64(37),
 | |
| 		"delay":  float64(51.016),
 | |
| 		"offset": float64(233.010),
 | |
| 		"jitter": float64(17.462),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "uschi5-ntp-002.",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        "10.177.80.46",
 | |
| 		"stratum":      "2",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestMinutesNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(whenMinutesNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.NoError(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"when":   int64(120),
 | |
| 		"poll":   int64(256),
 | |
| 		"reach":  int64(37),
 | |
| 		"delay":  float64(51.016),
 | |
| 		"offset": float64(233.010),
 | |
| 		"jitter": float64(17.462),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "uschi5-ntp-002.",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        "10.177.80.46",
 | |
| 		"stratum":      "2",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestBadWhenNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(whenBadNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.Error(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"poll":   int64(256),
 | |
| 		"reach":  int64(37),
 | |
| 		"delay":  float64(51.016),
 | |
| 		"offset": float64(233.010),
 | |
| 		"jitter": float64(17.462),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "uschi5-ntp-002.",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        "10.177.80.46",
 | |
| 		"stratum":      "2",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| // TestParserNTPQ - realated to:
 | |
| // https://github.com/influxdata/telegraf/issues/2386
 | |
| func TestParserNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(multiParserNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.NoError(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"poll":   int64(64),
 | |
| 		"when":   int64(60),
 | |
| 		"reach":  int64(377),
 | |
| 		"delay":  float64(0.0),
 | |
| 		"offset": float64(0.045),
 | |
| 		"jitter": float64(1.012),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "SHM(0)",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        ".PPS.",
 | |
| 		"stratum":      "1",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| 
 | |
| 	fields = map[string]interface{}{
 | |
| 		"poll":   int64(128),
 | |
| 		"when":   int64(121),
 | |
| 		"reach":  int64(377),
 | |
| 		"delay":  float64(0.0),
 | |
| 		"offset": float64(10.105),
 | |
| 		"jitter": float64(2.012),
 | |
| 	}
 | |
| 	tags = map[string]string{
 | |
| 		"remote":       "SHM(1)",
 | |
| 		"state_prefix": "-",
 | |
| 		"refid":        ".GPS.",
 | |
| 		"stratum":      "1",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| 
 | |
| 	fields = map[string]interface{}{
 | |
| 		"poll":   int64(1024),
 | |
| 		"when":   int64(10),
 | |
| 		"reach":  int64(377),
 | |
| 		"delay":  float64(1.748),
 | |
| 		"offset": float64(0.373),
 | |
| 		"jitter": float64(0.101),
 | |
| 	}
 | |
| 	tags = map[string]string{
 | |
| 		"remote":       "37.58.57.238",
 | |
| 		"state_prefix": "+",
 | |
| 		"refid":        "192.53.103.103",
 | |
| 		"stratum":      "2",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestMultiNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(multiNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.NoError(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"delay":  float64(54.033),
 | |
| 		"jitter": float64(449514),
 | |
| 		"offset": float64(243.426),
 | |
| 		"poll":   int64(1024),
 | |
| 		"reach":  int64(377),
 | |
| 		"when":   int64(740),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"refid":   "10.177.80.37",
 | |
| 		"remote":  "83.137.98.96",
 | |
| 		"stratum": "2",
 | |
| 		"type":    "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| 
 | |
| 	fields = map[string]interface{}{
 | |
| 		"delay":  float64(60.785),
 | |
| 		"jitter": float64(449539),
 | |
| 		"offset": float64(232.597),
 | |
| 		"poll":   int64(1024),
 | |
| 		"reach":  int64(377),
 | |
| 		"when":   int64(739),
 | |
| 	}
 | |
| 	tags = map[string]string{
 | |
| 		"refid":   "10.177.80.37",
 | |
| 		"remote":  "81.7.16.52",
 | |
| 		"stratum": "2",
 | |
| 		"type":    "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestBadHeaderNTPQ(t *testing.T) {
 | |
| 	resetVars()
 | |
| 	tt := tester{
 | |
| 		ret: []byte(badHeaderNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.NoError(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"when":   int64(101),
 | |
| 		"poll":   int64(256),
 | |
| 		"reach":  int64(37),
 | |
| 		"delay":  float64(51.016),
 | |
| 		"offset": float64(233.010),
 | |
| 		"jitter": float64(17.462),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "uschi5-ntp-002.",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        "10.177.80.46",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestMissingDelayColumnNTPQ(t *testing.T) {
 | |
| 	resetVars()
 | |
| 	tt := tester{
 | |
| 		ret: []byte(missingDelayNTPQ),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.NoError(t, acc.GatherError(n.Gather))
 | |
| 
 | |
| 	fields := map[string]interface{}{
 | |
| 		"when":   int64(101),
 | |
| 		"poll":   int64(256),
 | |
| 		"reach":  int64(37),
 | |
| 		"offset": float64(233.010),
 | |
| 		"jitter": float64(17.462),
 | |
| 	}
 | |
| 	tags := map[string]string{
 | |
| 		"remote":       "uschi5-ntp-002.",
 | |
| 		"state_prefix": "*",
 | |
| 		"refid":        "10.177.80.46",
 | |
| 		"type":         "u",
 | |
| 	}
 | |
| 	acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
 | |
| }
 | |
| 
 | |
| func TestFailedNTPQ(t *testing.T) {
 | |
| 	tt := tester{
 | |
| 		ret: []byte(singleNTPQ),
 | |
| 		err: fmt.Errorf("Test failure"),
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{}
 | |
| 	assert.Error(t, acc.GatherError(n.Gather))
 | |
| }
 | |
| 
 | |
| // It is possible for the output of ntqp to be missing the refid column.  This
 | |
| // is believed to be http://bugs.ntp.org/show_bug.cgi?id=3484 which is fixed
 | |
| // in ntp-4.2.8p12 (included first in Debian Buster).
 | |
| func TestNoRefID(t *testing.T) {
 | |
| 	now := time.Now()
 | |
| 	expected := []telegraf.Metric{
 | |
| 		testutil.MustMetric("ntpq",
 | |
| 			map[string]string{
 | |
| 				"refid":   "10.177.80.37",
 | |
| 				"remote":  "83.137.98.96",
 | |
| 				"stratum": "2",
 | |
| 				"type":    "u",
 | |
| 			},
 | |
| 			map[string]interface{}{
 | |
| 				"delay":  float64(54.033),
 | |
| 				"jitter": float64(449514),
 | |
| 				"offset": float64(243.426),
 | |
| 				"poll":   int64(1024),
 | |
| 				"reach":  int64(377),
 | |
| 				"when":   int64(740),
 | |
| 			},
 | |
| 			now),
 | |
| 		testutil.MustMetric("ntpq",
 | |
| 			map[string]string{
 | |
| 				"refid":   "10.177.80.37",
 | |
| 				"remote":  "131.188.3.221",
 | |
| 				"stratum": "2",
 | |
| 				"type":    "u",
 | |
| 			},
 | |
| 			map[string]interface{}{
 | |
| 				"delay":  float64(111.820),
 | |
| 				"jitter": float64(449528),
 | |
| 				"offset": float64(261.921),
 | |
| 				"poll":   int64(1024),
 | |
| 				"reach":  int64(377),
 | |
| 				"when":   int64(783),
 | |
| 			},
 | |
| 			now),
 | |
| 	}
 | |
| 
 | |
| 	tt := tester{
 | |
| 		ret: []byte(noRefID),
 | |
| 		err: nil,
 | |
| 	}
 | |
| 	n := &NTPQ{
 | |
| 		runQ: tt.runqTest,
 | |
| 	}
 | |
| 
 | |
| 	acc := testutil.Accumulator{
 | |
| 		TimeFunc: func() time.Time { return now },
 | |
| 	}
 | |
| 
 | |
| 	require.NoError(t, acc.GatherError(n.Gather))
 | |
| 	testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
 | |
| }
 | |
| 
 | |
| type tester struct {
 | |
| 	ret []byte
 | |
| 	err error
 | |
| }
 | |
| 
 | |
| func (t *tester) runqTest() ([]byte, error) {
 | |
| 	return t.ret, t.err
 | |
| }
 | |
| 
 | |
| func resetVars() {
 | |
| 	// Mapping of ntpq header names to tag keys
 | |
| 	tagHeaders = map[string]string{
 | |
| 		"remote": "remote",
 | |
| 		"refid":  "refid",
 | |
| 		"st":     "stratum",
 | |
| 		"t":      "type",
 | |
| 	}
 | |
| 
 | |
| 	// Mapping of the ntpq tag key to the index in the command output
 | |
| 	tagI = map[string]int{
 | |
| 		"remote":  -1,
 | |
| 		"refid":   -1,
 | |
| 		"stratum": -1,
 | |
| 		"type":    -1,
 | |
| 	}
 | |
| 
 | |
| 	// Mapping of float metrics to their index in the command output
 | |
| 	floatI = map[string]int{
 | |
| 		"delay":  -1,
 | |
| 		"offset": -1,
 | |
| 		"jitter": -1,
 | |
| 	}
 | |
| 
 | |
| 	// Mapping of int metrics to their index in the command output
 | |
| 	intI = map[string]int{
 | |
| 		"when":  -1,
 | |
| 		"poll":  -1,
 | |
| 		"reach": -1,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var singleNTPQ = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
| *uschi5-ntp-002. 10.177.80.46     2 u  101  256   37   51.016  233.010  17.462
 | |
| `
 | |
| 
 | |
| var badHeaderNTPQ = `remote      refid   foobar t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
| *uschi5-ntp-002. 10.177.80.46     2 u  101  256   37   51.016  233.010  17.462
 | |
| `
 | |
| 
 | |
| var missingDelayNTPQ = `remote      refid   foobar t when poll reach   offset  jitter
 | |
| ==============================================================================
 | |
| *uschi5-ntp-002. 10.177.80.46     2 u  101  256   37   233.010  17.462
 | |
| `
 | |
| 
 | |
| var whenDaysNTPQ = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
| *uschi5-ntp-002. 10.177.80.46     2 u  2d  256   37   51.016  233.010  17.462
 | |
| `
 | |
| 
 | |
| var whenHoursNTPQ = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
| *uschi5-ntp-002. 10.177.80.46     2 u  2h  256   37   51.016  233.010  17.462
 | |
| `
 | |
| 
 | |
| var whenMinutesNTPQ = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
| *uschi5-ntp-002. 10.177.80.46     2 u  2m  256   37   51.016  233.010  17.462
 | |
| `
 | |
| 
 | |
| var whenBadNTPQ = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
| *uschi5-ntp-002. 10.177.80.46     2 u  2q  256   37   51.016  233.010  17.462
 | |
| `
 | |
| 
 | |
| var badFloatParseNTPQ = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
| *uschi5-ntp-002. 10.177.80.46     2 u  2  256   37   51.016  foobar  17.462
 | |
| `
 | |
| 
 | |
| var badIntParseNTPQ = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
| *uschi5-ntp-002. 10.177.80.46     2 u  101  foobar   37   51.016  233.010  17.462
 | |
| `
 | |
| 
 | |
| var multiNTPQ = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
|  83.137.98.96    10.177.80.37     2 u  740 1024  377   54.033  243.426 449514.
 | |
|  81.7.16.52      10.177.80.37     2 u  739 1024  377   60.785  232.597 449539.
 | |
|  131.188.3.221   10.177.80.37     2 u  783 1024  377  111.820  261.921 449528.
 | |
|  5.9.29.107      10.177.80.37     2 u  703 1024  377  205.704  160.406 449602.
 | |
|  91.189.94.4     10.177.80.37     2 u  673 1024  377  143.047  274.726 449445.
 | |
| `
 | |
| 
 | |
| var multiParserNTPQ = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
| *SHM(0)          .PPS.                          1 u   60  64   377    0.000    0.045   1.012
 | |
| +37.58.57.238 (d 192.53.103.103			2 u   10 1024  377    1.748    0.373   0.101
 | |
| +37.58.57.238 (domain) 192.53.103.103   2 u   10 1024  377    1.748    0.373   0.101
 | |
| +37.58.57.238 ( 192.53.103.103			2 u   10 1024  377    1.748    0.373   0.101
 | |
| -SHM(1)          .GPS.                          1 u   121 128  377    0.000   10.105   2.012
 | |
| `
 | |
| 
 | |
| var noRefID = `     remote           refid      st t when poll reach   delay   offset  jitter
 | |
| ==============================================================================
 | |
|  83.137.98.96    10.177.80.37     2 u  740 1024  377   54.033  243.426 449514.
 | |
|  91.189.94.4                      2 u  673 1024  377  143.047  274.726 449445.
 | |
|  131.188.3.221   10.177.80.37     2 u  783 1024  377  111.820  261.921 449528.
 | |
| `
 |