176 lines
4.3 KiB
Go
176 lines
4.3 KiB
Go
package stressClient
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
|
|
influx "github.com/influxdata/influxdb/client/v2"
|
|
)
|
|
|
|
// NewStressTest creates the backend for the stress test
|
|
func NewStressTest() *StressTest {
|
|
|
|
packageCh := make(chan Package, 0)
|
|
directiveCh := make(chan Directive, 0)
|
|
responseCh := make(chan Response, 0)
|
|
|
|
clnt, _ := influx.NewHTTPClient(influx.HTTPConfig{
|
|
Addr: fmt.Sprintf("http://%v/", "localhost:8086"),
|
|
})
|
|
|
|
s := &StressTest{
|
|
TestDB: "_stressTest",
|
|
Precision: "s",
|
|
StartDate: "2016-01-02",
|
|
BatchSize: 5000,
|
|
|
|
packageChan: packageCh,
|
|
directiveChan: directiveCh,
|
|
|
|
ResultsClient: clnt,
|
|
ResultsChan: responseCh,
|
|
communes: make(map[string]*commune),
|
|
TestID: randStr(10),
|
|
}
|
|
|
|
// Start the client service
|
|
startStressClient(packageCh, directiveCh, responseCh, s.TestID)
|
|
|
|
// Listen for Results coming in
|
|
s.resultsListen()
|
|
|
|
return s
|
|
}
|
|
|
|
// NewTestStressTest returns a StressTest to be used for testing Statements
|
|
func NewTestStressTest() (*StressTest, chan Package, chan Directive) {
|
|
|
|
packageCh := make(chan Package, 0)
|
|
directiveCh := make(chan Directive, 0)
|
|
|
|
s := &StressTest{
|
|
TestDB: "_stressTest",
|
|
Precision: "s",
|
|
StartDate: "2016-01-02",
|
|
BatchSize: 5000,
|
|
|
|
directiveChan: directiveCh,
|
|
packageChan: packageCh,
|
|
|
|
communes: make(map[string]*commune),
|
|
TestID: randStr(10),
|
|
}
|
|
|
|
return s, packageCh, directiveCh
|
|
}
|
|
|
|
// The StressTest is the Statement facing API that consumes Statement output and coordinates the test results
|
|
type StressTest struct {
|
|
TestID string
|
|
TestDB string
|
|
|
|
Precision string
|
|
StartDate string
|
|
BatchSize int
|
|
|
|
sync.WaitGroup
|
|
sync.Mutex
|
|
|
|
packageChan chan<- Package
|
|
directiveChan chan<- Directive
|
|
|
|
ResultsChan chan Response
|
|
communes map[string]*commune
|
|
ResultsClient influx.Client
|
|
}
|
|
|
|
// SendPackage is the public facing API for to send Queries and Points
|
|
func (st *StressTest) SendPackage(p Package) {
|
|
st.packageChan <- p
|
|
}
|
|
|
|
// SendDirective is the public facing API to set state variables in the test
|
|
func (st *StressTest) SendDirective(d Directive) {
|
|
st.directiveChan <- d
|
|
}
|
|
|
|
// Starts a go routine that listens for Results
|
|
func (st *StressTest) resultsListen() {
|
|
st.createDatabase(st.TestDB)
|
|
go func() {
|
|
bp := st.NewResultsPointBatch()
|
|
for resp := range st.ResultsChan {
|
|
switch resp.Point.Name() {
|
|
case "done":
|
|
st.ResultsClient.Write(bp)
|
|
resp.Tracer.Done()
|
|
default:
|
|
// Add the StressTest tags
|
|
pt, err := resp.AddTags(st.tags())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
// Add the point to the batch
|
|
bp = st.batcher(pt, bp)
|
|
resp.Tracer.Done()
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
// NewResultsPointBatch creates a new batch of points for the results
|
|
func (st *StressTest) NewResultsPointBatch() influx.BatchPoints {
|
|
bp, _ := influx.NewBatchPoints(influx.BatchPointsConfig{
|
|
Database: st.TestDB,
|
|
Precision: "ns",
|
|
})
|
|
return bp
|
|
}
|
|
|
|
// Batches incoming Result.Point and sends them if the batch reaches 5k in size
|
|
func (st *StressTest) batcher(pt *influx.Point, bp influx.BatchPoints) influx.BatchPoints {
|
|
if len(bp.Points()) <= 5000 {
|
|
bp.AddPoint(pt)
|
|
} else {
|
|
err := st.ResultsClient.Write(bp)
|
|
if err != nil {
|
|
log.Fatalf("Error writing performance stats\n error: %v\n", err)
|
|
}
|
|
bp = st.NewResultsPointBatch()
|
|
}
|
|
return bp
|
|
}
|
|
|
|
// Convinence database creation function
|
|
func (st *StressTest) createDatabase(db string) {
|
|
query := fmt.Sprintf("CREATE DATABASE %v", db)
|
|
res, err := st.ResultsClient.Query(influx.Query{Command: query})
|
|
if err != nil {
|
|
log.Fatalf("error: no running influx server at localhost:8086")
|
|
if res.Error() != nil {
|
|
log.Fatalf("error: no running influx server at localhost:8086")
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetStatementResults is a convinence function for fetching all results given a StatementID
|
|
func (st *StressTest) GetStatementResults(sID, t string) (res []influx.Result) {
|
|
qryStr := fmt.Sprintf(`SELECT * FROM "%v" WHERE statement_id = '%v'`, t, sID)
|
|
return st.queryTestResults(qryStr)
|
|
}
|
|
|
|
// Runs given qry on the test results database and returns the results or nil in case of error
|
|
func (st *StressTest) queryTestResults(qry string) (res []influx.Result) {
|
|
response, err := st.ResultsClient.Query(influx.Query{Command: qry, Database: st.TestDB})
|
|
if err == nil {
|
|
if response.Error() != nil {
|
|
log.Fatalf("Error sending results query\n error: %v\n", response.Error())
|
|
}
|
|
}
|
|
if response.Results[0].Series == nil {
|
|
return nil
|
|
}
|
|
return response.Results
|
|
}
|