boulder/test/load-generator/latency.go

87 lines
1.7 KiB
Go

package main
import (
"encoding/json"
"fmt"
"os"
"time"
)
type point struct {
Sent time.Time `json:"sent"`
Finished time.Time `json:"finished"`
Took int64 `json:"took"`
PType string `json:"type"`
Action string `json:"action"`
}
type latencyWriter interface {
Add(action string, sent, finished time.Time, pType string)
Close()
}
type latencyNoop struct{}
func (ln *latencyNoop) Add(_ string, _, _ time.Time, _ string) {}
func (ln *latencyNoop) Close() {}
type latencyFile struct {
metrics chan *point
output *os.File
stop chan struct{}
}
func newLatencyFile(filename string) (latencyWriter, error) {
if filename == "" {
return &latencyNoop{}, nil
}
fmt.Printf("[+] Opening results file %s\n", filename)
file, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND|os.O_CREATE, os.ModePerm)
if err != nil {
return nil, err
}
f := &latencyFile{
metrics: make(chan *point, 2048),
stop: make(chan struct{}, 1),
output: file,
}
go f.write()
return f, nil
}
func (f *latencyFile) write() {
for {
select {
case p := <-f.metrics:
data, err := json.Marshal(p)
if err != nil {
panic(err)
}
_, err = f.output.Write(append(data, []byte("\n")...))
if err != nil {
panic(err)
}
case <-f.stop:
return
}
}
}
// Add writes a point to the file
func (f *latencyFile) Add(action string, sent, finished time.Time, pType string) {
f.metrics <- &point{
Sent: sent,
Finished: finished,
Took: finished.Sub(sent).Nanoseconds(),
PType: pType,
Action: action,
}
}
// Close stops f.write() and closes the file, any remaining metrics will be discarded
func (f *latencyFile) Close() {
f.stop <- struct{}{}
_ = f.output.Close()
}