Add threaded parsing in statsd input plugin (#6922)

This commit is contained in:
josephpeacock 2020-03-03 14:47:33 -08:00 committed by GitHub
parent f04d84994d
commit ab8438dcc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 88 additions and 17 deletions

View File

@ -31,6 +31,8 @@ const (
defaultSeparator = "_" defaultSeparator = "_"
defaultAllowPendingMessage = 10000 defaultAllowPendingMessage = 10000
MaxTCPConnections = 250 MaxTCPConnections = 250
parserGoRoutines = 5
) )
// Statsd allows the importing of statsd and dogstatsd data. // Statsd allows the importing of statsd and dogstatsd data.
@ -398,12 +400,14 @@ func (s *Statsd) Start(ac telegraf.Accumulator) error {
}() }()
} }
// Start the line parser for i := 1; i <= parserGoRoutines; i++ {
s.wg.Add(1) // Start the line parser
go func() { s.wg.Add(1)
defer s.wg.Done() go func() {
s.parser() defer s.wg.Done()
}() s.parser()
}()
}
s.Log.Infof("Started the statsd service on %q", s.ServiceAddress) s.Log.Infof("Started the statsd service on %q", s.ServiceAddress)
return nil return nil
} }

View File

@ -2,19 +2,21 @@ package statsd
import ( import (
"fmt" "fmt"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/internal"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"net" "net"
"sync"
"testing" "testing"
"time" "time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/internal"
"github.com/influxdata/telegraf/testutil" "github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
const ( const (
testMsg = "test.tcp.msg:100|c" testMsg = "test.tcp.msg:100|c"
producerThreads = 10
) )
func NewTestStatsd() *Statsd { func NewTestStatsd() *Statsd {
@ -137,15 +139,30 @@ func BenchmarkUDP(b *testing.B) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
for i := 0; i < 250000; i++ {
fmt.Fprintf(conn, testMsg) var wg sync.WaitGroup
for i := 1; i <= producerThreads; i++ {
wg.Add(1)
go sendRequests(conn, &wg)
} }
wg.Wait()
// wait for 250,000 metrics to get added to accumulator // wait for 250,000 metrics to get added to accumulator
time.Sleep(time.Millisecond) for len(listener.in) > 0 {
fmt.Printf("Left in buffer: %v \n", len(listener.in))
time.Sleep(time.Millisecond)
}
listener.Stop() listener.Stop()
} }
} }
func sendRequests(conn net.Conn, wg *sync.WaitGroup) {
defer wg.Done()
for i := 0; i < 25000; i++ {
fmt.Fprintf(conn, testMsg)
}
}
// benchmark how long it takes to accept & process 100,000 metrics: // benchmark how long it takes to accept & process 100,000 metrics:
func BenchmarkTCP(b *testing.B) { func BenchmarkTCP(b *testing.B) {
listener := Statsd{ listener := Statsd{
@ -169,11 +186,16 @@ func BenchmarkTCP(b *testing.B) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
for i := 0; i < 250000; i++ { var wg sync.WaitGroup
fmt.Fprintf(conn, testMsg) for i := 1; i <= producerThreads; i++ {
wg.Add(1)
go sendRequests(conn, &wg)
} }
wg.Wait()
// wait for 250,000 metrics to get added to accumulator // wait for 250,000 metrics to get added to accumulator
time.Sleep(time.Millisecond) for len(listener.in) > 0 {
time.Sleep(time.Millisecond)
}
listener.Stop() listener.Stop()
} }
} }
@ -1678,3 +1700,48 @@ func TestTCP(t *testing.T) {
testutil.IgnoreTime(), testutil.IgnoreTime(),
) )
} }
func TestUdp(t *testing.T) {
statsd := Statsd{
Log: testutil.Logger{},
Protocol: "udp",
ServiceAddress: "localhost:8125",
AllowedPendingMessages: 250000,
}
var acc testutil.Accumulator
require.NoError(t, statsd.Start(&acc))
defer statsd.Stop()
conn, err := net.Dial("udp", "127.0.0.1:8125")
_, err = conn.Write([]byte("cpu.time_idle:42|c\n"))
require.NoError(t, err)
err = conn.Close()
require.NoError(t, err)
for {
err = statsd.Gather(&acc)
require.NoError(t, err)
if len(acc.Metrics) > 0 {
break
}
}
testutil.RequireMetricsEqual(t,
[]telegraf.Metric{
testutil.MustMetric(
"cpu_time_idle",
map[string]string{
"metric_type": "counter",
},
map[string]interface{}{
"value": 42,
},
time.Now(),
telegraf.Counter,
),
},
acc.GetTelegrafMetrics(),
testutil.IgnoreTime(),
)
}