2016-04-22 21:47:26 +00:00
|
|
|
package tail
|
2016-04-26 16:43:41 +00:00
|
|
|
|
|
|
|
import (
|
2019-09-23 22:39:50 +00:00
|
|
|
"bytes"
|
2016-04-26 16:43:41 +00:00
|
|
|
"io/ioutil"
|
2019-09-23 22:39:50 +00:00
|
|
|
"log"
|
2016-04-26 16:43:41 +00:00
|
|
|
"os"
|
2017-03-24 19:03:36 +00:00
|
|
|
"runtime"
|
2016-04-26 16:43:41 +00:00
|
|
|
"testing"
|
2019-08-21 23:30:55 +00:00
|
|
|
"time"
|
2016-04-26 16:43:41 +00:00
|
|
|
|
2019-08-21 23:30:55 +00:00
|
|
|
"github.com/influxdata/telegraf"
|
2016-04-26 16:43:41 +00:00
|
|
|
"github.com/influxdata/telegraf/plugins/parsers"
|
2019-08-21 23:30:55 +00:00
|
|
|
"github.com/influxdata/telegraf/plugins/parsers/csv"
|
|
|
|
"github.com/influxdata/telegraf/plugins/parsers/json"
|
2016-04-26 16:43:41 +00:00
|
|
|
"github.com/influxdata/telegraf/testutil"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestTailFromBeginning(t *testing.T) {
|
2018-01-09 23:01:20 +00:00
|
|
|
if os.Getenv("CIRCLE_PROJECT_REPONAME") != "" {
|
|
|
|
t.Skip("Skipping CI testing due to race conditions")
|
|
|
|
}
|
|
|
|
|
2016-04-26 16:43:41 +00:00
|
|
|
tmpfile, err := ioutil.TempFile("", "")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer os.Remove(tmpfile.Name())
|
2020-03-27 22:40:08 +00:00
|
|
|
defer tmpfile.Close()
|
2016-07-28 13:08:12 +00:00
|
|
|
_, err = tmpfile.WriteString("cpu,mytag=foo usage_idle=100\n")
|
|
|
|
require.NoError(t, err)
|
2016-04-26 16:43:41 +00:00
|
|
|
|
|
|
|
tt := NewTail()
|
2019-09-23 22:39:50 +00:00
|
|
|
tt.Log = testutil.Logger{}
|
2016-04-26 16:43:41 +00:00
|
|
|
tt.FromBeginning = true
|
|
|
|
tt.Files = []string{tmpfile.Name()}
|
2018-09-18 16:23:45 +00:00
|
|
|
tt.SetParserFunc(parsers.NewInfluxParser)
|
2020-03-27 22:40:08 +00:00
|
|
|
|
|
|
|
err = tt.Init()
|
|
|
|
require.NoError(t, err)
|
2016-04-26 16:43:41 +00:00
|
|
|
|
|
|
|
acc := testutil.Accumulator{}
|
|
|
|
require.NoError(t, tt.Start(&acc))
|
2020-03-27 22:40:08 +00:00
|
|
|
defer tt.Stop()
|
2017-04-24 18:13:26 +00:00
|
|
|
require.NoError(t, acc.GatherError(tt.Gather))
|
2016-04-26 16:43:41 +00:00
|
|
|
|
2017-03-24 19:03:36 +00:00
|
|
|
acc.Wait(1)
|
2016-04-26 16:43:41 +00:00
|
|
|
acc.AssertContainsTaggedFields(t, "cpu",
|
|
|
|
map[string]interface{}{
|
|
|
|
"usage_idle": float64(100),
|
|
|
|
},
|
|
|
|
map[string]string{
|
|
|
|
"mytag": "foo",
|
2018-07-10 00:39:51 +00:00
|
|
|
"path": tmpfile.Name(),
|
2016-04-26 16:43:41 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTailFromEnd(t *testing.T) {
|
2018-01-13 00:48:45 +00:00
|
|
|
if os.Getenv("CIRCLE_PROJECT_REPONAME") != "" {
|
|
|
|
t.Skip("Skipping CI testing due to race conditions")
|
|
|
|
}
|
|
|
|
|
2016-04-26 16:43:41 +00:00
|
|
|
tmpfile, err := ioutil.TempFile("", "")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer os.Remove(tmpfile.Name())
|
2020-03-27 22:40:08 +00:00
|
|
|
defer tmpfile.Close()
|
2016-04-26 16:43:41 +00:00
|
|
|
_, err = tmpfile.WriteString("cpu,mytag=foo usage_idle=100\n")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tt := NewTail()
|
2019-09-23 22:39:50 +00:00
|
|
|
tt.Log = testutil.Logger{}
|
2016-04-26 16:43:41 +00:00
|
|
|
tt.Files = []string{tmpfile.Name()}
|
2018-09-18 16:23:45 +00:00
|
|
|
tt.SetParserFunc(parsers.NewInfluxParser)
|
2020-03-27 22:40:08 +00:00
|
|
|
|
|
|
|
err = tt.Init()
|
|
|
|
require.NoError(t, err)
|
2016-04-26 16:43:41 +00:00
|
|
|
|
|
|
|
acc := testutil.Accumulator{}
|
|
|
|
require.NoError(t, tt.Start(&acc))
|
2020-03-27 22:40:08 +00:00
|
|
|
defer tt.Stop()
|
2017-03-24 19:03:36 +00:00
|
|
|
for _, tailer := range tt.tailers {
|
|
|
|
for n, err := tailer.Tell(); err == nil && n == 0; n, err = tailer.Tell() {
|
|
|
|
// wait for tailer to jump to end
|
|
|
|
runtime.Gosched()
|
|
|
|
}
|
|
|
|
}
|
2016-04-26 16:43:41 +00:00
|
|
|
|
|
|
|
_, err = tmpfile.WriteString("cpu,othertag=foo usage_idle=100\n")
|
|
|
|
require.NoError(t, err)
|
2017-04-24 18:13:26 +00:00
|
|
|
require.NoError(t, acc.GatherError(tt.Gather))
|
2016-04-26 16:43:41 +00:00
|
|
|
|
2017-03-24 19:03:36 +00:00
|
|
|
acc.Wait(1)
|
2016-04-26 16:43:41 +00:00
|
|
|
acc.AssertContainsTaggedFields(t, "cpu",
|
|
|
|
map[string]interface{}{
|
|
|
|
"usage_idle": float64(100),
|
|
|
|
},
|
|
|
|
map[string]string{
|
|
|
|
"othertag": "foo",
|
2018-07-10 00:39:51 +00:00
|
|
|
"path": tmpfile.Name(),
|
2016-04-26 16:43:41 +00:00
|
|
|
})
|
|
|
|
assert.Len(t, acc.Metrics, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTailBadLine(t *testing.T) {
|
|
|
|
tmpfile, err := ioutil.TempFile("", "")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer os.Remove(tmpfile.Name())
|
2020-03-27 22:40:08 +00:00
|
|
|
defer tmpfile.Close()
|
2016-04-26 16:43:41 +00:00
|
|
|
|
|
|
|
tt := NewTail()
|
2019-09-23 22:39:50 +00:00
|
|
|
tt.Log = testutil.Logger{}
|
2016-04-26 16:43:41 +00:00
|
|
|
tt.FromBeginning = true
|
|
|
|
tt.Files = []string{tmpfile.Name()}
|
2018-09-18 16:23:45 +00:00
|
|
|
tt.SetParserFunc(parsers.NewInfluxParser)
|
2020-03-27 22:40:08 +00:00
|
|
|
|
|
|
|
err = tt.Init()
|
|
|
|
require.NoError(t, err)
|
2016-04-26 16:43:41 +00:00
|
|
|
|
|
|
|
acc := testutil.Accumulator{}
|
|
|
|
require.NoError(t, tt.Start(&acc))
|
2020-03-27 22:40:08 +00:00
|
|
|
defer tt.Stop()
|
2019-09-23 22:39:50 +00:00
|
|
|
|
|
|
|
buf := &bytes.Buffer{}
|
|
|
|
log.SetOutput(buf)
|
|
|
|
|
2018-03-08 21:03:48 +00:00
|
|
|
require.NoError(t, acc.GatherError(tt.Gather))
|
2016-04-26 16:43:41 +00:00
|
|
|
|
|
|
|
_, err = tmpfile.WriteString("cpu mytag= foo usage_idle= 100\n")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2019-09-23 22:39:50 +00:00
|
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
assert.Contains(t, buf.String(), "Malformed log line")
|
2016-04-26 16:43:41 +00:00
|
|
|
}
|
2017-06-16 20:16:48 +00:00
|
|
|
|
|
|
|
func TestTailDosLineendings(t *testing.T) {
|
|
|
|
tmpfile, err := ioutil.TempFile("", "")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer os.Remove(tmpfile.Name())
|
2020-03-27 22:40:08 +00:00
|
|
|
defer tmpfile.Close()
|
2017-06-16 20:16:48 +00:00
|
|
|
_, err = tmpfile.WriteString("cpu usage_idle=100\r\ncpu2 usage_idle=200\r\n")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tt := NewTail()
|
2019-09-23 22:39:50 +00:00
|
|
|
tt.Log = testutil.Logger{}
|
2017-06-16 20:16:48 +00:00
|
|
|
tt.FromBeginning = true
|
|
|
|
tt.Files = []string{tmpfile.Name()}
|
2018-09-18 16:23:45 +00:00
|
|
|
tt.SetParserFunc(parsers.NewInfluxParser)
|
2020-03-27 22:40:08 +00:00
|
|
|
|
|
|
|
err = tt.Init()
|
|
|
|
require.NoError(t, err)
|
2017-06-16 20:16:48 +00:00
|
|
|
|
|
|
|
acc := testutil.Accumulator{}
|
|
|
|
require.NoError(t, tt.Start(&acc))
|
2020-03-27 22:40:08 +00:00
|
|
|
defer tt.Stop()
|
2017-06-16 20:16:48 +00:00
|
|
|
require.NoError(t, acc.GatherError(tt.Gather))
|
|
|
|
|
|
|
|
acc.Wait(2)
|
|
|
|
acc.AssertContainsFields(t, "cpu",
|
|
|
|
map[string]interface{}{
|
|
|
|
"usage_idle": float64(100),
|
|
|
|
})
|
|
|
|
acc.AssertContainsFields(t, "cpu2",
|
|
|
|
map[string]interface{}{
|
|
|
|
"usage_idle": float64(200),
|
|
|
|
})
|
|
|
|
}
|
2019-08-21 23:30:55 +00:00
|
|
|
|
|
|
|
// The csv parser should only parse the header line once per file.
|
|
|
|
func TestCSVHeadersParsedOnce(t *testing.T) {
|
|
|
|
tmpfile, err := ioutil.TempFile("", "")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
tmpfile.Close()
|
|
|
|
os.Remove(tmpfile.Name())
|
|
|
|
}()
|
|
|
|
|
|
|
|
_, err = tmpfile.WriteString(`
|
|
|
|
measurement,time_idle
|
|
|
|
cpu,42
|
|
|
|
cpu,42
|
|
|
|
`)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
plugin := NewTail()
|
2019-09-23 22:39:50 +00:00
|
|
|
plugin.Log = testutil.Logger{}
|
2019-08-21 23:30:55 +00:00
|
|
|
plugin.FromBeginning = true
|
|
|
|
plugin.Files = []string{tmpfile.Name()}
|
|
|
|
plugin.SetParserFunc(func() (parsers.Parser, error) {
|
|
|
|
return &csv.Parser{
|
|
|
|
MeasurementColumn: "measurement",
|
|
|
|
HeaderRowCount: 1,
|
|
|
|
TimeFunc: func() time.Time { return time.Unix(0, 0) },
|
|
|
|
}, nil
|
|
|
|
})
|
2020-03-27 22:40:08 +00:00
|
|
|
|
|
|
|
err = plugin.Init()
|
|
|
|
require.NoError(t, err)
|
2019-08-21 23:30:55 +00:00
|
|
|
|
|
|
|
acc := testutil.Accumulator{}
|
|
|
|
err = plugin.Start(&acc)
|
|
|
|
require.NoError(t, err)
|
2020-03-27 22:40:08 +00:00
|
|
|
defer plugin.Stop()
|
2019-08-21 23:30:55 +00:00
|
|
|
err = plugin.Gather(&acc)
|
|
|
|
require.NoError(t, err)
|
|
|
|
acc.Wait(2)
|
|
|
|
plugin.Stop()
|
|
|
|
|
|
|
|
expected := []telegraf.Metric{
|
|
|
|
testutil.MustMetric("cpu",
|
|
|
|
map[string]string{
|
|
|
|
"path": tmpfile.Name(),
|
|
|
|
},
|
|
|
|
map[string]interface{}{
|
2020-05-26 21:16:48 +00:00
|
|
|
"time_idle": 42,
|
2019-08-21 23:30:55 +00:00
|
|
|
},
|
|
|
|
time.Unix(0, 0)),
|
|
|
|
testutil.MustMetric("cpu",
|
|
|
|
map[string]string{
|
|
|
|
"path": tmpfile.Name(),
|
|
|
|
},
|
|
|
|
map[string]interface{}{
|
2020-05-26 21:16:48 +00:00
|
|
|
"time_idle": 42,
|
2019-08-21 23:30:55 +00:00
|
|
|
},
|
|
|
|
time.Unix(0, 0)),
|
|
|
|
}
|
|
|
|
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that the first line can produce multiple metrics (#6138)
|
|
|
|
func TestMultipleMetricsOnFirstLine(t *testing.T) {
|
|
|
|
tmpfile, err := ioutil.TempFile("", "")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer func() {
|
|
|
|
tmpfile.Close()
|
|
|
|
os.Remove(tmpfile.Name())
|
|
|
|
}()
|
|
|
|
|
|
|
|
_, err = tmpfile.WriteString(`
|
|
|
|
[{"time_idle": 42}, {"time_idle": 42}]
|
|
|
|
`)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
plugin := NewTail()
|
2019-09-23 22:39:50 +00:00
|
|
|
plugin.Log = testutil.Logger{}
|
2019-08-21 23:30:55 +00:00
|
|
|
plugin.FromBeginning = true
|
|
|
|
plugin.Files = []string{tmpfile.Name()}
|
|
|
|
plugin.SetParserFunc(func() (parsers.Parser, error) {
|
|
|
|
return json.New(
|
|
|
|
&json.Config{
|
|
|
|
MetricName: "cpu",
|
|
|
|
})
|
|
|
|
})
|
2020-03-27 22:40:08 +00:00
|
|
|
|
|
|
|
err = plugin.Init()
|
|
|
|
require.NoError(t, err)
|
2019-08-21 23:30:55 +00:00
|
|
|
|
|
|
|
acc := testutil.Accumulator{}
|
|
|
|
err = plugin.Start(&acc)
|
|
|
|
require.NoError(t, err)
|
2020-03-27 22:40:08 +00:00
|
|
|
defer plugin.Stop()
|
2019-08-21 23:30:55 +00:00
|
|
|
err = plugin.Gather(&acc)
|
|
|
|
require.NoError(t, err)
|
|
|
|
acc.Wait(2)
|
|
|
|
plugin.Stop()
|
|
|
|
|
|
|
|
expected := []telegraf.Metric{
|
|
|
|
testutil.MustMetric("cpu",
|
|
|
|
map[string]string{
|
|
|
|
"path": tmpfile.Name(),
|
|
|
|
},
|
|
|
|
map[string]interface{}{
|
|
|
|
"time_idle": 42.0,
|
|
|
|
},
|
|
|
|
time.Unix(0, 0)),
|
|
|
|
testutil.MustMetric("cpu",
|
|
|
|
map[string]string{
|
|
|
|
"path": tmpfile.Name(),
|
|
|
|
},
|
|
|
|
map[string]interface{}{
|
|
|
|
"time_idle": 42.0,
|
|
|
|
},
|
|
|
|
time.Unix(0, 0)),
|
|
|
|
}
|
|
|
|
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics(),
|
|
|
|
testutil.IgnoreTime())
|
|
|
|
}
|