Compare commits
16 Commits
1.3.3
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7192e68b24 | ||
|
|
ca4234cfd0 | ||
|
|
e7ce063f8a | ||
|
|
d4f59a1bd7 | ||
|
|
2a83f97546 | ||
|
|
99650a20e3 | ||
|
|
d4536ad29e | ||
|
|
7bbd3daa98 | ||
|
|
ebea9f16df | ||
|
|
b7205e9a6c | ||
|
|
8ea07a9678 | ||
|
|
aef603889f | ||
|
|
88c3a4bb4e | ||
|
|
c6e2500a84 | ||
|
|
6751718fb2 | ||
|
|
5b5d562bd4 |
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,3 +1,21 @@
|
|||||||
|
## v1.3.5 [2017-07-26]
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
- [#3049](https://github.com/influxdata/telegraf/issues/3049): Fix prometheus output cannot be reloaded.
|
||||||
|
- [#3037](https://github.com/influxdata/telegraf/issues/3037): Fix filestat reporting exists when cannot list directory.
|
||||||
|
- [#2386](https://github.com/influxdata/telegraf/issues/2386): Fix ntpq parse issue when using dns_lookup.
|
||||||
|
- [#2554](https://github.com/influxdata/telegraf/issues/2554): Fix panic when agent.interval = "0s".
|
||||||
|
|
||||||
|
## v1.3.4 [2017-07-12]
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
- [#3001](https://github.com/influxdata/telegraf/issues/3001): Fix handling of escape characters within fields.
|
||||||
|
- [#2988](https://github.com/influxdata/telegraf/issues/2988): Fix chrony plugin does not track system time offset.
|
||||||
|
- [#3004](https://github.com/influxdata/telegraf/issues/3004): Do not allow metrics with trailing slashes.
|
||||||
|
- [#3011](https://github.com/influxdata/telegraf/issues/3011): Prevent Write from being called concurrently.
|
||||||
|
|
||||||
## v1.3.3 [2017-06-28]
|
## v1.3.3 [2017-06-28]
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|||||||
@@ -151,6 +151,16 @@ func reloadLoop(
|
|||||||
log.Fatalf("E! Error: no inputs found, did you provide a valid config file?")
|
log.Fatalf("E! Error: no inputs found, did you provide a valid config file?")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if int64(c.Agent.Interval.Duration) <= 0 {
|
||||||
|
log.Fatalf("E! Agent interval must be positive, found %s",
|
||||||
|
c.Agent.Interval.Duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
if int64(c.Agent.FlushInterval.Duration) <= 0 {
|
||||||
|
log.Fatalf("E! Agent flush_interval must be positive; found %s",
|
||||||
|
c.Agent.Interval.Duration)
|
||||||
|
}
|
||||||
|
|
||||||
ag, err := agent.NewAgent(c)
|
ag, err := agent.NewAgent(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("E! " + err.Error())
|
log.Fatal("E! " + err.Error())
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func (g *GlobPath) Match() map[string]os.FileInfo {
|
|||||||
if !g.hasMeta {
|
if !g.hasMeta {
|
||||||
out := make(map[string]os.FileInfo)
|
out := make(map[string]os.FileInfo)
|
||||||
info, err := os.Stat(g.path)
|
info, err := os.Stat(g.path)
|
||||||
if !os.IsNotExist(err) {
|
if err == nil {
|
||||||
out[g.path] = info
|
out[g.path] = info
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
@@ -55,7 +55,7 @@ func (g *GlobPath) Match() map[string]os.FileInfo {
|
|||||||
files, _ := filepath.Glob(g.path)
|
files, _ := filepath.Glob(g.path)
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
info, err := os.Stat(file)
|
info, err := os.Stat(file)
|
||||||
if !os.IsNotExist(err) {
|
if err == nil {
|
||||||
out[file] = info
|
out[file] = info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package globpath
|
package globpath
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -70,3 +71,20 @@ func getTestdataDir() string {
|
|||||||
_, filename, _, _ := runtime.Caller(1)
|
_, filename, _, _ := runtime.Caller(1)
|
||||||
return strings.Replace(filename, "globpath_test.go", "testdata", 1)
|
return strings.Replace(filename, "globpath_test.go", "testdata", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMatch_ErrPermission(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
expected map[string]os.FileInfo
|
||||||
|
}{
|
||||||
|
{"/root/foo", map[string]os.FileInfo{}},
|
||||||
|
{"/root/f*", map[string]os.FileInfo{}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
glob, err := Compile(test.input)
|
||||||
|
require.NoError(t, err)
|
||||||
|
actual := glob.Match()
|
||||||
|
require.Equal(t, test.expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package models
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
@@ -77,7 +78,27 @@ func makemetric(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for k, v := range tags {
|
||||||
|
if strings.HasSuffix(k, `\`) {
|
||||||
|
log.Printf("D! Measurement [%s] tag [%s] "+
|
||||||
|
"ends with a backslash, skipping", measurement, k)
|
||||||
|
delete(tags, k)
|
||||||
|
continue
|
||||||
|
} else if strings.HasSuffix(v, `\`) {
|
||||||
|
log.Printf("D! Measurement [%s] tag [%s] has a value "+
|
||||||
|
"ending with a backslash, skipping", measurement, k)
|
||||||
|
delete(tags, k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for k, v := range fields {
|
for k, v := range fields {
|
||||||
|
if strings.HasSuffix(k, `\`) {
|
||||||
|
log.Printf("D! Measurement [%s] field [%s] "+
|
||||||
|
"ends with a backslash, skipping", measurement, k)
|
||||||
|
delete(fields, k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
// Validate uint64 and float64 fields
|
// Validate uint64 and float64 fields
|
||||||
// convert all int & uint types to int64
|
// convert all int & uint types to int64
|
||||||
switch val := v.(type) {
|
switch val := v.(type) {
|
||||||
@@ -128,6 +149,14 @@ func makemetric(
|
|||||||
delete(fields, k)
|
delete(fields, k)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
case string:
|
||||||
|
if strings.HasSuffix(val, `\`) {
|
||||||
|
log.Printf("D! Measurement [%s] field [%s] has a value "+
|
||||||
|
"ending with a backslash, skipping", measurement, k)
|
||||||
|
delete(fields, k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fields[k] = v
|
||||||
default:
|
default:
|
||||||
fields[k] = v
|
fields[k] = v
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMakeMetricNoFields(t *testing.T) {
|
func TestMakeMetricNoFields(t *testing.T) {
|
||||||
@@ -332,6 +333,128 @@ func TestMakeMetricNameSuffix(t *testing.T) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMakeMetric_TrailingSlash(t *testing.T) {
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
measurement string
|
||||||
|
fields map[string]interface{}
|
||||||
|
tags map[string]string
|
||||||
|
expectedNil bool
|
||||||
|
expectedMeasurement string
|
||||||
|
expectedFields map[string]interface{}
|
||||||
|
expectedTags map[string]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Measurement cannot have trailing slash",
|
||||||
|
measurement: `cpu\`,
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
tags: map[string]string{},
|
||||||
|
expectedNil: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Field key with trailing slash dropped",
|
||||||
|
measurement: `cpu`,
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
`bad\`: `xyzzy`,
|
||||||
|
},
|
||||||
|
tags: map[string]string{},
|
||||||
|
expectedMeasurement: `cpu`,
|
||||||
|
expectedFields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
expectedTags: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Field value with trailing slash dropped",
|
||||||
|
measurement: `cpu`,
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
"bad": `xyzzy\`,
|
||||||
|
},
|
||||||
|
tags: map[string]string{},
|
||||||
|
expectedMeasurement: `cpu`,
|
||||||
|
expectedFields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
expectedTags: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Must have one field after dropped",
|
||||||
|
measurement: `cpu`,
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"bad": `xyzzy\`,
|
||||||
|
},
|
||||||
|
tags: map[string]string{},
|
||||||
|
expectedNil: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Tag key with trailing slash dropped",
|
||||||
|
measurement: `cpu`,
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
tags: map[string]string{
|
||||||
|
`host\`: "localhost",
|
||||||
|
"a": "x",
|
||||||
|
},
|
||||||
|
expectedMeasurement: `cpu`,
|
||||||
|
expectedFields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
expectedTags: map[string]string{
|
||||||
|
"a": "x",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Tag value with trailing slash dropped",
|
||||||
|
measurement: `cpu`,
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
tags: map[string]string{
|
||||||
|
`host`: `localhost\`,
|
||||||
|
"a": "x",
|
||||||
|
},
|
||||||
|
expectedMeasurement: `cpu`,
|
||||||
|
expectedFields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
expectedTags: map[string]string{
|
||||||
|
"a": "x",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ri := NewRunningInput(&testInput{}, &InputConfig{
|
||||||
|
Name: "TestRunningInput",
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
m := ri.MakeMetric(
|
||||||
|
tc.measurement,
|
||||||
|
tc.fields,
|
||||||
|
tc.tags,
|
||||||
|
telegraf.Untyped,
|
||||||
|
now)
|
||||||
|
|
||||||
|
if tc.expectedNil {
|
||||||
|
require.Nil(t, m)
|
||||||
|
} else {
|
||||||
|
require.NotNil(t, m)
|
||||||
|
require.Equal(t, tc.expectedMeasurement, m.Name())
|
||||||
|
require.Equal(t, tc.expectedFields, m.Fields())
|
||||||
|
require.Equal(t, tc.expectedTags, m.Tags())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type testInput struct{}
|
type testInput struct{}
|
||||||
|
|
||||||
func (t *testInput) Description() string { return "" }
|
func (t *testInput) Description() string { return "" }
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
@@ -34,6 +35,9 @@ type RunningOutput struct {
|
|||||||
|
|
||||||
metrics *buffer.Buffer
|
metrics *buffer.Buffer
|
||||||
failMetrics *buffer.Buffer
|
failMetrics *buffer.Buffer
|
||||||
|
|
||||||
|
// Guards against concurrent calls to the Output as described in #3009
|
||||||
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRunningOutput(
|
func NewRunningOutput(
|
||||||
@@ -169,6 +173,8 @@ func (ro *RunningOutput) write(metrics []telegraf.Metric) error {
|
|||||||
if nMetrics == 0 {
|
if nMetrics == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
ro.Lock()
|
||||||
|
defer ro.Unlock()
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := ro.Output.Write(metrics)
|
err := ro.Output.Write(metrics)
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
@@ -26,6 +27,9 @@ func New(
|
|||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
return nil, fmt.Errorf("Metric cannot be made with an empty name")
|
return nil, fmt.Errorf("Metric cannot be made with an empty name")
|
||||||
}
|
}
|
||||||
|
if strings.HasSuffix(name, `\`) {
|
||||||
|
return nil, fmt.Errorf("Metric cannot have measurement name ending with a backslash")
|
||||||
|
}
|
||||||
|
|
||||||
var thisType telegraf.ValueType
|
var thisType telegraf.ValueType
|
||||||
if len(mType) > 0 {
|
if len(mType) > 0 {
|
||||||
@@ -44,6 +48,13 @@ func New(
|
|||||||
// pre-allocate exact size of the tags slice
|
// pre-allocate exact size of the tags slice
|
||||||
taglen := 0
|
taglen := 0
|
||||||
for k, v := range tags {
|
for k, v := range tags {
|
||||||
|
if strings.HasSuffix(k, `\`) {
|
||||||
|
return nil, fmt.Errorf("Metric cannot have tag key ending with a backslash")
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(v, `\`) {
|
||||||
|
return nil, fmt.Errorf("Metric cannot have tag value ending with a backslash")
|
||||||
|
}
|
||||||
|
|
||||||
if len(k) == 0 || len(v) == 0 {
|
if len(k) == 0 || len(v) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -66,7 +77,17 @@ func New(
|
|||||||
|
|
||||||
// pre-allocate capacity of the fields slice
|
// pre-allocate capacity of the fields slice
|
||||||
fieldlen := 0
|
fieldlen := 0
|
||||||
for k, _ := range fields {
|
for k, v := range fields {
|
||||||
|
if strings.HasSuffix(k, `\`) {
|
||||||
|
return nil, fmt.Errorf("Metric cannot have field key ending with a backslash")
|
||||||
|
}
|
||||||
|
switch val := v.(type) {
|
||||||
|
case string:
|
||||||
|
if strings.HasSuffix(val, `\`) {
|
||||||
|
return nil, fmt.Errorf("Metric cannot have field value ending with a backslash")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 10 bytes is completely arbitrary, but will at least prevent some
|
// 10 bytes is completely arbitrary, but will at least prevent some
|
||||||
// amount of allocations. There's a small possibility this will create
|
// amount of allocations. There's a small possibility this will create
|
||||||
// slightly more allocations for a metric that has many short fields.
|
// slightly more allocations for a metric that has many short fields.
|
||||||
@@ -98,7 +119,7 @@ func indexUnescapedByte(buf []byte, b byte) int {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
keyi += i
|
keyi += i
|
||||||
if countBackslashes(buf, keyi-1)%2 == 0 {
|
if buf[keyi-1] != '\\' {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
keyi++
|
keyi++
|
||||||
@@ -107,24 +128,6 @@ func indexUnescapedByte(buf []byte, b byte) int {
|
|||||||
return keyi
|
return keyi
|
||||||
}
|
}
|
||||||
|
|
||||||
// countBackslashes counts the number of preceding backslashes starting at
|
|
||||||
// the 'start' index.
|
|
||||||
func countBackslashes(buf []byte, index int) int {
|
|
||||||
var count int
|
|
||||||
for {
|
|
||||||
if index < 0 {
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
if buf[index] == '\\' {
|
|
||||||
count++
|
|
||||||
index--
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
type metric struct {
|
type metric struct {
|
||||||
name []byte
|
name []byte
|
||||||
tags []byte
|
tags []byte
|
||||||
|
|||||||
@@ -255,6 +255,8 @@ func TestNewMetric_Fields(t *testing.T) {
|
|||||||
"bool": true,
|
"bool": true,
|
||||||
"false": false,
|
"false": false,
|
||||||
"string": "test",
|
"string": "test",
|
||||||
|
"quote_string": `x"y`,
|
||||||
|
"backslash_quote_string": `x\"y`,
|
||||||
}
|
}
|
||||||
m, err := New("cpu", tags, fields, now)
|
m, err := New("cpu", tags, fields, now)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -367,7 +369,7 @@ func TestIndexUnescapedByte(t *testing.T) {
|
|||||||
{
|
{
|
||||||
in: []byte(`foo\\bar`),
|
in: []byte(`foo\\bar`),
|
||||||
b: 'b',
|
b: 'b',
|
||||||
expected: 5,
|
expected: -1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
in: []byte(`foobar`),
|
in: []byte(`foobar`),
|
||||||
@@ -685,3 +687,55 @@ func TestEmptyTagValueOrKey(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewMetric_TrailingSlash(t *testing.T) {
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
tags map[string]string
|
||||||
|
fields map[string]interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: `cpu\`,
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cpu",
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
`value\`: "x",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cpu",
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"value": `x\`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cpu",
|
||||||
|
tags: map[string]string{
|
||||||
|
`host\`: "localhost",
|
||||||
|
},
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cpu",
|
||||||
|
tags: map[string]string{
|
||||||
|
"host": `localhost\`,
|
||||||
|
},
|
||||||
|
fields: map[string]interface{}{
|
||||||
|
"value": int64(42),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
_, err := New(tc.name, tc.tags, tc.fields, now)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ Delete second or Not synchronised.
|
|||||||
### Measurements & Fields:
|
### Measurements & Fields:
|
||||||
|
|
||||||
- chrony
|
- chrony
|
||||||
|
- system_time (float, seconds)
|
||||||
- last_offset (float, seconds)
|
- last_offset (float, seconds)
|
||||||
- rms_offset (float, seconds)
|
- rms_offset (float, seconds)
|
||||||
- frequency (float, ppm)
|
- frequency (float, ppm)
|
||||||
@@ -84,7 +85,7 @@ Delete second or Not synchronised.
|
|||||||
```
|
```
|
||||||
$ telegraf -config telegraf.conf -input-filter chrony -test
|
$ telegraf -config telegraf.conf -input-filter chrony -test
|
||||||
* Plugin: chrony, Collection 1
|
* Plugin: chrony, Collection 1
|
||||||
> chrony,leap_status=normal,reference_id=192.168.1.1,stratum=3 frequency=-35.657,last_offset=-0.000013616,residual_freq=-0,rms_offset=0.000027073,root_delay=0.000644,root_dispersion=0.003444,skew=0.001,update_interval=1031.2 1463750789687639161
|
> chrony,leap_status=normal,reference_id=192.168.1.1,stratum=3 frequency=-35.657,system_time=0.000027073,last_offset=-0.000013616,residual_freq=-0,rms_offset=0.000027073,root_delay=0.000644,root_dispersion=0.003444,skew=0.001,update_interval=1031.2 1463750789687639161
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func processChronycOutput(out string) (map[string]interface{}, map[string]string
|
|||||||
}
|
}
|
||||||
name := strings.ToLower(strings.Replace(strings.TrimSpace(stats[0]), " ", "_", -1))
|
name := strings.ToLower(strings.Replace(strings.TrimSpace(stats[0]), " ", "_", -1))
|
||||||
// ignore reference time
|
// ignore reference time
|
||||||
if strings.Contains(name, "time") {
|
if strings.Contains(name, "ref_time") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
valueFields := strings.Fields(stats[1])
|
valueFields := strings.Fields(stats[1])
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ func TestGather(t *testing.T) {
|
|||||||
"stratum": "3",
|
"stratum": "3",
|
||||||
}
|
}
|
||||||
fields := map[string]interface{}{
|
fields := map[string]interface{}{
|
||||||
|
"system_time": 0.000020390,
|
||||||
"last_offset": 0.000012651,
|
"last_offset": 0.000012651,
|
||||||
"rms_offset": 0.000025577,
|
"rms_offset": 0.000025577,
|
||||||
"frequency": -16.001,
|
"frequency": -16.001,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -67,6 +68,14 @@ func (n *NTPQ) Gather(acc telegraf.Accumulator) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Due to problems with a parsing, we have to use regexp expression in order
|
||||||
|
// to remove string that starts from '(' and ends with space
|
||||||
|
// see: https://github.com/influxdata/telegraf/issues/2386
|
||||||
|
reg, err := regexp.Compile("\\([\\S]*")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
lineCounter := 0
|
lineCounter := 0
|
||||||
scanner := bufio.NewScanner(bytes.NewReader(out))
|
scanner := bufio.NewScanner(bytes.NewReader(out))
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
@@ -80,6 +89,8 @@ func (n *NTPQ) Gather(acc telegraf.Accumulator) error {
|
|||||||
line = strings.TrimLeft(line, "*#o+x.-")
|
line = strings.TrimLeft(line, "*#o+x.-")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
line = reg.ReplaceAllString(line, "")
|
||||||
|
|
||||||
fields := strings.Fields(line)
|
fields := strings.Fields(line)
|
||||||
if len(fields) < 2 {
|
if len(fields) < 2 {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -247,6 +247,21 @@ func TestBadWhenNTPQ(t *testing.T) {
|
|||||||
acc.AssertContainsTaggedFields(t, "ntpq", fields, tags)
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
func TestMultiNTPQ(t *testing.T) {
|
func TestMultiNTPQ(t *testing.T) {
|
||||||
tt := tester{
|
tt := tester{
|
||||||
ret: []byte(multiNTPQ),
|
ret: []byte(multiNTPQ),
|
||||||
@@ -463,3 +478,9 @@ var multiNTPQ = ` remote refid st t when poll reach delay
|
|||||||
5.9.29.107 10.177.80.37 2 u 703 1024 377 205.704 160.406 449602.
|
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.
|
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
|
||||||
|
==============================================================================
|
||||||
|
+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
|
||||||
|
`
|
||||||
|
|||||||
@@ -94,7 +94,9 @@ func (p *PrometheusClient) Connect() error {
|
|||||||
func (p *PrometheusClient) Close() error {
|
func (p *PrometheusClient) Close() error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return p.server.Shutdown(ctx)
|
err := p.server.Shutdown(ctx)
|
||||||
|
prometheus.Unregister(p)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrometheusClient) SampleConfig() string {
|
func (p *PrometheusClient) SampleConfig() string {
|
||||||
|
|||||||
Reference in New Issue
Block a user